зеркало из https://github.com/mozilla/pjs.git
Bug 422538. Import libvorbis
This commit is contained in:
Родитель
49d7ffc394
Коммит
ddcb68fbed
|
@ -0,0 +1,3 @@
|
|||
Monty <monty@xiph.org>
|
||||
|
||||
and the rest of the Xiph.org Foundation.
|
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2002-2004 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 FOUNDATION
|
||||
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.
|
|
@ -0,0 +1,51 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = vorbis
|
||||
|
||||
DIRS = \
|
||||
include \
|
||||
lib \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,132 @@
|
|||
********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.org Foundation, http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
Vorbis is a general purpose audio and music encoding format
|
||||
contemporary to MPEG-4's AAC and TwinVQ, the next generation beyond
|
||||
MPEG audio layer 3. Unlike the MPEG sponsored formats (and other
|
||||
proprietary formats such as RealAudio G2 and Windows' flavor of the
|
||||
month), the Vorbis CODEC specification belongs to the public domain.
|
||||
All the technical details are published and documented, and any
|
||||
software entity may make full use of the format without license
|
||||
fee, royalty or patent concerns.
|
||||
|
||||
This package contains:
|
||||
|
||||
* libvorbis, a BSD-style license software implementation of
|
||||
the Vorbis specification by the Xiph.Org Foundation
|
||||
(http://www.xiph.org/)
|
||||
|
||||
* libvorbisfile, a BSD-style license convenience library
|
||||
built on Vorbis designed to simplify common uses
|
||||
|
||||
* libvorbisenc, a BSD-style license library that provides a simple,
|
||||
programmatic encoding setup interface
|
||||
|
||||
* example code making use of libogg, libvorbis, libvorbisfile and
|
||||
libvorbisenc
|
||||
|
||||
WHAT'S HERE:
|
||||
|
||||
This source distribution includes libvorbis and an example
|
||||
encoder/player to demonstrate use of libvorbis as well as
|
||||
documentation on the Ogg Vorbis audio coding format.
|
||||
|
||||
You'll need libogg (distributed separately) to compile this library.
|
||||
A more comprehensive set of utilities is available in the vorbis-tools
|
||||
package.
|
||||
|
||||
Directory:
|
||||
|
||||
./lib The source for the libraries, a BSD-license implementation
|
||||
of the public domain Ogg Vorbis audio encoding format.
|
||||
|
||||
./include Library API headers
|
||||
|
||||
./debian Rules/spec files for building Debian .deb packages
|
||||
|
||||
./doc Vorbis documentation
|
||||
|
||||
./examples Example code illustrating programmatic use of libvorbis,
|
||||
libvorbisfile and libvorbisenc
|
||||
|
||||
./mac Codewarrior project files and build tweaks for MacOS.
|
||||
|
||||
./macosx Project files for MacOS X.
|
||||
|
||||
./win32 Win32 projects files and build automation
|
||||
|
||||
./vq Internal utilities for training/building new LSP/residue
|
||||
and auxiliary codebooks.
|
||||
|
||||
CONTACT:
|
||||
|
||||
The Ogg homepage is located at 'http://www.xiph.org/ogg/'.
|
||||
Vorbis's homepage is located at 'http://www.xiph.org/vorbis/'.
|
||||
Up to date technical documents, contact information, source code and
|
||||
pre-built utilities may be found there.
|
||||
|
||||
The user website for Ogg Vorbis software and audio is http://vorbis.com/
|
||||
|
||||
BUILDING FROM TRUNK:
|
||||
|
||||
Development source is under subversion revision control at
|
||||
http://svn.xiph.org/trunk/vorbis/. You will also need the
|
||||
newest versions of autoconf, automake, and libtool in order
|
||||
to compile vorbis from development source. A configure script
|
||||
is provided for you in the source tarball distributions.
|
||||
|
||||
[update or checkout latest source]
|
||||
./autogen.sh
|
||||
make
|
||||
|
||||
and as root if desired:
|
||||
|
||||
make install
|
||||
|
||||
This will install the vorbis libraries (static and shared) into
|
||||
/usr/local/lib, includes into /usr/local/include and API manpages
|
||||
(once we write some) into /usr/local/man.
|
||||
|
||||
BUILDING FROM TARBALL DISTRIBUTIONS:
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
and optionally (as root):
|
||||
make install
|
||||
|
||||
BUILDING RPMS:
|
||||
|
||||
after normal configuring:
|
||||
|
||||
make dist
|
||||
rpm -ta libvorbis-<version>.tar.gz
|
||||
|
||||
BUILDING ON MACOS 9:
|
||||
|
||||
Vorbis on MacOS 9 is built using Metroworks CodeWarrior. To build it,
|
||||
first verify that the Ogg libraries are already built following the
|
||||
instructions in the Ogg module README. Open vorbis/mac/libvorbis.mcp,
|
||||
switch to the "Targets" pane, select everything, and make the project.
|
||||
Do the same thing to build libvorbisenc.mcp, and libvorbisfile.mcp (in
|
||||
that order). In vorbis/mac/Output you will now have both debug and final
|
||||
versions of Vorbis shared libraries to link your projects against.
|
||||
|
||||
To build a project using Ogg Vorbis, add access paths to your
|
||||
CodeWarrior project for the ogg/include, ogg/mac/Output,
|
||||
vorbis/include, and vorbis/mac/Output folders. Be sure that
|
||||
"interpret DOS and Unix paths" is turned on in your project; it can
|
||||
be found in the "access paths" pane in your project settings. Now
|
||||
simply add the shared libraries you need to your project (OggLib and
|
||||
VorbisLib at least) and #include "ogg/ogg.h" and "vorbis/codec.h"
|
||||
wherever you need to access Ogg and Vorbis functionality.
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
The source from this directory was copied from the libvorbis-1.2.0
|
||||
source distribution using the update.sh script. The only changes made
|
||||
were those applied by update.sh and the addition/upate of Makefile.in
|
||||
files for the Mozilla build system.
|
||||
|
||||
Some files are renamed during the copy to prevent clashes with object
|
||||
file names with other Mozilla libraries.
|
|
@ -0,0 +1,47 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = vorbis
|
||||
DIRS = vorbis
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,50 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = vorbis
|
||||
|
||||
EXPORTS = \
|
||||
codec.h \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,241 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _vorbis_codec_h_
|
||||
#define _vorbis_codec_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
typedef struct vorbis_info{
|
||||
int version;
|
||||
int channels;
|
||||
long rate;
|
||||
|
||||
/* The below bitrate declarations are *hints*.
|
||||
Combinations of the three values carry the following implications:
|
||||
|
||||
all three set to the same value:
|
||||
implies a fixed rate bitstream
|
||||
only nominal set:
|
||||
implies a VBR stream that averages the nominal bitrate. No hard
|
||||
upper/lower limit
|
||||
upper and or lower set:
|
||||
implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
may also be set to give a nominal rate.
|
||||
none set:
|
||||
the coder does not care to speculate.
|
||||
*/
|
||||
|
||||
long bitrate_upper;
|
||||
long bitrate_nominal;
|
||||
long bitrate_lower;
|
||||
long bitrate_window;
|
||||
|
||||
void *codec_setup;
|
||||
} vorbis_info;
|
||||
|
||||
/* vorbis_dsp_state buffers the current vorbis audio
|
||||
analysis/synthesis state. The DSP state belongs to a specific
|
||||
logical bitstream ****************************************************/
|
||||
typedef struct vorbis_dsp_state{
|
||||
int analysisp;
|
||||
vorbis_info *vi;
|
||||
|
||||
float **pcm;
|
||||
float **pcmret;
|
||||
int pcm_storage;
|
||||
int pcm_current;
|
||||
int pcm_returned;
|
||||
|
||||
int preextrapolate;
|
||||
int eofflag;
|
||||
|
||||
long lW;
|
||||
long W;
|
||||
long nW;
|
||||
long centerW;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
ogg_int64_t sequence;
|
||||
|
||||
ogg_int64_t glue_bits;
|
||||
ogg_int64_t time_bits;
|
||||
ogg_int64_t floor_bits;
|
||||
ogg_int64_t res_bits;
|
||||
|
||||
void *backend_state;
|
||||
} vorbis_dsp_state;
|
||||
|
||||
typedef struct vorbis_block{
|
||||
/* necessary stream state for linking to the framing abstraction */
|
||||
float **pcm; /* this is a pointer into local storage */
|
||||
oggpack_buffer opb;
|
||||
|
||||
long lW;
|
||||
long W;
|
||||
long nW;
|
||||
int pcmend;
|
||||
int mode;
|
||||
|
||||
int eofflag;
|
||||
ogg_int64_t granulepos;
|
||||
ogg_int64_t sequence;
|
||||
vorbis_dsp_state *vd; /* For read-only access of configuration */
|
||||
|
||||
/* local storage to avoid remallocing; it's up to the mapping to
|
||||
structure it */
|
||||
void *localstore;
|
||||
long localtop;
|
||||
long localalloc;
|
||||
long totaluse;
|
||||
struct alloc_chain *reap;
|
||||
|
||||
/* bitmetrics for the frame */
|
||||
long glue_bits;
|
||||
long time_bits;
|
||||
long floor_bits;
|
||||
long res_bits;
|
||||
|
||||
void *internal;
|
||||
|
||||
} vorbis_block;
|
||||
|
||||
/* vorbis_block is a single block of data to be processed as part of
|
||||
the analysis/synthesis stream; it belongs to a specific logical
|
||||
bitstream, but is independant from other vorbis_blocks belonging to
|
||||
that logical bitstream. *************************************************/
|
||||
|
||||
struct alloc_chain{
|
||||
void *ptr;
|
||||
struct alloc_chain *next;
|
||||
};
|
||||
|
||||
/* vorbis_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc). vorbis_info and substructures are in backends.h.
|
||||
*********************************************************************/
|
||||
|
||||
/* the comments are not part of vorbis_info so that vorbis_info can be
|
||||
static storage */
|
||||
typedef struct vorbis_comment{
|
||||
/* unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
whatever vendor is set to in encode */
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int comments;
|
||||
char *vendor;
|
||||
|
||||
} vorbis_comment;
|
||||
|
||||
|
||||
/* libvorbis encodes in two abstraction layers; first we perform DSP
|
||||
and produce a packet (see docs/analysis.txt). The packet is then
|
||||
coded into a framed OggSquish bitstream by the second layer (see
|
||||
docs/framing.txt). Decode is the reverse process; we sync/frame
|
||||
the bitstream and extract individual packets, then decode the
|
||||
packet back into PCM audio.
|
||||
|
||||
The extra framing/packetizing is used in streaming formats, such as
|
||||
files. Over the net (such as with UDP), the framing and
|
||||
packetization aren't necessary as they're provided by the transport
|
||||
and the streaming layer is not used */
|
||||
|
||||
/* Vorbis PRIMITIVES: general ***************************************/
|
||||
|
||||
extern void vorbis_info_init(vorbis_info *vi);
|
||||
extern void vorbis_info_clear(vorbis_info *vi);
|
||||
extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
|
||||
extern void vorbis_comment_init(vorbis_comment *vc);
|
||||
extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
|
||||
extern void vorbis_comment_add_tag(vorbis_comment *vc,
|
||||
char *tag, char *contents);
|
||||
extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
|
||||
extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
|
||||
extern void vorbis_comment_clear(vorbis_comment *vc);
|
||||
|
||||
extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
|
||||
extern int vorbis_block_clear(vorbis_block *vb);
|
||||
extern void vorbis_dsp_clear(vorbis_dsp_state *v);
|
||||
extern double vorbis_granule_time(vorbis_dsp_state *v,
|
||||
ogg_int64_t granulepos);
|
||||
|
||||
/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
|
||||
|
||||
extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op);
|
||||
extern int vorbis_analysis_headerout(vorbis_dsp_state *v,
|
||||
vorbis_comment *vc,
|
||||
ogg_packet *op,
|
||||
ogg_packet *op_comm,
|
||||
ogg_packet *op_code);
|
||||
extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op);
|
||||
|
||||
extern int vorbis_bitrate_addblock(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,
|
||||
ogg_packet *op);
|
||||
|
||||
/* Vorbis PRIMITIVES: synthesis layer *******************************/
|
||||
extern int vorbis_synthesis_idheader(ogg_packet *op);
|
||||
extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,
|
||||
ogg_packet *op);
|
||||
|
||||
extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_synthesis_restart(vorbis_dsp_state *v);
|
||||
extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
|
||||
extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op);
|
||||
extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
|
||||
extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm);
|
||||
extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
|
||||
extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
|
||||
|
||||
extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag);
|
||||
extern int vorbis_synthesis_halfrate_p(vorbis_info *v);
|
||||
|
||||
/* Vorbis ERRORS and return codes ***********************************/
|
||||
|
||||
#define OV_FALSE -1
|
||||
#define OV_EOF -2
|
||||
#define OV_HOLE -3
|
||||
|
||||
#define OV_EREAD -128
|
||||
#define OV_EFAULT -129
|
||||
#define OV_EIMPL -130
|
||||
#define OV_EINVAL -131
|
||||
#define OV_ENOTVORBIS -132
|
||||
#define OV_EBADHEADER -133
|
||||
#define OV_EVERSION -134
|
||||
#define OV_ENOTAUDIO -135
|
||||
#define OV_EBADPACKET -136
|
||||
#define OV_EBADLINK -137
|
||||
#define OV_ENOSEEK -138
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is Mozilla code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is the Mozilla Corporation.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2007
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
# Chris Double <chris.double@double.co.nz>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = vorbis
|
||||
LIBRARY_NAME = vorbis
|
||||
FORCE_STATIC_LIB= 1
|
||||
|
||||
CSRCS = \
|
||||
vorbis_mdct.c \
|
||||
vorbis_smallft.c \
|
||||
vorbis_block.c \
|
||||
vorbis_info.c \
|
||||
vorbis_envelope.c \
|
||||
vorbis_window.c \
|
||||
vorbis_lsp.c \
|
||||
vorbis_lpc.c \
|
||||
vorbis_analysis.c \
|
||||
vorbis_synthesis.c \
|
||||
vorbis_psy.c \
|
||||
vorbis_floor1.c \
|
||||
vorbis_floor0.c \
|
||||
vorbis_res0.c \
|
||||
vorbis_mapping0.c \
|
||||
vorbis_registry.c \
|
||||
vorbis_codebook.c \
|
||||
vorbis_sharedbook.c \
|
||||
vorbis_lookup.c \
|
||||
vorbis_bitrate.c \
|
||||
$(NULL)
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
|
@ -0,0 +1,146 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis backend and mapping structures; needed for
|
||||
static mode headers
|
||||
last mod: $Id: backends.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* this is exposed up here because we need it for static modes.
|
||||
Lookups for each backend aren't exposed because there's no reason
|
||||
to do so */
|
||||
|
||||
#ifndef _vorbis_backend_h_
|
||||
#define _vorbis_backend_h_
|
||||
|
||||
#include "codec_internal.h"
|
||||
|
||||
/* this would all be simpler/shorter with templates, but.... */
|
||||
/* Floor backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info_floor *,oggpack_buffer *);
|
||||
vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_floor *);
|
||||
void (*free_info) (vorbis_info_floor *);
|
||||
void (*free_look) (vorbis_look_floor *);
|
||||
void *(*inverse1) (struct vorbis_block *,vorbis_look_floor *);
|
||||
int (*inverse2) (struct vorbis_block *,vorbis_look_floor *,
|
||||
void *buffer,float *);
|
||||
} vorbis_func_floor;
|
||||
|
||||
typedef struct{
|
||||
int order;
|
||||
long rate;
|
||||
long barkmap;
|
||||
|
||||
int ampbits;
|
||||
int ampdB;
|
||||
|
||||
int numbooks; /* <= 16 */
|
||||
int books[16];
|
||||
|
||||
float lessthan; /* encode-only config setting hacks for libvorbis */
|
||||
float greaterthan; /* encode-only config setting hacks for libvorbis */
|
||||
|
||||
} vorbis_info_floor0;
|
||||
|
||||
|
||||
#define VIF_POSIT 63
|
||||
#define VIF_CLASS 16
|
||||
#define VIF_PARTS 31
|
||||
typedef struct{
|
||||
int partitions; /* 0 to 31 */
|
||||
int partitionclass[VIF_PARTS]; /* 0 to 15 */
|
||||
|
||||
int class_dim[VIF_CLASS]; /* 1 to 8 */
|
||||
int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */
|
||||
int class_book[VIF_CLASS]; /* subs ^ dim entries */
|
||||
int class_subbook[VIF_CLASS][8]; /* [VIF_CLASS][subs] */
|
||||
|
||||
|
||||
int mult; /* 1 2 3 or 4 */
|
||||
int postlist[VIF_POSIT+2]; /* first two implicit */
|
||||
|
||||
|
||||
/* encode side analysis parameters */
|
||||
float maxover;
|
||||
float maxunder;
|
||||
float maxerr;
|
||||
|
||||
float twofitweight;
|
||||
float twofitatten;
|
||||
|
||||
int n;
|
||||
|
||||
} vorbis_info_floor1;
|
||||
|
||||
/* Residue backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info_residue *,oggpack_buffer *);
|
||||
vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
vorbis_look_residue *(*look) (vorbis_dsp_state *,
|
||||
vorbis_info_residue *);
|
||||
void (*free_info) (vorbis_info_residue *);
|
||||
void (*free_look) (vorbis_look_residue *);
|
||||
long **(*class) (struct vorbis_block *,vorbis_look_residue *,
|
||||
float **,int *,int);
|
||||
int (*forward) (oggpack_buffer *,struct vorbis_block *,
|
||||
vorbis_look_residue *,
|
||||
float **,float **,int *,int,long **);
|
||||
int (*inverse) (struct vorbis_block *,vorbis_look_residue *,
|
||||
float **,int *,int);
|
||||
} vorbis_func_residue;
|
||||
|
||||
typedef struct vorbis_info_residue0{
|
||||
/* block-partitioned VQ coded straight residue */
|
||||
long begin;
|
||||
long end;
|
||||
|
||||
/* first stage (lossless partitioning) */
|
||||
int grouping; /* group n vectors per partition */
|
||||
int partitions; /* possible codebooks for a partition */
|
||||
int groupbook; /* huffbook for partitioning */
|
||||
int secondstages[64]; /* expanded out to pointers in lookup */
|
||||
int booklist[256]; /* list of second stage books */
|
||||
|
||||
float classmetric1[64];
|
||||
float classmetric2[64];
|
||||
|
||||
} vorbis_info_residue0;
|
||||
|
||||
/* Mapping backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info *,vorbis_info_mapping *,
|
||||
oggpack_buffer *);
|
||||
vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
void (*free_info) (vorbis_info_mapping *);
|
||||
int (*forward) (struct vorbis_block *vb);
|
||||
int (*inverse) (struct vorbis_block *vb,vorbis_info_mapping *);
|
||||
} vorbis_func_mapping;
|
||||
|
||||
typedef struct vorbis_info_mapping0{
|
||||
int submaps; /* <= 16 */
|
||||
int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */
|
||||
|
||||
int floorsubmap[16]; /* [mux] submap to floors */
|
||||
int residuesubmap[16]; /* [mux] submap to residue */
|
||||
|
||||
int coupling_steps;
|
||||
int coupling_mag[256];
|
||||
int coupling_ang[256];
|
||||
|
||||
} vorbis_info_mapping0;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
last mod: $Id: bitrate.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_BITRATE_H_
|
||||
#define _V_BITRATE_H_
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "os.h"
|
||||
|
||||
/* encode side bitrate tracking */
|
||||
typedef struct bitrate_manager_state {
|
||||
int managed;
|
||||
|
||||
long avg_reservoir;
|
||||
long minmax_reservoir;
|
||||
long avg_bitsper;
|
||||
long min_bitsper;
|
||||
long max_bitsper;
|
||||
|
||||
long short_per_long;
|
||||
double avgfloat;
|
||||
|
||||
vorbis_block *vb;
|
||||
int choice;
|
||||
} bitrate_manager_state;
|
||||
|
||||
typedef struct bitrate_manager_info{
|
||||
long avg_rate;
|
||||
long min_rate;
|
||||
long max_rate;
|
||||
long reservoir_bits;
|
||||
double reservoir_bias;
|
||||
|
||||
double slew_damp;
|
||||
|
||||
} bitrate_manager_info;
|
||||
|
||||
extern void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bs);
|
||||
extern void vorbis_bitrate_clear(bitrate_manager_state *bs);
|
||||
extern int vorbis_bitrate_managed(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_addblock(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, ogg_packet *op);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,160 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic shared codebook operations
|
||||
last mod: $Id: codebook.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_CODEBOOK_H_
|
||||
#define _V_CODEBOOK_H_
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
/* This structure encapsulates huffman and VQ style encoding books; it
|
||||
doesn't do anything specific to either.
|
||||
|
||||
valuelist/quantlist are nonNULL (and q_* significant) only if
|
||||
there's entry->value mapping to be done.
|
||||
|
||||
If encode-side mapping must be done (and thus the entry needs to be
|
||||
hunted), the auxiliary encode pointer will point to a decision
|
||||
tree. This is true of both VQ and huffman, but is mostly useful
|
||||
with VQ.
|
||||
|
||||
*/
|
||||
|
||||
typedef struct static_codebook{
|
||||
long dim; /* codebook dimensions (elements per vector) */
|
||||
long entries; /* codebook entries */
|
||||
long *lengthlist; /* codeword lengths in bits */
|
||||
|
||||
/* mapping ***************************************************************/
|
||||
int maptype; /* 0=none
|
||||
1=implicitly populated values from map column
|
||||
2=listed arbitrary values */
|
||||
|
||||
/* The below does a linear, single monotonic sequence mapping. */
|
||||
long q_min; /* packed 32 bit float; quant value 0 maps to minval */
|
||||
long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */
|
||||
int q_quant; /* bits: 0 < quant <= 16 */
|
||||
int q_sequencep; /* bitflag */
|
||||
|
||||
long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map
|
||||
map == 2: list of dim*entries quantized entry vals
|
||||
*/
|
||||
|
||||
/* encode helpers ********************************************************/
|
||||
struct encode_aux_nearestmatch *nearest_tree;
|
||||
struct encode_aux_threshmatch *thresh_tree;
|
||||
struct encode_aux_pigeonhole *pigeon_tree;
|
||||
|
||||
int allocedp;
|
||||
} static_codebook;
|
||||
|
||||
/* this structures an arbitrary trained book to quickly find the
|
||||
nearest cell match */
|
||||
typedef struct encode_aux_nearestmatch{
|
||||
/* pre-calculated partitioning tree */
|
||||
long *ptr0;
|
||||
long *ptr1;
|
||||
|
||||
long *p; /* decision points (each is an entry) */
|
||||
long *q; /* decision points (each is an entry) */
|
||||
long aux; /* number of tree entries */
|
||||
long alloc;
|
||||
} encode_aux_nearestmatch;
|
||||
|
||||
/* assumes a maptype of 1; encode side only, so that's OK */
|
||||
typedef struct encode_aux_threshmatch{
|
||||
float *quantthresh;
|
||||
long *quantmap;
|
||||
int quantvals;
|
||||
int threshvals;
|
||||
} encode_aux_threshmatch;
|
||||
|
||||
typedef struct encode_aux_pigeonhole{
|
||||
float min;
|
||||
float del;
|
||||
|
||||
int mapentries;
|
||||
int quantvals;
|
||||
long *pigeonmap;
|
||||
|
||||
long fittotal;
|
||||
long *fitlist;
|
||||
long *fitmap;
|
||||
long *fitlength;
|
||||
} encode_aux_pigeonhole;
|
||||
|
||||
typedef struct codebook{
|
||||
long dim; /* codebook dimensions (elements per vector) */
|
||||
long entries; /* codebook entries */
|
||||
long used_entries; /* populated codebook entries */
|
||||
const static_codebook *c;
|
||||
|
||||
/* for encode, the below are entry-ordered, fully populated */
|
||||
/* for decode, the below are ordered by bitreversed codeword and only
|
||||
used entries are populated */
|
||||
float *valuelist; /* list of dim*entries actual entry values */
|
||||
ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */
|
||||
|
||||
int *dec_index; /* only used if sparseness collapsed */
|
||||
char *dec_codelengths;
|
||||
ogg_uint32_t *dec_firsttable;
|
||||
int dec_firsttablen;
|
||||
int dec_maxlength;
|
||||
|
||||
} codebook;
|
||||
|
||||
extern void vorbis_staticbook_clear(static_codebook *b);
|
||||
extern void vorbis_staticbook_destroy(static_codebook *b);
|
||||
extern int vorbis_book_init_encode(codebook *dest,const static_codebook *source);
|
||||
extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source);
|
||||
extern void vorbis_book_clear(codebook *b);
|
||||
|
||||
extern float *_book_unquantize(const static_codebook *b,int n,int *map);
|
||||
extern float *_book_logdist(const static_codebook *b,float *vals);
|
||||
extern float _float32_unpack(long val);
|
||||
extern long _float32_pack(float val);
|
||||
extern int _best(codebook *book, float *a, int step);
|
||||
extern int _ilog(unsigned int v);
|
||||
extern long _book_maptype1_quantvals(const static_codebook *b);
|
||||
|
||||
extern int vorbis_book_besterror(codebook *book,float *a,int step,int addmul);
|
||||
extern long vorbis_book_codeword(codebook *book,int entry);
|
||||
extern long vorbis_book_codelen(codebook *book,int entry);
|
||||
|
||||
|
||||
|
||||
extern int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b);
|
||||
extern int vorbis_staticbook_unpack(oggpack_buffer *b,static_codebook *c);
|
||||
|
||||
extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b);
|
||||
extern int vorbis_book_errorv(codebook *book, float *a);
|
||||
extern int vorbis_book_encodev(codebook *book, int best,float *a,
|
||||
oggpack_buffer *b);
|
||||
|
||||
extern long vorbis_book_decode(codebook *book, oggpack_buffer *b);
|
||||
extern long vorbis_book_decodevs_add(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodev_set(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodev_add(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodevv_add(codebook *book, float **a,
|
||||
long off,int ch,
|
||||
oggpack_buffer *b,int n);
|
||||
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,137 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec_internal.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_CODECI_H_
|
||||
#define _V_CODECI_H_
|
||||
|
||||
#include "envelope.h"
|
||||
#include "codebook.h"
|
||||
|
||||
#define BLOCKTYPE_IMPULSE 0
|
||||
#define BLOCKTYPE_PADDING 1
|
||||
#define BLOCKTYPE_TRANSITION 0
|
||||
#define BLOCKTYPE_LONG 1
|
||||
|
||||
#define PACKETBLOBS 15
|
||||
|
||||
typedef struct vorbis_block_internal{
|
||||
float **pcmdelay; /* this is a pointer into local storage */
|
||||
float ampmax;
|
||||
int blocktype;
|
||||
|
||||
oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed;
|
||||
blob [PACKETBLOBS/2] points to
|
||||
the oggpack_buffer in the
|
||||
main vorbis_block */
|
||||
} vorbis_block_internal;
|
||||
|
||||
typedef void vorbis_look_floor;
|
||||
typedef void vorbis_look_residue;
|
||||
typedef void vorbis_look_transform;
|
||||
|
||||
/* mode ************************************************************/
|
||||
typedef struct {
|
||||
int blockflag;
|
||||
int windowtype;
|
||||
int transformtype;
|
||||
int mapping;
|
||||
} vorbis_info_mode;
|
||||
|
||||
typedef void vorbis_info_floor;
|
||||
typedef void vorbis_info_residue;
|
||||
typedef void vorbis_info_mapping;
|
||||
|
||||
#include "psy.h"
|
||||
#include "bitrate.h"
|
||||
|
||||
typedef struct private_state {
|
||||
/* local lookup storage */
|
||||
envelope_lookup *ve; /* envelope lookup */
|
||||
int window[2];
|
||||
vorbis_look_transform **transform[2]; /* block, type */
|
||||
drft_lookup fft_look[2];
|
||||
|
||||
int modebits;
|
||||
vorbis_look_floor **flr;
|
||||
vorbis_look_residue **residue;
|
||||
vorbis_look_psy *psy;
|
||||
vorbis_look_psy_global *psy_g_look;
|
||||
|
||||
/* local storage, only used on the encoding side. This way the
|
||||
application does not need to worry about freeing some packets'
|
||||
memory and not others'; packet storage is always tracked.
|
||||
Cleared next call to a _dsp_ function */
|
||||
unsigned char *header;
|
||||
unsigned char *header1;
|
||||
unsigned char *header2;
|
||||
|
||||
bitrate_manager_state bms;
|
||||
|
||||
ogg_int64_t sample_count;
|
||||
} private_state;
|
||||
|
||||
/* codec_setup_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc).
|
||||
*********************************************************************/
|
||||
|
||||
#include "highlevel.h"
|
||||
typedef struct codec_setup_info {
|
||||
|
||||
/* Vorbis supports only short and long blocks, but allows the
|
||||
encoder to choose the sizes */
|
||||
|
||||
long blocksizes[2];
|
||||
|
||||
/* modes are the primary means of supporting on-the-fly different
|
||||
blocksizes, different channel mappings (LR or M/A),
|
||||
different residue backends, etc. Each mode consists of a
|
||||
blocksize flag and a mapping (along with the mapping setup */
|
||||
|
||||
int modes;
|
||||
int maps;
|
||||
int floors;
|
||||
int residues;
|
||||
int books;
|
||||
int psys; /* encode only */
|
||||
|
||||
vorbis_info_mode *mode_param[64];
|
||||
int map_type[64];
|
||||
vorbis_info_mapping *map_param[64];
|
||||
int floor_type[64];
|
||||
vorbis_info_floor *floor_param[64];
|
||||
int residue_type[64];
|
||||
vorbis_info_residue *residue_param[64];
|
||||
static_codebook *book_param[256];
|
||||
codebook *fullbooks;
|
||||
|
||||
vorbis_info_psy *psy_param[4]; /* encode only */
|
||||
vorbis_info_psy_global psy_g_param;
|
||||
|
||||
bitrate_manager_info bi;
|
||||
highlevel_encode_setup hi; /* used only by vorbisenc.c. It's a
|
||||
highly redundant structure, but
|
||||
improves clarity of program flow. */
|
||||
int halfrate_flag; /* painless downsample for decode */
|
||||
} codec_setup_info;
|
||||
|
||||
extern vorbis_look_psy_global *_vp_global_look(vorbis_info *vi);
|
||||
extern void _vp_global_free(vorbis_look_psy_global *look);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis and manipulation
|
||||
last mod: $Id: envelope.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_ENVELOPE_
|
||||
#define _V_ENVELOPE_
|
||||
|
||||
#include "mdct.h"
|
||||
|
||||
#define VE_PRE 16
|
||||
#define VE_WIN 4
|
||||
#define VE_POST 2
|
||||
#define VE_AMP (VE_PRE+VE_POST-1)
|
||||
|
||||
#define VE_BANDS 7
|
||||
#define VE_NEARDC 15
|
||||
|
||||
#define VE_MINSTRETCH 2 /* a bit less than short block */
|
||||
#define VE_MAXSTRETCH 12 /* one-third full block */
|
||||
|
||||
typedef struct {
|
||||
float ampbuf[VE_AMP];
|
||||
int ampptr;
|
||||
|
||||
float nearDC[VE_NEARDC];
|
||||
float nearDC_acc;
|
||||
float nearDC_partialacc;
|
||||
int nearptr;
|
||||
|
||||
} envelope_filter_state;
|
||||
|
||||
typedef struct {
|
||||
int begin;
|
||||
int end;
|
||||
float *window;
|
||||
float total;
|
||||
} envelope_band;
|
||||
|
||||
typedef struct {
|
||||
int ch;
|
||||
int winlength;
|
||||
int searchstep;
|
||||
float minenergy;
|
||||
|
||||
mdct_lookup mdct;
|
||||
float *mdct_win;
|
||||
|
||||
envelope_band band[VE_BANDS];
|
||||
envelope_filter_state *filter;
|
||||
int stretch;
|
||||
|
||||
int *mark;
|
||||
|
||||
long storage;
|
||||
long current;
|
||||
long curmark;
|
||||
long cursor;
|
||||
} envelope_lookup;
|
||||
|
||||
extern void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi);
|
||||
extern void _ve_envelope_clear(envelope_lookup *e);
|
||||
extern long _ve_envelope_search(vorbis_dsp_state *v);
|
||||
extern void _ve_envelope_shift(envelope_lookup *e,long shift);
|
||||
extern int _ve_envelope_mark(vorbis_dsp_state *v);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: highlevel encoder setup struct seperated out for vorbisenc clarity
|
||||
last mod: $Id: highlevel.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
typedef struct highlevel_byblocktype {
|
||||
double tone_mask_setting;
|
||||
double tone_peaklimit_setting;
|
||||
double noise_bias_setting;
|
||||
double noise_compand_setting;
|
||||
} highlevel_byblocktype;
|
||||
|
||||
typedef struct highlevel_encode_setup {
|
||||
void *setup;
|
||||
int set_in_stone;
|
||||
|
||||
double base_setting;
|
||||
double long_setting;
|
||||
double short_setting;
|
||||
double impulse_noisetune;
|
||||
|
||||
int managed;
|
||||
long bitrate_min;
|
||||
long bitrate_av;
|
||||
double bitrate_av_damp;
|
||||
long bitrate_max;
|
||||
long bitrate_reservoir;
|
||||
double bitrate_reservoir_bias;
|
||||
|
||||
int impulse_block_p;
|
||||
int noise_normalize_p;
|
||||
|
||||
double stereo_point_setting;
|
||||
double lowpass_kHz;
|
||||
|
||||
double ath_floating_dB;
|
||||
double ath_absolute_dB;
|
||||
|
||||
double amplitude_track_dBpersec;
|
||||
double trigger_setting;
|
||||
|
||||
highlevel_byblocktype block[4]; /* padding, impulse, transition, long */
|
||||
|
||||
} highlevel_encode_setup;
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
last mod: $Id: lookup.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
extern float vorbis_coslook(float a);
|
||||
extern float vorbis_invsqlook(float a);
|
||||
extern float vorbis_invsq2explook(int a);
|
||||
extern float vorbis_fromdBlook(float a);
|
||||
#endif
|
||||
#ifdef INT_LOOKUP
|
||||
extern long vorbis_invsqlook_i(long a,long e);
|
||||
extern long vorbis_coslook_i(long a);
|
||||
extern float vorbis_fromdBlook_i(long a);
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,189 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup data; generated by lookups.pl; edit there
|
||||
last mod: $Id: lookup_data.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_DATA_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
#define COS_LOOKUP_SZ 128
|
||||
static float COS_LOOKUP[COS_LOOKUP_SZ+1]={
|
||||
+1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f,
|
||||
+0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f,
|
||||
+0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f,
|
||||
+0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f,
|
||||
+0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f,
|
||||
+0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f,
|
||||
+0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f,
|
||||
+0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f,
|
||||
+0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f,
|
||||
+0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f,
|
||||
+0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f,
|
||||
+0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f,
|
||||
+0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f,
|
||||
+0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f,
|
||||
+0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f,
|
||||
+0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f,
|
||||
+0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f,
|
||||
-0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f,
|
||||
-0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f,
|
||||
-0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f,
|
||||
-0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f,
|
||||
-0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f,
|
||||
-0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f,
|
||||
-0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f,
|
||||
-0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f,
|
||||
-0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f,
|
||||
-0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f,
|
||||
-0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f,
|
||||
-0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f,
|
||||
-0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f,
|
||||
-0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f,
|
||||
-0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f,
|
||||
-1.0000000000000f,
|
||||
};
|
||||
|
||||
#define INVSQ_LOOKUP_SZ 32
|
||||
static float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={
|
||||
1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f,
|
||||
1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f,
|
||||
1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f,
|
||||
1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f,
|
||||
1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f,
|
||||
1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f,
|
||||
1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f,
|
||||
1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f,
|
||||
1.000000000000f,
|
||||
};
|
||||
|
||||
#define INVSQ2EXP_LOOKUP_MIN (-32)
|
||||
#define INVSQ2EXP_LOOKUP_MAX 32
|
||||
static float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\
|
||||
INVSQ2EXP_LOOKUP_MIN+1]={
|
||||
65536.f, 46340.95001f, 32768.f, 23170.47501f,
|
||||
16384.f, 11585.2375f, 8192.f, 5792.618751f,
|
||||
4096.f, 2896.309376f, 2048.f, 1448.154688f,
|
||||
1024.f, 724.0773439f, 512.f, 362.038672f,
|
||||
256.f, 181.019336f, 128.f, 90.50966799f,
|
||||
64.f, 45.254834f, 32.f, 22.627417f,
|
||||
16.f, 11.3137085f, 8.f, 5.656854249f,
|
||||
4.f, 2.828427125f, 2.f, 1.414213562f,
|
||||
1.f, 0.7071067812f, 0.5f, 0.3535533906f,
|
||||
0.25f, 0.1767766953f, 0.125f, 0.08838834765f,
|
||||
0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f,
|
||||
0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f,
|
||||
0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f,
|
||||
0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f,
|
||||
0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f,
|
||||
6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f,
|
||||
1.525878906e-05f,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#define FROMdB_LOOKUP_SZ 35
|
||||
#define FROMdB2_LOOKUP_SZ 32
|
||||
#define FROMdB_SHIFT 5
|
||||
#define FROMdB2_SHIFT 3
|
||||
#define FROMdB2_MASK 31
|
||||
static float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={
|
||||
1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f,
|
||||
0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f,
|
||||
0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f,
|
||||
0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f,
|
||||
0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f,
|
||||
0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f,
|
||||
1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f,
|
||||
2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f,
|
||||
3.981071706e-07f,2.511886432e-07f,1.584893192e-07f,
|
||||
};
|
||||
|
||||
static float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={
|
||||
0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f,
|
||||
0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f,
|
||||
0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f,
|
||||
0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f,
|
||||
0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f,
|
||||
0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f,
|
||||
0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f,
|
||||
0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f,
|
||||
};
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
|
||||
#define INVSQ_LOOKUP_I_SHIFT 10
|
||||
#define INVSQ_LOOKUP_I_MASK 1023
|
||||
static long INVSQ_LOOKUP_I[64+1]={
|
||||
92682l, 91966l, 91267l, 90583l,
|
||||
89915l, 89261l, 88621l, 87995l,
|
||||
87381l, 86781l, 86192l, 85616l,
|
||||
85051l, 84497l, 83953l, 83420l,
|
||||
82897l, 82384l, 81880l, 81385l,
|
||||
80899l, 80422l, 79953l, 79492l,
|
||||
79039l, 78594l, 78156l, 77726l,
|
||||
77302l, 76885l, 76475l, 76072l,
|
||||
75674l, 75283l, 74898l, 74519l,
|
||||
74146l, 73778l, 73415l, 73058l,
|
||||
72706l, 72359l, 72016l, 71679l,
|
||||
71347l, 71019l, 70695l, 70376l,
|
||||
70061l, 69750l, 69444l, 69141l,
|
||||
68842l, 68548l, 68256l, 67969l,
|
||||
67685l, 67405l, 67128l, 66855l,
|
||||
66585l, 66318l, 66054l, 65794l,
|
||||
65536l,
|
||||
};
|
||||
|
||||
#define COS_LOOKUP_I_SHIFT 9
|
||||
#define COS_LOOKUP_I_MASK 511
|
||||
#define COS_LOOKUP_I_SZ 128
|
||||
static long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={
|
||||
16384l, 16379l, 16364l, 16340l,
|
||||
16305l, 16261l, 16207l, 16143l,
|
||||
16069l, 15986l, 15893l, 15791l,
|
||||
15679l, 15557l, 15426l, 15286l,
|
||||
15137l, 14978l, 14811l, 14635l,
|
||||
14449l, 14256l, 14053l, 13842l,
|
||||
13623l, 13395l, 13160l, 12916l,
|
||||
12665l, 12406l, 12140l, 11866l,
|
||||
11585l, 11297l, 11003l, 10702l,
|
||||
10394l, 10080l, 9760l, 9434l,
|
||||
9102l, 8765l, 8423l, 8076l,
|
||||
7723l, 7366l, 7005l, 6639l,
|
||||
6270l, 5897l, 5520l, 5139l,
|
||||
4756l, 4370l, 3981l, 3590l,
|
||||
3196l, 2801l, 2404l, 2006l,
|
||||
1606l, 1205l, 804l, 402l,
|
||||
0l, -401l, -803l, -1204l,
|
||||
-1605l, -2005l, -2403l, -2800l,
|
||||
-3195l, -3589l, -3980l, -4369l,
|
||||
-4755l, -5138l, -5519l, -5896l,
|
||||
-6269l, -6638l, -7004l, -7365l,
|
||||
-7722l, -8075l, -8422l, -8764l,
|
||||
-9101l, -9433l, -9759l, -10079l,
|
||||
-10393l, -10701l, -11002l, -11296l,
|
||||
-11584l, -11865l, -12139l, -12405l,
|
||||
-12664l, -12915l, -13159l, -13394l,
|
||||
-13622l, -13841l, -14052l, -14255l,
|
||||
-14448l, -14634l, -14810l, -14977l,
|
||||
-15136l, -15285l, -15425l, -15556l,
|
||||
-15678l, -15790l, -15892l, -15985l,
|
||||
-16068l, -16142l, -16206l, -16260l,
|
||||
-16304l, -16339l, -16363l, -16378l,
|
||||
-16383l,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,29 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
last mod: $Id: lpc.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LPC_H_
|
||||
#define _V_LPC_H_
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
|
||||
/* simple linear scale LPC code */
|
||||
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
|
||||
|
||||
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||
float *data,long n);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,28 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LSP (also called LSF) conversion routines
|
||||
last mod: $Id: lsp.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
|
||||
#ifndef _V_LSP_H_
|
||||
#define _V_LSP_H_
|
||||
|
||||
extern int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m);
|
||||
|
||||
extern void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,
|
||||
float *lsp,int m,
|
||||
float amp,float ampoffset);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,785 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: masking curve data for psychoacoustics
|
||||
last mod: $Id: masking.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_MASKING_H_
|
||||
#define _V_MASKING_H_
|
||||
|
||||
/* more detailed ATH; the bass if flat to save stressing the floor
|
||||
overly for only a bin or two of savings. */
|
||||
|
||||
#define MAX_ATH 88
|
||||
static float ATH[]={
|
||||
/*15*/ -51, -52, -53, -54, -55, -56, -57, -58,
|
||||
/*31*/ -59, -60, -61, -62, -63, -64, -65, -66,
|
||||
/*63*/ -67, -68, -69, -70, -71, -72, -73, -74,
|
||||
/*125*/ -75, -76, -77, -78, -80, -81, -82, -83,
|
||||
/*250*/ -84, -85, -86, -87, -88, -88, -89, -89,
|
||||
/*500*/ -90, -91, -91, -92, -93, -94, -95, -96,
|
||||
/*1k*/ -96, -97, -98, -98, -99, -99,-100,-100,
|
||||
/*2k*/ -101,-102,-103,-104,-106,-107,-107,-107,
|
||||
/*4k*/ -107,-105,-103,-102,-101, -99, -98, -96,
|
||||
/*8k*/ -95, -95, -96, -97, -96, -95, -93, -90,
|
||||
/*16k*/ -80, -70, -50, -40, -30, -30, -30, -30
|
||||
};
|
||||
|
||||
/* The tone masking curves from Ehmer's and Fielder's papers have been
|
||||
replaced by an empirically collected data set. The previously
|
||||
published values were, far too often, simply on crack. */
|
||||
|
||||
#define EHMER_OFFSET 16
|
||||
#define EHMER_MAX 56
|
||||
|
||||
/* masking tones from -50 to 0dB, 62.5 through 16kHz at half octaves
|
||||
test tones from -2 octaves to +5 octaves sampled at eighth octaves */
|
||||
/* (Vorbis 0dB, the loudest possible tone, is assumed to be ~100dB SPL
|
||||
for collection of these curves) */
|
||||
|
||||
static float tonemasks[P_BANDS][6][EHMER_MAX]={
|
||||
/* 62.5 Hz */
|
||||
{{ -60, -60, -60, -60, -60, -60, -60, -60,
|
||||
-60, -60, -60, -60, -62, -62, -65, -73,
|
||||
-69, -68, -68, -67, -70, -70, -72, -74,
|
||||
-75, -79, -79, -80, -83, -88, -93, -100,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -48, -48, -48, -48, -48, -48, -48, -48,
|
||||
-48, -48, -48, -48, -48, -53, -61, -66,
|
||||
-66, -68, -67, -70, -76, -76, -72, -73,
|
||||
-75, -76, -78, -79, -83, -88, -93, -100,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -37, -37, -37, -37, -37, -37, -37, -37,
|
||||
-38, -40, -42, -46, -48, -53, -55, -62,
|
||||
-65, -58, -56, -56, -61, -60, -65, -67,
|
||||
-69, -71, -77, -77, -78, -80, -82, -84,
|
||||
-88, -93, -98, -106, -112, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -25, -25, -25, -25, -25, -25, -25, -25,
|
||||
-25, -26, -27, -29, -32, -38, -48, -52,
|
||||
-52, -50, -48, -48, -51, -52, -54, -60,
|
||||
-67, -67, -66, -68, -69, -73, -73, -76,
|
||||
-80, -81, -81, -85, -85, -86, -88, -93,
|
||||
-100, -110, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -16, -16, -16, -16, -16, -16, -16, -16,
|
||||
-17, -19, -20, -22, -26, -28, -31, -40,
|
||||
-47, -39, -39, -40, -42, -43, -47, -51,
|
||||
-57, -52, -55, -55, -60, -58, -62, -63,
|
||||
-70, -67, -69, -72, -73, -77, -80, -82,
|
||||
-83, -87, -90, -94, -98, -104, -115, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -8, -8, -8, -8, -8, -8, -8, -8,
|
||||
-8, -8, -10, -11, -15, -19, -25, -30,
|
||||
-34, -31, -30, -31, -29, -32, -35, -42,
|
||||
-48, -42, -44, -46, -50, -50, -51, -52,
|
||||
-59, -54, -55, -55, -58, -62, -63, -66,
|
||||
-72, -73, -76, -75, -78, -80, -80, -81,
|
||||
-84, -88, -90, -94, -98, -101, -106, -110}},
|
||||
/* 88Hz */
|
||||
{{ -66, -66, -66, -66, -66, -66, -66, -66,
|
||||
-66, -66, -66, -66, -66, -67, -67, -67,
|
||||
-76, -72, -71, -74, -76, -76, -75, -78,
|
||||
-79, -79, -81, -83, -86, -89, -93, -97,
|
||||
-100, -105, -110, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -47, -47, -47, -47, -47, -47, -47, -47,
|
||||
-47, -47, -47, -48, -51, -55, -59, -66,
|
||||
-66, -66, -67, -66, -68, -69, -70, -74,
|
||||
-79, -77, -77, -78, -80, -81, -82, -84,
|
||||
-86, -88, -91, -95, -100, -108, -116, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -36, -36, -36, -36, -36, -36, -36, -36,
|
||||
-36, -37, -37, -41, -44, -48, -51, -58,
|
||||
-62, -60, -57, -59, -59, -60, -63, -65,
|
||||
-72, -71, -70, -72, -74, -77, -76, -78,
|
||||
-81, -81, -80, -83, -86, -91, -96, -100,
|
||||
-105, -110, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -28, -28, -28, -28, -28, -28, -28, -28,
|
||||
-28, -30, -32, -32, -33, -35, -41, -49,
|
||||
-50, -49, -47, -48, -48, -52, -51, -57,
|
||||
-65, -61, -59, -61, -64, -69, -70, -74,
|
||||
-77, -77, -78, -81, -84, -85, -87, -90,
|
||||
-92, -96, -100, -107, -112, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -19, -19, -19, -19, -19, -19, -19, -19,
|
||||
-20, -21, -23, -27, -30, -35, -36, -41,
|
||||
-46, -44, -42, -40, -41, -41, -43, -48,
|
||||
-55, -53, -52, -53, -56, -59, -58, -60,
|
||||
-67, -66, -69, -71, -72, -75, -79, -81,
|
||||
-84, -87, -90, -93, -97, -101, -107, -114,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -9, -9, -9, -9, -9, -9, -9, -9,
|
||||
-11, -12, -12, -15, -16, -20, -23, -30,
|
||||
-37, -34, -33, -34, -31, -32, -32, -38,
|
||||
-47, -44, -41, -40, -47, -49, -46, -46,
|
||||
-58, -50, -50, -54, -58, -62, -64, -67,
|
||||
-67, -70, -72, -76, -79, -83, -87, -91,
|
||||
-96, -100, -104, -110, -999, -999, -999, -999}},
|
||||
/* 125 Hz */
|
||||
{{ -62, -62, -62, -62, -62, -62, -62, -62,
|
||||
-62, -62, -63, -64, -66, -67, -66, -68,
|
||||
-75, -72, -76, -75, -76, -78, -79, -82,
|
||||
-84, -85, -90, -94, -101, -110, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -59, -59, -59, -59, -59, -59, -59, -59,
|
||||
-59, -59, -59, -60, -60, -61, -63, -66,
|
||||
-71, -68, -70, -70, -71, -72, -72, -75,
|
||||
-81, -78, -79, -82, -83, -86, -90, -97,
|
||||
-103, -113, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -53, -53, -53, -53, -53, -53, -53, -53,
|
||||
-53, -54, -55, -57, -56, -57, -55, -61,
|
||||
-65, -60, -60, -62, -63, -63, -66, -68,
|
||||
-74, -73, -75, -75, -78, -80, -80, -82,
|
||||
-85, -90, -96, -101, -108, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -46, -46, -46, -46, -46, -46, -46, -46,
|
||||
-46, -46, -47, -47, -47, -47, -48, -51,
|
||||
-57, -51, -49, -50, -51, -53, -54, -59,
|
||||
-66, -60, -62, -67, -67, -70, -72, -75,
|
||||
-76, -78, -81, -85, -88, -94, -97, -104,
|
||||
-112, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -36, -36, -36, -36, -36, -36, -36, -36,
|
||||
-39, -41, -42, -42, -39, -38, -41, -43,
|
||||
-52, -44, -40, -39, -37, -37, -40, -47,
|
||||
-54, -50, -48, -50, -55, -61, -59, -62,
|
||||
-66, -66, -66, -69, -69, -73, -74, -74,
|
||||
-75, -77, -79, -82, -87, -91, -95, -100,
|
||||
-108, -115, -999, -999, -999, -999, -999, -999},
|
||||
{ -28, -26, -24, -22, -20, -20, -23, -29,
|
||||
-30, -31, -28, -27, -28, -28, -28, -35,
|
||||
-40, -33, -32, -29, -30, -30, -30, -37,
|
||||
-45, -41, -37, -38, -45, -47, -47, -48,
|
||||
-53, -49, -48, -50, -49, -49, -51, -52,
|
||||
-58, -56, -57, -56, -60, -61, -62, -70,
|
||||
-72, -74, -78, -83, -88, -93, -100, -106}},
|
||||
/* 177 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -110, -105, -100, -95, -91, -87, -83,
|
||||
-80, -78, -76, -78, -78, -81, -83, -85,
|
||||
-86, -85, -86, -87, -90, -97, -107, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -110, -105, -100, -95, -90,
|
||||
-85, -81, -77, -73, -70, -67, -67, -68,
|
||||
-75, -73, -70, -69, -70, -72, -75, -79,
|
||||
-84, -83, -84, -86, -88, -89, -89, -93,
|
||||
-98, -105, -112, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-105, -100, -95, -90, -85, -80, -76, -71,
|
||||
-68, -68, -65, -63, -63, -62, -62, -64,
|
||||
-65, -64, -61, -62, -63, -64, -66, -68,
|
||||
-73, -73, -74, -75, -76, -81, -83, -85,
|
||||
-88, -89, -92, -95, -100, -108, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -80, -75, -71, -68, -65, -63, -62, -61,
|
||||
-61, -61, -61, -59, -56, -57, -53, -50,
|
||||
-58, -52, -50, -50, -52, -53, -54, -58,
|
||||
-67, -63, -67, -68, -72, -75, -78, -80,
|
||||
-81, -81, -82, -85, -89, -90, -93, -97,
|
||||
-101, -107, -114, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -65, -61, -59, -57, -56, -55, -55, -56,
|
||||
-56, -57, -55, -53, -52, -47, -44, -44,
|
||||
-50, -44, -41, -39, -39, -42, -40, -46,
|
||||
-51, -49, -50, -53, -54, -63, -60, -61,
|
||||
-62, -66, -66, -66, -70, -73, -74, -75,
|
||||
-76, -75, -79, -85, -89, -91, -96, -102,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999},
|
||||
{ -52, -50, -49, -49, -48, -48, -48, -49,
|
||||
-50, -50, -49, -46, -43, -39, -35, -33,
|
||||
-38, -36, -32, -29, -32, -32, -32, -35,
|
||||
-44, -39, -38, -38, -46, -50, -45, -46,
|
||||
-53, -50, -50, -50, -54, -54, -53, -53,
|
||||
-56, -57, -59, -66, -70, -72, -74, -79,
|
||||
-83, -85, -90, -97, -114, -999, -999, -999}},
|
||||
/* 250 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -110, -105,
|
||||
-100, -95, -90, -86, -80, -75, -75, -79,
|
||||
-80, -79, -80, -81, -82, -88, -95, -103,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -108, -103, -98, -93,
|
||||
-88, -83, -79, -78, -75, -71, -67, -68,
|
||||
-73, -73, -72, -73, -75, -77, -80, -82,
|
||||
-88, -93, -100, -107, -114, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -110, -105, -101, -96, -90,
|
||||
-86, -81, -77, -73, -69, -66, -61, -62,
|
||||
-66, -64, -62, -65, -66, -70, -72, -76,
|
||||
-81, -80, -84, -90, -95, -102, -110, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -107, -103, -97, -92, -88,
|
||||
-83, -79, -74, -70, -66, -59, -53, -58,
|
||||
-62, -55, -54, -54, -54, -58, -61, -62,
|
||||
-72, -70, -72, -75, -78, -80, -81, -80,
|
||||
-83, -83, -88, -93, -100, -107, -115, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -105, -100, -95, -90, -85,
|
||||
-80, -75, -70, -66, -62, -56, -48, -44,
|
||||
-48, -46, -46, -43, -46, -48, -48, -51,
|
||||
-58, -58, -59, -60, -62, -62, -61, -61,
|
||||
-65, -64, -65, -68, -70, -74, -75, -78,
|
||||
-81, -86, -95, -110, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -105, -100, -95, -90, -85, -80,
|
||||
-75, -70, -65, -61, -55, -49, -39, -33,
|
||||
-40, -35, -32, -38, -40, -33, -35, -37,
|
||||
-46, -41, -45, -44, -46, -42, -45, -46,
|
||||
-52, -50, -50, -50, -54, -54, -55, -57,
|
||||
-62, -64, -66, -68, -70, -76, -81, -90,
|
||||
-100, -110, -999, -999, -999, -999, -999, -999}},
|
||||
/* 354 hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-105, -98, -90, -85, -82, -83, -80, -78,
|
||||
-84, -79, -80, -83, -87, -89, -91, -93,
|
||||
-99, -106, -117, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-105, -98, -90, -85, -80, -75, -70, -68,
|
||||
-74, -72, -74, -77, -80, -82, -85, -87,
|
||||
-92, -89, -91, -95, -100, -106, -112, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-105, -98, -90, -83, -75, -71, -63, -64,
|
||||
-67, -62, -64, -67, -70, -73, -77, -81,
|
||||
-84, -83, -85, -89, -90, -93, -98, -104,
|
||||
-109, -114, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-103, -96, -88, -81, -75, -68, -58, -54,
|
||||
-56, -54, -56, -56, -58, -60, -63, -66,
|
||||
-74, -69, -72, -72, -75, -74, -77, -81,
|
||||
-81, -82, -84, -87, -93, -96, -99, -104,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -108, -102, -96,
|
||||
-91, -85, -80, -74, -68, -60, -51, -46,
|
||||
-48, -46, -43, -45, -47, -47, -49, -48,
|
||||
-56, -53, -55, -58, -57, -63, -58, -60,
|
||||
-66, -64, -67, -70, -70, -74, -77, -84,
|
||||
-86, -89, -91, -93, -94, -101, -109, -118,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -108, -103, -98, -93, -88,
|
||||
-83, -78, -73, -68, -60, -53, -44, -35,
|
||||
-38, -38, -34, -34, -36, -40, -41, -44,
|
||||
-51, -45, -46, -47, -46, -54, -50, -49,
|
||||
-50, -50, -50, -51, -54, -57, -58, -60,
|
||||
-66, -66, -66, -64, -65, -68, -77, -82,
|
||||
-87, -95, -110, -999, -999, -999, -999, -999}},
|
||||
/* 500 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-107, -102, -97, -92, -87, -83, -78, -75,
|
||||
-82, -79, -83, -85, -89, -92, -95, -98,
|
||||
-101, -105, -109, -113, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -106,
|
||||
-100, -95, -90, -86, -81, -78, -74, -69,
|
||||
-74, -74, -76, -79, -83, -84, -86, -89,
|
||||
-92, -97, -93, -100, -103, -107, -110, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -106, -100,
|
||||
-95, -90, -87, -83, -80, -75, -69, -60,
|
||||
-66, -66, -68, -70, -74, -78, -79, -81,
|
||||
-81, -83, -84, -87, -93, -96, -99, -103,
|
||||
-107, -110, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -108, -103, -98,
|
||||
-93, -89, -85, -82, -78, -71, -62, -55,
|
||||
-58, -58, -54, -54, -55, -59, -61, -62,
|
||||
-70, -66, -66, -67, -70, -72, -75, -78,
|
||||
-84, -84, -84, -88, -91, -90, -95, -98,
|
||||
-102, -103, -106, -110, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -108, -103, -98, -94,
|
||||
-90, -87, -82, -79, -73, -67, -58, -47,
|
||||
-50, -45, -41, -45, -48, -44, -44, -49,
|
||||
-54, -51, -48, -47, -49, -50, -51, -57,
|
||||
-58, -60, -63, -69, -70, -69, -71, -74,
|
||||
-78, -82, -90, -95, -101, -105, -110, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -105, -101, -97, -93, -90,
|
||||
-85, -80, -77, -72, -65, -56, -48, -37,
|
||||
-40, -36, -34, -40, -50, -47, -38, -41,
|
||||
-47, -38, -35, -39, -38, -43, -40, -45,
|
||||
-50, -45, -44, -47, -50, -55, -48, -48,
|
||||
-52, -66, -70, -76, -82, -90, -97, -105,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 707 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -108, -103, -98, -93, -86, -79, -76,
|
||||
-83, -81, -85, -87, -89, -93, -98, -102,
|
||||
-107, -112, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -108, -103, -98, -93, -86, -79, -71,
|
||||
-77, -74, -77, -79, -81, -84, -85, -90,
|
||||
-92, -93, -92, -98, -101, -108, -112, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-108, -103, -98, -93, -87, -78, -68, -65,
|
||||
-66, -62, -65, -67, -70, -73, -75, -78,
|
||||
-82, -82, -83, -84, -91, -93, -98, -102,
|
||||
-106, -110, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-105, -100, -95, -90, -82, -74, -62, -57,
|
||||
-58, -56, -51, -52, -52, -54, -54, -58,
|
||||
-66, -59, -60, -63, -66, -69, -73, -79,
|
||||
-83, -84, -80, -81, -81, -82, -88, -92,
|
||||
-98, -105, -113, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -107,
|
||||
-102, -97, -92, -84, -79, -69, -57, -47,
|
||||
-52, -47, -44, -45, -50, -52, -42, -42,
|
||||
-53, -43, -43, -48, -51, -56, -55, -52,
|
||||
-57, -59, -61, -62, -67, -71, -78, -83,
|
||||
-86, -94, -98, -103, -110, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -105, -100,
|
||||
-95, -90, -84, -78, -70, -61, -51, -41,
|
||||
-40, -38, -40, -46, -52, -51, -41, -40,
|
||||
-46, -40, -38, -38, -41, -46, -41, -46,
|
||||
-47, -43, -43, -45, -41, -45, -56, -67,
|
||||
-68, -83, -87, -90, -95, -102, -107, -113,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 1000 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -109, -105, -101, -96, -91, -84, -77,
|
||||
-82, -82, -85, -89, -94, -100, -106, -110,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -106, -103, -98, -92, -85, -80, -71,
|
||||
-75, -72, -76, -80, -84, -86, -89, -93,
|
||||
-100, -107, -113, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -107,
|
||||
-104, -101, -97, -92, -88, -84, -80, -64,
|
||||
-66, -63, -64, -66, -69, -73, -77, -83,
|
||||
-83, -86, -91, -98, -104, -111, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -107,
|
||||
-104, -101, -97, -92, -90, -84, -74, -57,
|
||||
-58, -52, -55, -54, -50, -52, -50, -52,
|
||||
-63, -62, -69, -76, -77, -78, -78, -79,
|
||||
-82, -88, -94, -100, -106, -111, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -106, -102,
|
||||
-98, -95, -90, -85, -83, -78, -70, -50,
|
||||
-50, -41, -44, -49, -47, -50, -50, -44,
|
||||
-55, -46, -47, -48, -48, -54, -49, -49,
|
||||
-58, -62, -71, -81, -87, -92, -97, -102,
|
||||
-108, -114, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -106, -102,
|
||||
-98, -95, -90, -85, -83, -78, -70, -45,
|
||||
-43, -41, -47, -50, -51, -50, -49, -45,
|
||||
-47, -41, -44, -41, -39, -43, -38, -37,
|
||||
-40, -41, -44, -50, -58, -65, -73, -79,
|
||||
-85, -92, -97, -101, -105, -109, -113, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 1414 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -107, -100, -95, -87, -81,
|
||||
-85, -83, -88, -93, -100, -107, -114, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -107, -101, -95, -88, -83, -76,
|
||||
-73, -72, -79, -84, -90, -95, -100, -105,
|
||||
-110, -115, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -104, -98, -92, -87, -81, -70,
|
||||
-65, -62, -67, -71, -74, -80, -85, -91,
|
||||
-95, -99, -103, -108, -111, -114, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -103, -97, -90, -85, -76, -60,
|
||||
-56, -54, -60, -62, -61, -56, -63, -65,
|
||||
-73, -74, -77, -75, -78, -81, -86, -87,
|
||||
-88, -91, -94, -98, -103, -110, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -105,
|
||||
-100, -97, -92, -86, -81, -79, -70, -57,
|
||||
-51, -47, -51, -58, -60, -56, -53, -50,
|
||||
-58, -52, -50, -50, -53, -55, -64, -69,
|
||||
-71, -85, -82, -78, -81, -85, -95, -102,
|
||||
-112, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -105,
|
||||
-100, -97, -92, -85, -83, -79, -72, -49,
|
||||
-40, -43, -43, -54, -56, -51, -50, -40,
|
||||
-43, -38, -36, -35, -37, -38, -37, -44,
|
||||
-54, -60, -57, -60, -70, -75, -84, -92,
|
||||
-103, -112, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 2000 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -102, -95, -89, -82,
|
||||
-83, -84, -90, -92, -99, -107, -113, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -107, -101, -95, -89, -83, -72,
|
||||
-74, -78, -85, -88, -88, -90, -92, -98,
|
||||
-105, -111, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -109, -103, -97, -93, -87, -81, -70,
|
||||
-70, -67, -75, -73, -76, -79, -81, -83,
|
||||
-88, -89, -97, -103, -110, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -107, -100, -94, -88, -83, -75, -63,
|
||||
-59, -59, -63, -66, -60, -62, -67, -67,
|
||||
-77, -76, -81, -88, -86, -92, -96, -102,
|
||||
-109, -116, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -105, -98, -92, -86, -81, -73, -56,
|
||||
-52, -47, -55, -60, -58, -52, -51, -45,
|
||||
-49, -50, -53, -54, -61, -71, -70, -69,
|
||||
-78, -79, -87, -90, -96, -104, -112, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -103, -96, -90, -86, -78, -70, -51,
|
||||
-42, -47, -48, -55, -54, -54, -53, -42,
|
||||
-35, -28, -33, -38, -37, -44, -47, -49,
|
||||
-54, -63, -68, -78, -82, -89, -94, -99,
|
||||
-104, -109, -114, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 2828 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -110, -100, -90, -79,
|
||||
-85, -81, -82, -82, -89, -94, -99, -103,
|
||||
-109, -115, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -105, -97, -85, -72,
|
||||
-74, -70, -70, -70, -76, -85, -91, -93,
|
||||
-97, -103, -109, -115, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -112, -93, -81, -68,
|
||||
-62, -60, -60, -57, -63, -70, -77, -82,
|
||||
-90, -93, -98, -104, -109, -113, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -113, -100, -93, -84, -63,
|
||||
-58, -48, -53, -54, -52, -52, -57, -64,
|
||||
-66, -76, -83, -81, -85, -85, -90, -95,
|
||||
-98, -101, -103, -106, -108, -111, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -105, -95, -86, -74, -53,
|
||||
-50, -38, -43, -49, -43, -42, -39, -39,
|
||||
-46, -52, -57, -56, -72, -69, -74, -81,
|
||||
-87, -92, -94, -97, -99, -102, -105, -108,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -108, -99, -90, -76, -66, -45,
|
||||
-43, -41, -44, -47, -43, -47, -40, -30,
|
||||
-31, -31, -39, -33, -40, -41, -43, -53,
|
||||
-59, -70, -73, -77, -79, -82, -84, -87,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 4000 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -110, -91, -76,
|
||||
-75, -85, -93, -98, -104, -110, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -110, -91, -70,
|
||||
-70, -75, -86, -89, -94, -98, -101, -106,
|
||||
-110, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -110, -95, -80, -60,
|
||||
-65, -64, -74, -83, -88, -91, -95, -99,
|
||||
-103, -107, -110, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -110, -95, -80, -58,
|
||||
-55, -49, -66, -68, -71, -78, -78, -80,
|
||||
-88, -85, -89, -97, -100, -105, -110, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -110, -95, -80, -53,
|
||||
-52, -41, -59, -59, -49, -58, -56, -63,
|
||||
-86, -79, -90, -93, -98, -103, -107, -112,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -97, -91, -73, -45,
|
||||
-40, -33, -53, -61, -49, -54, -50, -50,
|
||||
-60, -52, -67, -74, -81, -92, -96, -100,
|
||||
-105, -110, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 5657 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -113, -106, -99, -92, -77,
|
||||
-80, -88, -97, -106, -115, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -116, -109, -102, -95, -89, -74,
|
||||
-72, -88, -87, -95, -102, -109, -116, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -116, -109, -102, -95, -89, -75,
|
||||
-66, -74, -77, -78, -86, -87, -90, -96,
|
||||
-105, -115, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -115, -108, -101, -94, -88, -66,
|
||||
-56, -61, -70, -65, -78, -72, -83, -84,
|
||||
-93, -98, -105, -110, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -110, -105, -95, -89, -82, -57,
|
||||
-52, -52, -59, -56, -59, -58, -69, -67,
|
||||
-88, -82, -82, -89, -94, -100, -108, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -110, -101, -96, -90, -83, -77, -54,
|
||||
-43, -38, -50, -48, -52, -48, -42, -42,
|
||||
-51, -52, -53, -59, -65, -71, -78, -85,
|
||||
-95, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 8000 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -120, -105, -86, -68,
|
||||
-78, -79, -90, -100, -110, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -120, -105, -86, -66,
|
||||
-73, -77, -88, -96, -105, -115, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -120, -105, -92, -80, -61,
|
||||
-64, -68, -80, -87, -92, -100, -110, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -120, -104, -91, -79, -52,
|
||||
-60, -54, -64, -69, -77, -80, -82, -84,
|
||||
-85, -87, -88, -90, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -118, -100, -87, -77, -49,
|
||||
-50, -44, -58, -61, -61, -67, -65, -62,
|
||||
-62, -62, -65, -68, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -115, -98, -84, -62, -49,
|
||||
-44, -38, -46, -49, -49, -46, -39, -37,
|
||||
-39, -40, -42, -43, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 11314 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -110, -88, -74,
|
||||
-77, -82, -82, -85, -90, -94, -99, -104,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -110, -88, -66,
|
||||
-70, -81, -80, -81, -84, -88, -91, -93,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -110, -88, -61,
|
||||
-63, -70, -71, -74, -77, -80, -83, -85,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -110, -86, -62,
|
||||
-63, -62, -62, -58, -52, -50, -50, -52,
|
||||
-54, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -118, -108, -84, -53,
|
||||
-50, -50, -50, -55, -47, -45, -40, -40,
|
||||
-40, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -118, -100, -73, -43,
|
||||
-37, -42, -43, -53, -38, -37, -35, -35,
|
||||
-38, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}},
|
||||
/* 16000 Hz */
|
||||
{{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -100, -91, -84, -74,
|
||||
-80, -80, -80, -80, -80, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -100, -91, -84, -74,
|
||||
-68, -68, -68, -68, -68, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -100, -86, -78, -70,
|
||||
-60, -45, -30, -21, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -100, -87, -78, -67,
|
||||
-48, -38, -29, -21, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -100, -86, -69, -56,
|
||||
-45, -35, -33, -29, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999},
|
||||
{-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -110, -100, -83, -71, -48,
|
||||
-27, -38, -37, -34, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999,
|
||||
-999, -999, -999, -999, -999, -999, -999, -999}}
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,83 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: modified discrete cosine transform prototypes
|
||||
last mod: $Id: mdct.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _OGG_mdct_H_
|
||||
#define _OGG_mdct_H_
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*#define MDCT_INTEGERIZED <- be warned there could be some hurt left here*/
|
||||
#ifdef MDCT_INTEGERIZED
|
||||
|
||||
#define DATA_TYPE int
|
||||
#define REG_TYPE register int
|
||||
#define TRIGBITS 14
|
||||
#define cPI3_8 6270
|
||||
#define cPI2_8 11585
|
||||
#define cPI1_8 15137
|
||||
|
||||
#define FLOAT_CONV(x) ((int)((x)*(1<<TRIGBITS)+.5))
|
||||
#define MULT_NORM(x) ((x)>>TRIGBITS)
|
||||
#define HALVE(x) ((x)>>1)
|
||||
|
||||
#else
|
||||
|
||||
#define DATA_TYPE float
|
||||
#define REG_TYPE float
|
||||
#define cPI3_8 .38268343236508977175F
|
||||
#define cPI2_8 .70710678118654752441F
|
||||
#define cPI1_8 .92387953251128675613F
|
||||
|
||||
#define FLOAT_CONV(x) (x)
|
||||
#define MULT_NORM(x) (x)
|
||||
#define HALVE(x) ((x)*.5f)
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct {
|
||||
int n;
|
||||
int log2n;
|
||||
|
||||
DATA_TYPE *trig;
|
||||
int *bitrev;
|
||||
|
||||
DATA_TYPE scale;
|
||||
} mdct_lookup;
|
||||
|
||||
extern void mdct_init(mdct_lookup *lookup,int n);
|
||||
extern void mdct_clear(mdct_lookup *l);
|
||||
extern void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out);
|
||||
extern void mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: miscellaneous prototypes
|
||||
last mod: $Id: misc.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_RANDOM_H_
|
||||
#define _V_RANDOM_H_
|
||||
#include "vorbis/codec.h"
|
||||
|
||||
extern int analysis_noisy;
|
||||
|
||||
extern void *_vorbis_block_alloc(vorbis_block *vb,long bytes);
|
||||
extern void _vorbis_block_ripcord(vorbis_block *vb);
|
||||
extern void _analysis_output(char *base,int i,float *v,int n,int bark,int dB,
|
||||
ogg_int64_t off);
|
||||
|
||||
#ifdef DEBUG_MALLOC
|
||||
|
||||
#define _VDBG_GRAPHFILE "malloc.m"
|
||||
extern void *_VDBG_malloc(void *ptr,long bytes,char *file,long line);
|
||||
extern void _VDBG_free(void *ptr,char *file,long line);
|
||||
|
||||
#ifndef MISC_C
|
||||
#undef _ogg_malloc
|
||||
#undef _ogg_calloc
|
||||
#undef _ogg_realloc
|
||||
#undef _ogg_free
|
||||
|
||||
#define _ogg_malloc(x) _VDBG_malloc(NULL,(x),__FILE__,__LINE__)
|
||||
#define _ogg_calloc(x,y) _VDBG_malloc(NULL,(x)*(y),__FILE__,__LINE__)
|
||||
#define _ogg_realloc(x,y) _VDBG_malloc((x),(y),__FILE__,__LINE__)
|
||||
#define _ogg_free(x) _VDBG_free((x),__FILE__,__LINE__)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
#ifndef _OS_H
|
||||
#define _OS_H
|
||||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: #ifdef jail to whip a few platforms into the UNIX ideal.
|
||||
last mod: $Id: os.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <ogg/os_types.h>
|
||||
|
||||
#include "misc.h"
|
||||
|
||||
#ifndef _V_IFDEFJAIL_H_
|
||||
# define _V_IFDEFJAIL_H_
|
||||
|
||||
# ifdef __GNUC__
|
||||
# define STIN static __inline__
|
||||
# elif _WIN32
|
||||
# define STIN static __inline
|
||||
# else
|
||||
# define STIN static
|
||||
# endif
|
||||
|
||||
#ifdef DJGPP
|
||||
# define rint(x) (floor((x)+0.5f))
|
||||
#endif
|
||||
|
||||
#ifndef M_PI
|
||||
# define M_PI (3.1415926536f)
|
||||
#endif
|
||||
|
||||
#if defined(_WIN32) && !defined(__SYMBIAN32__)
|
||||
# include <malloc.h>
|
||||
# define rint(x) (floor((x)+0.5f))
|
||||
# define NO_FLOAT_MATH_LIB
|
||||
# define FAST_HYPOT(a, b) sqrt((a)*(a) + (b)*(b))
|
||||
#endif
|
||||
|
||||
#if defined(__SYMBIAN32__) && defined(__WINS__)
|
||||
void *_alloca(size_t size);
|
||||
# define alloca _alloca
|
||||
#endif
|
||||
|
||||
#ifndef FAST_HYPOT
|
||||
# define FAST_HYPOT hypot
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ALLOCA_H
|
||||
# include <alloca.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_MEMORY_H
|
||||
# include <memory.h>
|
||||
#endif
|
||||
|
||||
#ifndef min
|
||||
# define min(x,y) ((x)>(y)?(y):(x))
|
||||
#endif
|
||||
|
||||
#ifndef max
|
||||
# define max(x,y) ((x)<(y)?(y):(x))
|
||||
#endif
|
||||
|
||||
#if defined(__i386__) && defined(__GNUC__) && !defined(__BEOS__)
|
||||
# define VORBIS_FPU_CONTROL
|
||||
/* both GCC and MSVC are kinda stupid about rounding/casting to int.
|
||||
Because of encapsulation constraints (GCC can't see inside the asm
|
||||
block and so we end up doing stupid things like a store/load that
|
||||
is collectively a noop), we do it this way */
|
||||
|
||||
/* we must set up the fpu before this works!! */
|
||||
|
||||
typedef ogg_int16_t vorbis_fpu_control;
|
||||
|
||||
static inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
|
||||
ogg_int16_t ret;
|
||||
ogg_int16_t temp;
|
||||
__asm__ __volatile__("fnstcw %0\n\t"
|
||||
"movw %0,%%dx\n\t"
|
||||
"orw $62463,%%dx\n\t"
|
||||
"movw %%dx,%1\n\t"
|
||||
"fldcw %1\n\t":"=m"(ret):"m"(temp): "dx");
|
||||
*fpu=ret;
|
||||
}
|
||||
|
||||
static inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
|
||||
__asm__ __volatile__("fldcw %0":: "m"(fpu));
|
||||
}
|
||||
|
||||
/* assumes the FPU is in round mode! */
|
||||
static inline int vorbis_ftoi(double f){ /* yes, double! Otherwise,
|
||||
we get extra fst/fld to
|
||||
truncate precision */
|
||||
int i;
|
||||
__asm__("fistl %0": "=m"(i) : "t"(f));
|
||||
return(i);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(_WIN32) && !defined(__GNUC__) && !defined(__BORLANDC__)
|
||||
# define VORBIS_FPU_CONTROL
|
||||
|
||||
typedef ogg_int16_t vorbis_fpu_control;
|
||||
|
||||
static __inline int vorbis_ftoi(double f){
|
||||
int i;
|
||||
__asm{
|
||||
fld f
|
||||
fistp i
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static __inline void vorbis_fpu_setround(vorbis_fpu_control *fpu){
|
||||
}
|
||||
|
||||
static __inline void vorbis_fpu_restore(vorbis_fpu_control fpu){
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef VORBIS_FPU_CONTROL
|
||||
|
||||
typedef int vorbis_fpu_control;
|
||||
|
||||
static int vorbis_ftoi(double f){
|
||||
return (int)(f+.5);
|
||||
}
|
||||
|
||||
/* We don't have special code for this compiler/arch, so do it the slow way */
|
||||
# define vorbis_fpu_setround(vorbis_fpu_control) {}
|
||||
# define vorbis_fpu_restore(vorbis_fpu_control) {}
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _OS_H */
|
|
@ -0,0 +1,186 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: random psychoacoustics (not including preecho)
|
||||
last mod: $Id: psy.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_PSY_H_
|
||||
#define _V_PSY_H_
|
||||
#include "smallft.h"
|
||||
|
||||
#include "backends.h"
|
||||
#include "envelope.h"
|
||||
|
||||
#ifndef EHMER_MAX
|
||||
#define EHMER_MAX 56
|
||||
#endif
|
||||
|
||||
/* psychoacoustic setup ********************************************/
|
||||
#define P_BANDS 17 /* 62Hz to 16kHz */
|
||||
#define P_LEVELS 8 /* 30dB to 100dB */
|
||||
#define P_LEVEL_0 30. /* 30 dB */
|
||||
#define P_NOISECURVES 3
|
||||
|
||||
#define NOISE_COMPAND_LEVELS 40
|
||||
typedef struct vorbis_info_psy{
|
||||
int blockflag;
|
||||
|
||||
float ath_adjatt;
|
||||
float ath_maxatt;
|
||||
|
||||
float tone_masteratt[P_NOISECURVES];
|
||||
float tone_centerboost;
|
||||
float tone_decay;
|
||||
float tone_abs_limit;
|
||||
float toneatt[P_BANDS];
|
||||
|
||||
int noisemaskp;
|
||||
float noisemaxsupp;
|
||||
float noisewindowlo;
|
||||
float noisewindowhi;
|
||||
int noisewindowlomin;
|
||||
int noisewindowhimin;
|
||||
int noisewindowfixed;
|
||||
float noiseoff[P_NOISECURVES][P_BANDS];
|
||||
float noisecompand[NOISE_COMPAND_LEVELS];
|
||||
|
||||
float max_curve_dB;
|
||||
|
||||
int normal_channel_p;
|
||||
int normal_point_p;
|
||||
int normal_start;
|
||||
int normal_partition;
|
||||
double normal_thresh;
|
||||
} vorbis_info_psy;
|
||||
|
||||
typedef struct{
|
||||
int eighth_octave_lines;
|
||||
|
||||
/* for block long/short tuning; encode only */
|
||||
float preecho_thresh[VE_BANDS];
|
||||
float postecho_thresh[VE_BANDS];
|
||||
float stretch_penalty;
|
||||
float preecho_minenergy;
|
||||
|
||||
float ampmax_att_per_sec;
|
||||
|
||||
/* channel coupling config */
|
||||
int coupling_pkHz[PACKETBLOBS];
|
||||
int coupling_pointlimit[2][PACKETBLOBS];
|
||||
int coupling_prepointamp[PACKETBLOBS];
|
||||
int coupling_postpointamp[PACKETBLOBS];
|
||||
int sliding_lowpass[2][PACKETBLOBS];
|
||||
|
||||
} vorbis_info_psy_global;
|
||||
|
||||
typedef struct {
|
||||
float ampmax;
|
||||
int channels;
|
||||
|
||||
vorbis_info_psy_global *gi;
|
||||
int coupling_pointlimit[2][P_NOISECURVES];
|
||||
} vorbis_look_psy_global;
|
||||
|
||||
|
||||
typedef struct {
|
||||
int n;
|
||||
struct vorbis_info_psy *vi;
|
||||
|
||||
float ***tonecurves;
|
||||
float **noiseoffset;
|
||||
|
||||
float *ath;
|
||||
long *octave; /* in n.ocshift format */
|
||||
long *bark;
|
||||
|
||||
long firstoc;
|
||||
long shiftoc;
|
||||
int eighth_octave_lines; /* power of two, please */
|
||||
int total_octave_lines;
|
||||
long rate; /* cache it */
|
||||
|
||||
float m_val; /* Masking compensation value */
|
||||
|
||||
} vorbis_look_psy;
|
||||
|
||||
extern void _vp_psy_init(vorbis_look_psy *p,vorbis_info_psy *vi,
|
||||
vorbis_info_psy_global *gi,int n,long rate);
|
||||
extern void _vp_psy_clear(vorbis_look_psy *p);
|
||||
extern void *_vi_psy_dup(void *source);
|
||||
|
||||
extern void _vi_psy_free(vorbis_info_psy *i);
|
||||
extern vorbis_info_psy *_vi_psy_copy(vorbis_info_psy *i);
|
||||
|
||||
extern void _vp_remove_floor(vorbis_look_psy *p,
|
||||
float *mdct,
|
||||
int *icodedflr,
|
||||
float *residue,
|
||||
int sliding_lowpass);
|
||||
|
||||
extern void _vp_noisemask(vorbis_look_psy *p,
|
||||
float *logmdct,
|
||||
float *logmask);
|
||||
|
||||
extern void _vp_tonemask(vorbis_look_psy *p,
|
||||
float *logfft,
|
||||
float *logmask,
|
||||
float global_specmax,
|
||||
float local_specmax);
|
||||
|
||||
extern void _vp_offset_and_mix(vorbis_look_psy *p,
|
||||
float *noise,
|
||||
float *tone,
|
||||
int offset_select,
|
||||
float *logmask,
|
||||
float *mdct,
|
||||
float *logmdct);
|
||||
|
||||
extern float _vp_ampmax_decay(float amp,vorbis_dsp_state *vd);
|
||||
|
||||
extern float **_vp_quantize_couple_memo(vorbis_block *vb,
|
||||
vorbis_info_psy_global *g,
|
||||
vorbis_look_psy *p,
|
||||
vorbis_info_mapping0 *vi,
|
||||
float **mdct);
|
||||
|
||||
extern void _vp_couple(int blobno,
|
||||
vorbis_info_psy_global *g,
|
||||
vorbis_look_psy *p,
|
||||
vorbis_info_mapping0 *vi,
|
||||
float **res,
|
||||
float **mag_memo,
|
||||
int **mag_sort,
|
||||
int **ifloor,
|
||||
int *nonzero,
|
||||
int sliding_lowpass);
|
||||
|
||||
extern void _vp_noise_normalize(vorbis_look_psy *p,
|
||||
float *in,float *out,int *sortedindex);
|
||||
|
||||
extern void _vp_noise_normalize_sort(vorbis_look_psy *p,
|
||||
float *magnitudes,int *sortedindex);
|
||||
|
||||
extern int **_vp_quantize_couple_sort(vorbis_block *vb,
|
||||
vorbis_look_psy *p,
|
||||
vorbis_info_mapping0 *vi,
|
||||
float **mags);
|
||||
|
||||
extern void hf_reduction(vorbis_info_psy_global *g,
|
||||
vorbis_look_psy *p,
|
||||
vorbis_info_mapping0 *vi,
|
||||
float **mdct);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: registry for time, floor, res backends and channel mappings
|
||||
last mod: $Id: registry.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_REG_H_
|
||||
#define _V_REG_H_
|
||||
|
||||
#define VI_TRANSFORMB 1
|
||||
#define VI_WINDOWB 1
|
||||
#define VI_TIMEB 1
|
||||
#define VI_FLOORB 2
|
||||
#define VI_RESB 3
|
||||
#define VI_MAPB 1
|
||||
|
||||
extern vorbis_func_floor *_floor_P[];
|
||||
extern vorbis_func_residue *_residue_P[];
|
||||
extern vorbis_func_mapping *_mapping_P[];
|
||||
|
||||
#endif
|
|
@ -0,0 +1,86 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: linear scale -> dB, Bark and Mel scales
|
||||
last mod: $Id: scales.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_SCALES_H_
|
||||
#define _V_SCALES_H_
|
||||
|
||||
#include <math.h>
|
||||
#include "os.h"
|
||||
|
||||
/* 20log10(x) */
|
||||
#define VORBIS_IEEE_FLOAT32 1
|
||||
#ifdef VORBIS_IEEE_FLOAT32
|
||||
|
||||
static float unitnorm(float x){
|
||||
union {
|
||||
ogg_uint32_t i;
|
||||
float f;
|
||||
} ix;
|
||||
ix.f = x;
|
||||
ix.i = (ix.i & 0x80000000U) | (0x3f800000U);
|
||||
return ix.f;
|
||||
}
|
||||
|
||||
/* Segher was off (too high) by ~ .3 decibel. Center the conversion correctly. */
|
||||
static float todB(const float *x){
|
||||
union {
|
||||
ogg_uint32_t i;
|
||||
float f;
|
||||
} ix;
|
||||
ix.f = *x;
|
||||
ix.i = ix.i&0x7fffffff;
|
||||
return (float)(ix.i * 7.17711438e-7f -764.6161886f);
|
||||
}
|
||||
|
||||
#define todB_nn(x) todB(x)
|
||||
|
||||
#else
|
||||
|
||||
static float unitnorm(float x){
|
||||
if(x<0)return(-1.f);
|
||||
return(1.f);
|
||||
}
|
||||
|
||||
#define todB(x) (*(x)==0?-400.f:log(*(x)**(x))*4.34294480f)
|
||||
#define todB_nn(x) (*(x)==0.f?-400.f:log(*(x))*8.6858896f)
|
||||
|
||||
#endif
|
||||
|
||||
#define fromdB(x) (exp((x)*.11512925f))
|
||||
|
||||
/* The bark scale equations are approximations, since the original
|
||||
table was somewhat hand rolled. The below are chosen to have the
|
||||
best possible fit to the rolled tables, thus their somewhat odd
|
||||
appearance (these are more accurate and over a longer range than
|
||||
the oft-quoted bark equations found in the texts I have). The
|
||||
approximations are valid from 0 - 30kHz (nyquist) or so.
|
||||
|
||||
all f in Hz, z in Bark */
|
||||
|
||||
#define toBARK(n) (13.1f*atan(.00074f*(n))+2.24f*atan((n)*(n)*1.85e-8f)+1e-4f*(n))
|
||||
#define fromBARK(z) (102.f*(z)-2.f*pow(z,2.f)+.4f*pow(z,3.f)+pow(1.46f,z)-1.f)
|
||||
#define toMEL(n) (log(1.f+(n)*.001f)*1442.695f)
|
||||
#define fromMEL(m) (1000.f*exp((m)/1442.695f)-1000.f)
|
||||
|
||||
/* Frequency to octave. We arbitrarily declare 63.5 Hz to be octave
|
||||
0.0 */
|
||||
|
||||
#define toOC(n) (log(n)*1.442695f-5.965784f)
|
||||
#define fromOC(o) (exp(((o)+5.965784f)*.693147f))
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: fft transform
|
||||
last mod: $Id: smallft.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_SMFT_H_
|
||||
#define _V_SMFT_H_
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
|
||||
typedef struct {
|
||||
int n;
|
||||
float *trigcache;
|
||||
int *splitcache;
|
||||
} drft_lookup;
|
||||
|
||||
extern void drft_forward(drft_lookup *l,float *data);
|
||||
extern void drft_backward(drft_lookup *l,float *data);
|
||||
extern void drft_init(drft_lookup *l,int n);
|
||||
extern void drft_clear(drft_lookup *l);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,121 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: single-block PCM analysis mode dispatch
|
||||
last mod: $Id: analysis.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "scales.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
|
||||
int analysis_noisy=1;
|
||||
|
||||
/* decides between modes, dispatches to the appropriate mapping. */
|
||||
int vorbis_analysis(vorbis_block *vb, ogg_packet *op){
|
||||
int ret,i;
|
||||
vorbis_block_internal *vbi=vb->internal;
|
||||
|
||||
vb->glue_bits=0;
|
||||
vb->time_bits=0;
|
||||
vb->floor_bits=0;
|
||||
vb->res_bits=0;
|
||||
|
||||
/* first things first. Make sure encode is ready */
|
||||
for(i=0;i<PACKETBLOBS;i++)
|
||||
oggpack_reset(vbi->packetblob[i]);
|
||||
|
||||
/* we only have one mapping type (0), and we let the mapping code
|
||||
itself figure out what soft mode to use. This allows easier
|
||||
bitrate management */
|
||||
|
||||
if((ret=_mapping_P[0]->forward(vb)))
|
||||
return(ret);
|
||||
|
||||
if(op){
|
||||
if(vorbis_bitrate_managed(vb))
|
||||
/* The app is using a bitmanaged mode... but not using the
|
||||
bitrate management interface. */
|
||||
return(OV_EINVAL);
|
||||
|
||||
op->packet=oggpack_get_buffer(&vb->opb);
|
||||
op->bytes=oggpack_bytes(&vb->opb);
|
||||
op->b_o_s=0;
|
||||
op->e_o_s=vb->eofflag;
|
||||
op->granulepos=vb->granulepos;
|
||||
op->packetno=vb->sequence; /* for sake of completeness */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* there was no great place to put this.... */
|
||||
void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,ogg_int64_t off){
|
||||
int j;
|
||||
FILE *of;
|
||||
char buffer[80];
|
||||
|
||||
/* if(i==5870){*/
|
||||
sprintf(buffer,"%s_%d.m",base,i);
|
||||
of=fopen(buffer,"w");
|
||||
|
||||
if(!of)perror("failed to open data dump file");
|
||||
|
||||
for(j=0;j<n;j++){
|
||||
if(bark){
|
||||
float b=toBARK((4000.f*j/n)+.25);
|
||||
fprintf(of,"%f ",b);
|
||||
}else
|
||||
if(off!=0)
|
||||
fprintf(of,"%f ",(double)(j+off)/8000.);
|
||||
else
|
||||
fprintf(of,"%f ",(double)j);
|
||||
|
||||
if(dB){
|
||||
float val;
|
||||
if(v[j]==0.)
|
||||
val=-140.;
|
||||
else
|
||||
val=todB(v+j);
|
||||
fprintf(of,"%f\n",val);
|
||||
}else{
|
||||
fprintf(of,"%f\n",v[j]);
|
||||
}
|
||||
}
|
||||
fclose(of);
|
||||
/* } */
|
||||
}
|
||||
|
||||
void _analysis_output(char *base,int i,float *v,int n,int bark,int dB,
|
||||
ogg_int64_t off){
|
||||
if(analysis_noisy)_analysis_output_always(base,i,v,n,bark,dB,off);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,253 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
last mod: $Id: bitrate.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
#include "bitrate.h"
|
||||
|
||||
/* compute bitrate tracking setup */
|
||||
void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
bitrate_manager_info *bi=&ci->bi;
|
||||
|
||||
memset(bm,0,sizeof(*bm));
|
||||
|
||||
if(bi && (bi->reservoir_bits>0)){
|
||||
long ratesamples=vi->rate;
|
||||
int halfsamples=ci->blocksizes[0]>>1;
|
||||
|
||||
bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0];
|
||||
bm->managed=1;
|
||||
|
||||
bm->avg_bitsper= rint(1.*bi->avg_rate*halfsamples/ratesamples);
|
||||
bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples);
|
||||
bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples);
|
||||
|
||||
bm->avgfloat=PACKETBLOBS/2;
|
||||
|
||||
/* not a necessary fix, but one that leads to a more balanced
|
||||
typical initialization */
|
||||
{
|
||||
long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
bm->avg_reservoir=desired_fill;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void vorbis_bitrate_clear(bitrate_manager_state *bm){
|
||||
memset(bm,0,sizeof(*bm));
|
||||
return;
|
||||
}
|
||||
|
||||
int vorbis_bitrate_managed(vorbis_block *vb){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=vd->backend_state;
|
||||
bitrate_manager_state *bm=&b->bms;
|
||||
|
||||
if(bm && bm->managed)return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* finish taking in the block we just processed */
|
||||
int vorbis_bitrate_addblock(vorbis_block *vb){
|
||||
vorbis_block_internal *vbi=vb->internal;
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=vd->backend_state;
|
||||
bitrate_manager_state *bm=&b->bms;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
bitrate_manager_info *bi=&ci->bi;
|
||||
|
||||
int choice=rint(bm->avgfloat);
|
||||
long this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper);
|
||||
long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper);
|
||||
int samples=ci->blocksizes[vb->W]>>1;
|
||||
long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
|
||||
if(!bm->managed){
|
||||
/* not a bitrate managed stream, but for API simplicity, we'll
|
||||
buffer the packet to keep the code path clean */
|
||||
|
||||
if(bm->vb)return(-1); /* one has been submitted without
|
||||
being claimed */
|
||||
bm->vb=vb;
|
||||
return(0);
|
||||
}
|
||||
|
||||
bm->vb=vb;
|
||||
|
||||
/* look ahead for avg floater */
|
||||
if(bm->avg_bitsper>0){
|
||||
double slew=0.;
|
||||
long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
|
||||
double slewlimit= 15./bi->slew_damp;
|
||||
|
||||
/* choosing a new floater:
|
||||
if we're over target, we slew down
|
||||
if we're under target, we slew up
|
||||
|
||||
choose slew as follows: look through packetblobs of this frame
|
||||
and set slew as the first in the appropriate direction that
|
||||
gives us the slew we want. This may mean no slew if delta is
|
||||
already favorable.
|
||||
|
||||
Then limit slew to slew max */
|
||||
|
||||
if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
|
||||
while(choice>0 && this_bits>avg_target_bits &&
|
||||
bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
|
||||
choice--;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
|
||||
while(choice+1<PACKETBLOBS && this_bits<avg_target_bits &&
|
||||
bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
|
||||
choice++;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
|
||||
slew=rint(choice-bm->avgfloat)/samples*vi->rate;
|
||||
if(slew<-slewlimit)slew=-slewlimit;
|
||||
if(slew>slewlimit)slew=slewlimit;
|
||||
choice=rint(bm->avgfloat+= slew/vi->rate*samples);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* enforce min(if used) on the current floater (if used) */
|
||||
if(bm->min_bitsper>0){
|
||||
/* do we need to force the bitrate up? */
|
||||
if(this_bits<min_target_bits){
|
||||
while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){
|
||||
choice++;
|
||||
if(choice>=PACKETBLOBS)break;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* enforce max (if used) on the current floater (if used) */
|
||||
if(bm->max_bitsper>0){
|
||||
/* do we need to force the bitrate down? */
|
||||
if(this_bits>max_target_bits){
|
||||
while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){
|
||||
choice--;
|
||||
if(choice<0)break;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Choice of packetblobs now made based on floater, and min/max
|
||||
requirements. Now boundary check extreme choices */
|
||||
|
||||
if(choice<0){
|
||||
/* choosing a smaller packetblob is insufficient to trim bitrate.
|
||||
frame will need to be truncated */
|
||||
long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8;
|
||||
bm->choice=choice=0;
|
||||
|
||||
if(oggpack_bytes(vbi->packetblob[choice])>maxsize){
|
||||
|
||||
oggpack_writetrunc(vbi->packetblob[choice],maxsize*8);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}else{
|
||||
long minsize=(min_target_bits-bm->minmax_reservoir+7)/8;
|
||||
if(choice>=PACKETBLOBS)
|
||||
choice=PACKETBLOBS-1;
|
||||
|
||||
bm->choice=choice;
|
||||
|
||||
/* prop up bitrate according to demand. pad this frame out with zeroes */
|
||||
minsize-=oggpack_bytes(vbi->packetblob[choice]);
|
||||
while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
|
||||
}
|
||||
|
||||
/* now we have the final packet and the final packet size. Update statistics */
|
||||
/* min and max reservoir */
|
||||
if(bm->min_bitsper>0 || bm->max_bitsper>0){
|
||||
|
||||
if(max_target_bits>0 && this_bits>max_target_bits){
|
||||
bm->minmax_reservoir+=(this_bits-max_target_bits);
|
||||
}else if(min_target_bits>0 && this_bits<min_target_bits){
|
||||
bm->minmax_reservoir+=(this_bits-min_target_bits);
|
||||
}else{
|
||||
/* inbetween; we want to take reservoir toward but not past desired_fill */
|
||||
if(bm->minmax_reservoir>desired_fill){
|
||||
if(max_target_bits>0){ /* logical bulletproofing against initialization state */
|
||||
bm->minmax_reservoir+=(this_bits-max_target_bits);
|
||||
if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill;
|
||||
}else{
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
}
|
||||
}else{
|
||||
if(min_target_bits>0){ /* logical bulletproofing against initialization state */
|
||||
bm->minmax_reservoir+=(this_bits-min_target_bits);
|
||||
if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill;
|
||||
}else{
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* avg reservoir */
|
||||
if(bm->avg_bitsper>0){
|
||||
long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
|
||||
bm->avg_reservoir+=this_bits-avg_target_bits;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
|
||||
private_state *b=vd->backend_state;
|
||||
bitrate_manager_state *bm=&b->bms;
|
||||
vorbis_block *vb=bm->vb;
|
||||
int choice=PACKETBLOBS/2;
|
||||
if(!vb)return 0;
|
||||
|
||||
if(op){
|
||||
vorbis_block_internal *vbi=vb->internal;
|
||||
|
||||
if(vorbis_bitrate_managed(vb))
|
||||
choice=bm->choice;
|
||||
|
||||
op->packet=oggpack_get_buffer(vbi->packetblob[choice]);
|
||||
op->bytes=oggpack_bytes(vbi->packetblob[choice]);
|
||||
op->b_o_s=0;
|
||||
op->e_o_s=vb->eofflag;
|
||||
op->granulepos=vb->granulepos;
|
||||
op->packetno=vb->sequence; /* for sake of completeness */
|
||||
}
|
||||
|
||||
bm->vb=0;
|
||||
return(1);
|
||||
}
|
|
@ -0,0 +1,993 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data vector blocking, windowing and dis/reassembly
|
||||
last mod: $Id: block.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
Handle windowing, overlap-add, etc of the PCM vectors. This is made
|
||||
more amusing by Vorbis' current two allowed block sizes.
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mdct.h"
|
||||
#include "lpc.h"
|
||||
#include "registry.h"
|
||||
#include "misc.h"
|
||||
|
||||
static int ilog2(unsigned int v){
|
||||
int ret=0;
|
||||
if(v)--v;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* pcm accumulator examples (not exhaustive):
|
||||
|
||||
<-------------- lW ---------------->
|
||||
<--------------- W ---------------->
|
||||
: .....|..... _______________ |
|
||||
: .''' | '''_--- | |\ |
|
||||
:.....''' |_____--- '''......| | \_______|
|
||||
:.................|__________________|_______|__|______|
|
||||
|<------ Sl ------>| > Sr < |endW
|
||||
|beginSl |endSl | |endSr
|
||||
|beginW |endlW |beginSr
|
||||
|
||||
|
||||
|< lW >|
|
||||
<--------------- W ---------------->
|
||||
| | .. ______________ |
|
||||
| | ' `/ | ---_ |
|
||||
|___.'___/`. | ---_____|
|
||||
|_______|__|_______|_________________|
|
||||
| >|Sl|< |<------ Sr ----->|endW
|
||||
| | |endSl |beginSr |endSr
|
||||
|beginW | |endlW
|
||||
mult[0] |beginSl mult[n]
|
||||
|
||||
<-------------- lW ----------------->
|
||||
|<--W-->|
|
||||
: .............. ___ | |
|
||||
: .''' |`/ \ | |
|
||||
:.....''' |/`....\|...|
|
||||
:.........................|___|___|___|
|
||||
|Sl |Sr |endW
|
||||
| | |endSr
|
||||
| |beginSr
|
||||
| |endSl
|
||||
|beginSl
|
||||
|beginW
|
||||
*/
|
||||
|
||||
/* block abstraction setup *********************************************/
|
||||
|
||||
#ifndef WORD_ALIGN
|
||||
#define WORD_ALIGN 8
|
||||
#endif
|
||||
|
||||
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
|
||||
int i;
|
||||
memset(vb,0,sizeof(*vb));
|
||||
vb->vd=v;
|
||||
vb->localalloc=0;
|
||||
vb->localstore=NULL;
|
||||
if(v->analysisp){
|
||||
vorbis_block_internal *vbi=
|
||||
vb->internal=_ogg_calloc(1,sizeof(vorbis_block_internal));
|
||||
vbi->ampmax=-9999;
|
||||
|
||||
for(i=0;i<PACKETBLOBS;i++){
|
||||
if(i==PACKETBLOBS/2){
|
||||
vbi->packetblob[i]=&vb->opb;
|
||||
}else{
|
||||
vbi->packetblob[i]=
|
||||
_ogg_calloc(1,sizeof(oggpack_buffer));
|
||||
}
|
||||
oggpack_writeinit(vbi->packetblob[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
|
||||
bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
|
||||
if(bytes+vb->localtop>vb->localalloc){
|
||||
/* can't just _ogg_realloc... there are outstanding pointers */
|
||||
if(vb->localstore){
|
||||
struct alloc_chain *link=_ogg_malloc(sizeof(*link));
|
||||
vb->totaluse+=vb->localtop;
|
||||
link->next=vb->reap;
|
||||
link->ptr=vb->localstore;
|
||||
vb->reap=link;
|
||||
}
|
||||
/* highly conservative */
|
||||
vb->localalloc=bytes;
|
||||
vb->localstore=_ogg_malloc(vb->localalloc);
|
||||
vb->localtop=0;
|
||||
}
|
||||
{
|
||||
void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
|
||||
vb->localtop+=bytes;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* reap the chain, pull the ripcord */
|
||||
void _vorbis_block_ripcord(vorbis_block *vb){
|
||||
/* reap the chain */
|
||||
struct alloc_chain *reap=vb->reap;
|
||||
while(reap){
|
||||
struct alloc_chain *next=reap->next;
|
||||
_ogg_free(reap->ptr);
|
||||
memset(reap,0,sizeof(*reap));
|
||||
_ogg_free(reap);
|
||||
reap=next;
|
||||
}
|
||||
/* consolidate storage */
|
||||
if(vb->totaluse){
|
||||
vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
|
||||
vb->localalloc+=vb->totaluse;
|
||||
vb->totaluse=0;
|
||||
}
|
||||
|
||||
/* pull the ripcord */
|
||||
vb->localtop=0;
|
||||
vb->reap=NULL;
|
||||
}
|
||||
|
||||
int vorbis_block_clear(vorbis_block *vb){
|
||||
int i;
|
||||
vorbis_block_internal *vbi=vb->internal;
|
||||
|
||||
_vorbis_block_ripcord(vb);
|
||||
if(vb->localstore)_ogg_free(vb->localstore);
|
||||
|
||||
if(vbi){
|
||||
for(i=0;i<PACKETBLOBS;i++){
|
||||
oggpack_writeclear(vbi->packetblob[i]);
|
||||
if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]);
|
||||
}
|
||||
_ogg_free(vbi);
|
||||
}
|
||||
memset(vb,0,sizeof(*vb));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Analysis side code, but directly related to blocking. Thus it's
|
||||
here and not in analysis.c (which is for analysis transforms only).
|
||||
The init is here because some of it is shared */
|
||||
|
||||
static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
|
||||
int i;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
private_state *b=NULL;
|
||||
int hs;
|
||||
|
||||
if(ci==NULL) return 1;
|
||||
hs=ci->halfrate_flag;
|
||||
|
||||
memset(v,0,sizeof(*v));
|
||||
b=v->backend_state=_ogg_calloc(1,sizeof(*b));
|
||||
|
||||
v->vi=vi;
|
||||
b->modebits=ilog2(ci->modes);
|
||||
|
||||
b->transform[0]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0]));
|
||||
b->transform[1]=_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1]));
|
||||
|
||||
/* MDCT is tranform 0 */
|
||||
|
||||
b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
|
||||
b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
|
||||
mdct_init(b->transform[0][0],ci->blocksizes[0]>>hs);
|
||||
mdct_init(b->transform[1][0],ci->blocksizes[1]>>hs);
|
||||
|
||||
/* Vorbis I uses only window type 0 */
|
||||
b->window[0]=ilog2(ci->blocksizes[0])-6;
|
||||
b->window[1]=ilog2(ci->blocksizes[1])-6;
|
||||
|
||||
if(encp){ /* encode/decode differ here */
|
||||
|
||||
/* analysis always needs an fft */
|
||||
drft_init(&b->fft_look[0],ci->blocksizes[0]);
|
||||
drft_init(&b->fft_look[1],ci->blocksizes[1]);
|
||||
|
||||
/* finish the codebooks */
|
||||
if(!ci->fullbooks){
|
||||
ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
|
||||
for(i=0;i<ci->books;i++)
|
||||
vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]);
|
||||
}
|
||||
|
||||
b->psy=_ogg_calloc(ci->psys,sizeof(*b->psy));
|
||||
for(i=0;i<ci->psys;i++){
|
||||
_vp_psy_init(b->psy+i,
|
||||
ci->psy_param[i],
|
||||
&ci->psy_g_param,
|
||||
ci->blocksizes[ci->psy_param[i]->blockflag]/2,
|
||||
vi->rate);
|
||||
}
|
||||
|
||||
v->analysisp=1;
|
||||
}else{
|
||||
/* finish the codebooks */
|
||||
if(!ci->fullbooks){
|
||||
ci->fullbooks=_ogg_calloc(ci->books,sizeof(*ci->fullbooks));
|
||||
for(i=0;i<ci->books;i++){
|
||||
vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
|
||||
/* decode codebooks are now standalone after init */
|
||||
vorbis_staticbook_destroy(ci->book_param[i]);
|
||||
ci->book_param[i]=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the storage vectors. blocksize[1] is small for encode,
|
||||
but the correct size for decode */
|
||||
v->pcm_storage=ci->blocksizes[1];
|
||||
v->pcm=_ogg_malloc(vi->channels*sizeof(*v->pcm));
|
||||
v->pcmret=_ogg_malloc(vi->channels*sizeof(*v->pcmret));
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcm[i]=_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
|
||||
}
|
||||
|
||||
/* all 1 (large block) or 0 (small block) */
|
||||
/* explicitly set for the sake of clarity */
|
||||
v->lW=0; /* previous window size */
|
||||
v->W=0; /* current window size */
|
||||
|
||||
/* all vector indexes */
|
||||
v->centerW=ci->blocksizes[1]/2;
|
||||
|
||||
v->pcm_current=v->centerW;
|
||||
|
||||
/* initialize all the backend lookups */
|
||||
b->flr=_ogg_calloc(ci->floors,sizeof(*b->flr));
|
||||
b->residue=_ogg_calloc(ci->residues,sizeof(*b->residue));
|
||||
|
||||
for(i=0;i<ci->floors;i++)
|
||||
b->flr[i]=_floor_P[ci->floor_type[i]]->
|
||||
look(v,ci->floor_param[i]);
|
||||
|
||||
for(i=0;i<ci->residues;i++)
|
||||
b->residue[i]=_residue_P[ci->residue_type[i]]->
|
||||
look(v,ci->residue_param[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* arbitrary settings and spec-mandated numbers get filled in here */
|
||||
int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
|
||||
private_state *b=NULL;
|
||||
|
||||
if(_vds_shared_init(v,vi,1))return 1;
|
||||
b=v->backend_state;
|
||||
b->psy_g_look=_vp_global_look(vi);
|
||||
|
||||
/* Initialize the envelope state storage */
|
||||
b->ve=_ogg_calloc(1,sizeof(*b->ve));
|
||||
_ve_envelope_init(b->ve,vi);
|
||||
|
||||
vorbis_bitrate_init(vi,&b->bms);
|
||||
|
||||
/* compressed audio packets start after the headers
|
||||
with sequence number 3 */
|
||||
v->sequence=3;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void vorbis_dsp_clear(vorbis_dsp_state *v){
|
||||
int i;
|
||||
if(v){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(vi?vi->codec_setup:NULL);
|
||||
private_state *b=v->backend_state;
|
||||
|
||||
if(b){
|
||||
|
||||
if(b->ve){
|
||||
_ve_envelope_clear(b->ve);
|
||||
_ogg_free(b->ve);
|
||||
}
|
||||
|
||||
if(b->transform[0]){
|
||||
mdct_clear(b->transform[0][0]);
|
||||
_ogg_free(b->transform[0][0]);
|
||||
_ogg_free(b->transform[0]);
|
||||
}
|
||||
if(b->transform[1]){
|
||||
mdct_clear(b->transform[1][0]);
|
||||
_ogg_free(b->transform[1][0]);
|
||||
_ogg_free(b->transform[1]);
|
||||
}
|
||||
|
||||
if(b->flr){
|
||||
if(ci)
|
||||
for(i=0;i<ci->floors;i++)
|
||||
_floor_P[ci->floor_type[i]]->
|
||||
free_look(b->flr[i]);
|
||||
_ogg_free(b->flr);
|
||||
}
|
||||
if(b->residue){
|
||||
if(ci)
|
||||
for(i=0;i<ci->residues;i++)
|
||||
_residue_P[ci->residue_type[i]]->
|
||||
free_look(b->residue[i]);
|
||||
_ogg_free(b->residue);
|
||||
}
|
||||
if(b->psy){
|
||||
if(ci)
|
||||
for(i=0;i<ci->psys;i++)
|
||||
_vp_psy_clear(b->psy+i);
|
||||
_ogg_free(b->psy);
|
||||
}
|
||||
|
||||
if(b->psy_g_look)_vp_global_free(b->psy_g_look);
|
||||
vorbis_bitrate_clear(&b->bms);
|
||||
|
||||
drft_clear(&b->fft_look[0]);
|
||||
drft_clear(&b->fft_look[1]);
|
||||
|
||||
}
|
||||
|
||||
if(v->pcm){
|
||||
if(vi)
|
||||
for(i=0;i<vi->channels;i++)
|
||||
if(v->pcm[i])_ogg_free(v->pcm[i]);
|
||||
_ogg_free(v->pcm);
|
||||
if(v->pcmret)_ogg_free(v->pcmret);
|
||||
}
|
||||
|
||||
if(b){
|
||||
/* free header, header1, header2 */
|
||||
if(b->header)_ogg_free(b->header);
|
||||
if(b->header1)_ogg_free(b->header1);
|
||||
if(b->header2)_ogg_free(b->header2);
|
||||
_ogg_free(b);
|
||||
}
|
||||
|
||||
memset(v,0,sizeof(*v));
|
||||
}
|
||||
}
|
||||
|
||||
float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
|
||||
int i;
|
||||
vorbis_info *vi=v->vi;
|
||||
private_state *b=v->backend_state;
|
||||
|
||||
/* free header, header1, header2 */
|
||||
if(b->header)_ogg_free(b->header);b->header=NULL;
|
||||
if(b->header1)_ogg_free(b->header1);b->header1=NULL;
|
||||
if(b->header2)_ogg_free(b->header2);b->header2=NULL;
|
||||
|
||||
/* Do we have enough storage space for the requested buffer? If not,
|
||||
expand the PCM (and envelope) storage */
|
||||
|
||||
if(v->pcm_current+vals>=v->pcm_storage){
|
||||
v->pcm_storage=v->pcm_current+vals*2;
|
||||
|
||||
for(i=0;i<vi->channels;i++){
|
||||
v->pcm[i]=_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcmret[i]=v->pcm[i]+v->pcm_current;
|
||||
|
||||
return(v->pcmret);
|
||||
}
|
||||
|
||||
static void _preextrapolate_helper(vorbis_dsp_state *v){
|
||||
int i;
|
||||
int order=32;
|
||||
float *lpc=alloca(order*sizeof(*lpc));
|
||||
float *work=alloca(v->pcm_current*sizeof(*work));
|
||||
long j;
|
||||
v->preextrapolate=1;
|
||||
|
||||
if(v->pcm_current-v->centerW>order*2){ /* safety */
|
||||
for(i=0;i<v->vi->channels;i++){
|
||||
/* need to run the extrapolation in reverse! */
|
||||
for(j=0;j<v->pcm_current;j++)
|
||||
work[j]=v->pcm[i][v->pcm_current-j-1];
|
||||
|
||||
/* prime as above */
|
||||
vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
|
||||
|
||||
/* run the predictor filter */
|
||||
vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
|
||||
order,
|
||||
work+v->pcm_current-v->centerW,
|
||||
v->centerW);
|
||||
|
||||
for(j=0;j<v->pcm_current;j++)
|
||||
v->pcm[i][v->pcm_current-j-1]=work[j];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* call with val<=0 to set eof */
|
||||
|
||||
int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
|
||||
if(vals<=0){
|
||||
int order=32;
|
||||
int i;
|
||||
float *lpc=alloca(order*sizeof(*lpc));
|
||||
|
||||
/* if it wasn't done earlier (very short sample) */
|
||||
if(!v->preextrapolate)
|
||||
_preextrapolate_helper(v);
|
||||
|
||||
/* We're encoding the end of the stream. Just make sure we have
|
||||
[at least] a few full blocks of zeroes at the end. */
|
||||
/* actually, we don't want zeroes; that could drop a large
|
||||
amplitude off a cliff, creating spread spectrum noise that will
|
||||
suck to encode. Extrapolate for the sake of cleanliness. */
|
||||
|
||||
vorbis_analysis_buffer(v,ci->blocksizes[1]*3);
|
||||
v->eofflag=v->pcm_current;
|
||||
v->pcm_current+=ci->blocksizes[1]*3;
|
||||
|
||||
for(i=0;i<vi->channels;i++){
|
||||
if(v->eofflag>order*2){
|
||||
/* extrapolate with LPC to fill in */
|
||||
long n;
|
||||
|
||||
/* make a predictor filter */
|
||||
n=v->eofflag;
|
||||
if(n>ci->blocksizes[1])n=ci->blocksizes[1];
|
||||
vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
|
||||
|
||||
/* run the predictor filter */
|
||||
vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
|
||||
v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
|
||||
}else{
|
||||
/* not enough data to extrapolate (unlikely to happen due to
|
||||
guarding the overlap, but bulletproof in case that
|
||||
assumtion goes away). zeroes will do. */
|
||||
memset(v->pcm[i]+v->eofflag,0,
|
||||
(v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
|
||||
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
if(v->pcm_current+vals>v->pcm_storage)
|
||||
return(OV_EINVAL);
|
||||
|
||||
v->pcm_current+=vals;
|
||||
|
||||
/* we may want to reverse extrapolate the beginning of a stream
|
||||
too... in case we're beginning on a cliff! */
|
||||
/* clumsy, but simple. It only runs once, so simple is good. */
|
||||
if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
|
||||
_preextrapolate_helper(v);
|
||||
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* do the deltas, envelope shaping, pre-echo and determine the size of
|
||||
the next block on which to continue analysis */
|
||||
int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
|
||||
int i;
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
private_state *b=v->backend_state;
|
||||
vorbis_look_psy_global *g=b->psy_g_look;
|
||||
long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
|
||||
|
||||
/* check to see if we're started... */
|
||||
if(!v->preextrapolate)return(0);
|
||||
|
||||
/* check to see if we're done... */
|
||||
if(v->eofflag==-1)return(0);
|
||||
|
||||
/* By our invariant, we have lW, W and centerW set. Search for
|
||||
the next boundary so we can determine nW (the next window size)
|
||||
which lets us compute the shape of the current block's window */
|
||||
|
||||
/* we do an envelope search even on a single blocksize; we may still
|
||||
be throwing more bits at impulses, and envelope search handles
|
||||
marking impulses too. */
|
||||
{
|
||||
long bp=_ve_envelope_search(v);
|
||||
if(bp==-1){
|
||||
|
||||
if(v->eofflag==0)return(0); /* not enough data currently to search for a
|
||||
full long block */
|
||||
v->nW=0;
|
||||
}else{
|
||||
|
||||
if(ci->blocksizes[0]==ci->blocksizes[1])
|
||||
v->nW=0;
|
||||
else
|
||||
v->nW=bp;
|
||||
}
|
||||
}
|
||||
|
||||
centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
|
||||
|
||||
{
|
||||
/* center of next block + next block maximum right side. */
|
||||
|
||||
long blockbound=centerNext+ci->blocksizes[v->nW]/2;
|
||||
if(v->pcm_current<blockbound)return(0); /* not enough data yet;
|
||||
although this check is
|
||||
less strict that the
|
||||
_ve_envelope_search,
|
||||
the search is not run
|
||||
if we only use one
|
||||
block size */
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* fill in the block. Note that for a short window, lW and nW are *short*
|
||||
regardless of actual settings in the stream */
|
||||
|
||||
_vorbis_block_ripcord(vb);
|
||||
vb->lW=v->lW;
|
||||
vb->W=v->W;
|
||||
vb->nW=v->nW;
|
||||
|
||||
if(v->W){
|
||||
if(!v->lW || !v->nW){
|
||||
vbi->blocktype=BLOCKTYPE_TRANSITION;
|
||||
/*fprintf(stderr,"-");*/
|
||||
}else{
|
||||
vbi->blocktype=BLOCKTYPE_LONG;
|
||||
/*fprintf(stderr,"_");*/
|
||||
}
|
||||
}else{
|
||||
if(_ve_envelope_mark(v)){
|
||||
vbi->blocktype=BLOCKTYPE_IMPULSE;
|
||||
/*fprintf(stderr,"|");*/
|
||||
|
||||
}else{
|
||||
vbi->blocktype=BLOCKTYPE_PADDING;
|
||||
/*fprintf(stderr,".");*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
vb->vd=v;
|
||||
vb->sequence=v->sequence++;
|
||||
vb->granulepos=v->granulepos;
|
||||
vb->pcmend=ci->blocksizes[v->W];
|
||||
|
||||
/* copy the vectors; this uses the local storage in vb */
|
||||
|
||||
/* this tracks 'strongest peak' for later psychoacoustics */
|
||||
/* moved to the global psy state; clean this mess up */
|
||||
if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
|
||||
g->ampmax=_vp_ampmax_decay(g->ampmax,v);
|
||||
vbi->ampmax=g->ampmax;
|
||||
|
||||
vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
|
||||
vbi->pcmdelay=_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
|
||||
for(i=0;i<vi->channels;i++){
|
||||
vbi->pcmdelay[i]=
|
||||
_vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
|
||||
memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
|
||||
vb->pcm[i]=vbi->pcmdelay[i]+beginW;
|
||||
|
||||
/* before we added the delay
|
||||
vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
|
||||
memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/* handle eof detection: eof==0 means that we've not yet received EOF
|
||||
eof>0 marks the last 'real' sample in pcm[]
|
||||
eof<0 'no more to do'; doesn't get here */
|
||||
|
||||
if(v->eofflag){
|
||||
if(v->centerW>=v->eofflag){
|
||||
v->eofflag=-1;
|
||||
vb->eofflag=1;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* advance storage vectors and clean up */
|
||||
{
|
||||
int new_centerNext=ci->blocksizes[1]/2;
|
||||
int movementW=centerNext-new_centerNext;
|
||||
|
||||
if(movementW>0){
|
||||
|
||||
_ve_envelope_shift(b->ve,movementW);
|
||||
v->pcm_current-=movementW;
|
||||
|
||||
for(i=0;i<vi->channels;i++)
|
||||
memmove(v->pcm[i],v->pcm[i]+movementW,
|
||||
v->pcm_current*sizeof(*v->pcm[i]));
|
||||
|
||||
|
||||
v->lW=v->W;
|
||||
v->W=v->nW;
|
||||
v->centerW=new_centerNext;
|
||||
|
||||
if(v->eofflag){
|
||||
v->eofflag-=movementW;
|
||||
if(v->eofflag<=0)v->eofflag=-1;
|
||||
/* do not add padding to end of stream! */
|
||||
if(v->centerW>=v->eofflag){
|
||||
v->granulepos+=movementW-(v->centerW-v->eofflag);
|
||||
}else{
|
||||
v->granulepos+=movementW;
|
||||
}
|
||||
}else{
|
||||
v->granulepos+=movementW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* done */
|
||||
return(1);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_restart(vorbis_dsp_state *v){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci;
|
||||
int hs;
|
||||
|
||||
if(!v->backend_state)return -1;
|
||||
if(!vi)return -1;
|
||||
ci=vi->codec_setup;
|
||||
if(!ci)return -1;
|
||||
hs=ci->halfrate_flag;
|
||||
|
||||
v->centerW=ci->blocksizes[1]>>(hs+1);
|
||||
v->pcm_current=v->centerW>>hs;
|
||||
|
||||
v->pcm_returned=-1;
|
||||
v->granulepos=-1;
|
||||
v->sequence=-1;
|
||||
v->eofflag=0;
|
||||
((private_state *)(v->backend_state))->sample_count=-1;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
|
||||
if(_vds_shared_init(v,vi,0)) return 1;
|
||||
vorbis_synthesis_restart(v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unlike in analysis, the window is only partially applied for each
|
||||
block. The time domain envelope is not yet handled at the point of
|
||||
calling (as it relies on the previous block). */
|
||||
|
||||
int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
private_state *b=v->backend_state;
|
||||
int hs=ci->halfrate_flag;
|
||||
int i,j;
|
||||
|
||||
if(!vb)return(OV_EINVAL);
|
||||
if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
|
||||
|
||||
v->lW=v->W;
|
||||
v->W=vb->W;
|
||||
v->nW=-1;
|
||||
|
||||
if((v->sequence==-1)||
|
||||
(v->sequence+1 != vb->sequence)){
|
||||
v->granulepos=-1; /* out of sequence; lose count */
|
||||
b->sample_count=-1;
|
||||
}
|
||||
|
||||
v->sequence=vb->sequence;
|
||||
|
||||
if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
|
||||
was called on block */
|
||||
int n=ci->blocksizes[v->W]>>(hs+1);
|
||||
int n0=ci->blocksizes[0]>>(hs+1);
|
||||
int n1=ci->blocksizes[1]>>(hs+1);
|
||||
|
||||
int thisCenter;
|
||||
int prevCenter;
|
||||
|
||||
v->glue_bits+=vb->glue_bits;
|
||||
v->time_bits+=vb->time_bits;
|
||||
v->floor_bits+=vb->floor_bits;
|
||||
v->res_bits+=vb->res_bits;
|
||||
|
||||
if(v->centerW){
|
||||
thisCenter=n1;
|
||||
prevCenter=0;
|
||||
}else{
|
||||
thisCenter=0;
|
||||
prevCenter=n1;
|
||||
}
|
||||
|
||||
/* v->pcm is now used like a two-stage double buffer. We don't want
|
||||
to have to constantly shift *or* adjust memory usage. Don't
|
||||
accept a new block until the old is shifted out */
|
||||
|
||||
for(j=0;j<vi->channels;j++){
|
||||
/* the overlap/add section */
|
||||
if(v->lW){
|
||||
if(v->W){
|
||||
/* large/large */
|
||||
float *w=_vorbis_window_get(b->window[1]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter;
|
||||
float *p=vb->pcm[j];
|
||||
for(i=0;i<n1;i++)
|
||||
pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i];
|
||||
}else{
|
||||
/* large/small */
|
||||
float *w=_vorbis_window_get(b->window[0]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
|
||||
float *p=vb->pcm[j];
|
||||
for(i=0;i<n0;i++)
|
||||
pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
|
||||
}
|
||||
}else{
|
||||
if(v->W){
|
||||
/* small/large */
|
||||
float *w=_vorbis_window_get(b->window[0]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter;
|
||||
float *p=vb->pcm[j]+n1/2-n0/2;
|
||||
for(i=0;i<n0;i++)
|
||||
pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
|
||||
for(;i<n1/2+n0/2;i++)
|
||||
pcm[i]=p[i];
|
||||
}else{
|
||||
/* small/small */
|
||||
float *w=_vorbis_window_get(b->window[0]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter;
|
||||
float *p=vb->pcm[j];
|
||||
for(i=0;i<n0;i++)
|
||||
pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* the copy section */
|
||||
{
|
||||
float *pcm=v->pcm[j]+thisCenter;
|
||||
float *p=vb->pcm[j]+n;
|
||||
for(i=0;i<n;i++)
|
||||
pcm[i]=p[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(v->centerW)
|
||||
v->centerW=0;
|
||||
else
|
||||
v->centerW=n1;
|
||||
|
||||
/* deal with initial packet state; we do this using the explicit
|
||||
pcm_returned==-1 flag otherwise we're sensitive to first block
|
||||
being short or long */
|
||||
|
||||
if(v->pcm_returned==-1){
|
||||
v->pcm_returned=thisCenter;
|
||||
v->pcm_current=thisCenter;
|
||||
}else{
|
||||
v->pcm_returned=prevCenter;
|
||||
v->pcm_current=prevCenter+
|
||||
((ci->blocksizes[v->lW]/4+
|
||||
ci->blocksizes[v->W]/4)>>hs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* track the frame number... This is for convenience, but also
|
||||
making sure our last packet doesn't end with added padding. If
|
||||
the last packet is partial, the number of samples we'll have to
|
||||
return will be past the vb->granulepos.
|
||||
|
||||
This is not foolproof! It will be confused if we begin
|
||||
decoding at the last page after a seek or hole. In that case,
|
||||
we don't have a starting point to judge where the last frame
|
||||
is. For this reason, vorbisfile will always try to make sure
|
||||
it reads the last two marked pages in proper sequence */
|
||||
|
||||
if(b->sample_count==-1){
|
||||
b->sample_count=0;
|
||||
}else{
|
||||
b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
|
||||
}
|
||||
|
||||
if(v->granulepos==-1){
|
||||
if(vb->granulepos!=-1){ /* only set if we have a position to set to */
|
||||
|
||||
v->granulepos=vb->granulepos;
|
||||
|
||||
/* is this a short page? */
|
||||
if(b->sample_count>v->granulepos){
|
||||
/* corner case; if this is both the first and last audio page,
|
||||
then spec says the end is cut, not beginning */
|
||||
if(vb->eofflag){
|
||||
/* trim the end */
|
||||
/* no preceeding granulepos; assume we started at zero (we'd
|
||||
have to in a short single-page stream) */
|
||||
/* granulepos could be -1 due to a seek, but that would result
|
||||
in a long count, not short count */
|
||||
|
||||
v->pcm_current-=(b->sample_count-v->granulepos)>>hs;
|
||||
}else{
|
||||
/* trim the beginning */
|
||||
v->pcm_returned+=(b->sample_count-v->granulepos)>>hs;
|
||||
if(v->pcm_returned>v->pcm_current)
|
||||
v->pcm_returned=v->pcm_current;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}else{
|
||||
v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
|
||||
if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
|
||||
|
||||
if(v->granulepos>vb->granulepos){
|
||||
long extra=v->granulepos-vb->granulepos;
|
||||
|
||||
if(extra)
|
||||
if(vb->eofflag){
|
||||
/* partial last frame. Strip the extra samples off */
|
||||
v->pcm_current-=extra>>hs;
|
||||
} /* else {Shouldn't happen *unless* the bitstream is out of
|
||||
spec. Either way, believe the bitstream } */
|
||||
} /* else {Shouldn't happen *unless* the bitstream is out of
|
||||
spec. Either way, believe the bitstream } */
|
||||
v->granulepos=vb->granulepos;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update, cleanup */
|
||||
|
||||
if(vb->eofflag)v->eofflag=1;
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/* pcm==NULL indicates we just want the pending samples, no more */
|
||||
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
|
||||
vorbis_info *vi=v->vi;
|
||||
|
||||
if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
|
||||
if(pcm){
|
||||
int i;
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
|
||||
*pcm=v->pcmret;
|
||||
}
|
||||
return(v->pcm_current-v->pcm_returned);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
|
||||
if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
|
||||
v->pcm_returned+=n;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* intended for use with a specific vorbisfile feature; we want access
|
||||
to the [usually synthetic/postextrapolated] buffer and lapping at
|
||||
the end of a decode cycle, specifically, a half-short-block worth.
|
||||
This funtion works like pcmout above, except it will also expose
|
||||
this implicit buffer data not normally decoded. */
|
||||
int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
int hs=ci->halfrate_flag;
|
||||
|
||||
int n=ci->blocksizes[v->W]>>(hs+1);
|
||||
int n0=ci->blocksizes[0]>>(hs+1);
|
||||
int n1=ci->blocksizes[1]>>(hs+1);
|
||||
int i,j;
|
||||
|
||||
if(v->pcm_returned<0)return 0;
|
||||
|
||||
/* our returned data ends at pcm_returned; because the synthesis pcm
|
||||
buffer is a two-fragment ring, that means our data block may be
|
||||
fragmented by buffering, wrapping or a short block not filling
|
||||
out a buffer. To simplify things, we unfragment if it's at all
|
||||
possibly needed. Otherwise, we'd need to call lapout more than
|
||||
once as well as hold additional dsp state. Opt for
|
||||
simplicity. */
|
||||
|
||||
/* centerW was advanced by blockin; it would be the center of the
|
||||
*next* block */
|
||||
if(v->centerW==n1){
|
||||
/* the data buffer wraps; swap the halves */
|
||||
/* slow, sure, small */
|
||||
for(j=0;j<vi->channels;j++){
|
||||
float *p=v->pcm[j];
|
||||
for(i=0;i<n1;i++){
|
||||
float temp=p[i];
|
||||
p[i]=p[i+n1];
|
||||
p[i+n1]=temp;
|
||||
}
|
||||
}
|
||||
|
||||
v->pcm_current-=n1;
|
||||
v->pcm_returned-=n1;
|
||||
v->centerW=0;
|
||||
}
|
||||
|
||||
/* solidify buffer into contiguous space */
|
||||
if((v->lW^v->W)==1){
|
||||
/* long/short or short/long */
|
||||
for(j=0;j<vi->channels;j++){
|
||||
float *s=v->pcm[j];
|
||||
float *d=v->pcm[j]+(n1-n0)/2;
|
||||
for(i=(n1+n0)/2-1;i>=0;--i)
|
||||
d[i]=s[i];
|
||||
}
|
||||
v->pcm_returned+=(n1-n0)/2;
|
||||
v->pcm_current+=(n1-n0)/2;
|
||||
}else{
|
||||
if(v->lW==0){
|
||||
/* short/short */
|
||||
for(j=0;j<vi->channels;j++){
|
||||
float *s=v->pcm[j];
|
||||
float *d=v->pcm[j]+n1-n0;
|
||||
for(i=n0-1;i>=0;--i)
|
||||
d[i]=s[i];
|
||||
}
|
||||
v->pcm_returned+=n1-n0;
|
||||
v->pcm_current+=n1-n0;
|
||||
}
|
||||
}
|
||||
|
||||
if(pcm){
|
||||
int i;
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
|
||||
*pcm=v->pcmret;
|
||||
}
|
||||
|
||||
return(n1+n-v->pcm_returned);
|
||||
|
||||
}
|
||||
|
||||
float *vorbis_window(vorbis_dsp_state *v,int W){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
int hs=ci->halfrate_flag;
|
||||
private_state *b=v->backend_state;
|
||||
|
||||
if(b->window[W]-1<0)return NULL;
|
||||
return _vorbis_window_get(b->window[W]-hs);
|
||||
}
|
||||
|
|
@ -0,0 +1,634 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic codebook pack/unpack/code/decode operations
|
||||
last mod: $Id: codebook.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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 *************/
|
||||
int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){
|
||||
long i,j;
|
||||
memset(s,0,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;
|
||||
|
||||
/* codeword ordering.... length ordered or unordered? */
|
||||
switch((int)oggpack_read(opb,1)){
|
||||
case 0:
|
||||
/* unordered */
|
||||
s->lengthlist=_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
|
||||
|
||||
/* allocated but unused entries? */
|
||||
if(oggpack_read(opb,1)){
|
||||
/* yes, unused entries */
|
||||
|
||||
for(i=0;i<s->entries;i++){
|
||||
if(oggpack_read(opb,1)){
|
||||
long num=oggpack_read(opb,5);
|
||||
if(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;
|
||||
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;
|
||||
for(j=0;j<num && i<s->entries;j++,i++)
|
||||
s->lengthlist[i]=length;
|
||||
length++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* EOF */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
{
|
||||
int quantvals=0;
|
||||
switch(s->maptype){
|
||||
case 1:
|
||||
quantvals=_book_maptype1_quantvals(s);
|
||||
break;
|
||||
case 2:
|
||||
quantvals=s->entries*s->dim;
|
||||
break;
|
||||
}
|
||||
|
||||
/* quantized values */
|
||||
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(0);
|
||||
|
||||
_errout:
|
||||
_eofout:
|
||||
vorbis_staticbook_clear(s);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* 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]);
|
||||
}
|
||||
|
||||
/* One the encode side, our vector writers are each designed for a
|
||||
specific purpose, and the encoder is not flexible without modification:
|
||||
|
||||
The LSP vector coder uses a single stage nearest-match with no
|
||||
interleave, so no step and no error return. This is specced by floor0
|
||||
and doesn't change.
|
||||
|
||||
Residue0 encoding interleaves, uses multiple stages, and each stage
|
||||
peels of a specific amount of resolution from a lattice (thus we want
|
||||
to match by threshold, not nearest match). Residue doesn't *have* to
|
||||
be encoded that way, but to change it, one will need to add more
|
||||
infrastructure on the encode side (decode side is specced and simpler) */
|
||||
|
||||
/* floor0 LSP (single stage, non interleaved, nearest match) */
|
||||
/* returns entry number and *modifies a* to the quantization value *****/
|
||||
int vorbis_book_errorv(codebook *book,float *a){
|
||||
int dim=book->dim,k;
|
||||
int best=_best(book,a,1);
|
||||
for(k=0;k<dim;k++)
|
||||
a[k]=(book->valuelist+best*dim)[k];
|
||||
return(best);
|
||||
}
|
||||
|
||||
/* returns the number of bits and *modifies a* to the quantization value *****/
|
||||
int vorbis_book_encodev(codebook *book,int best,float *a,oggpack_buffer *b){
|
||||
int k,dim=book->dim;
|
||||
for(k=0;k<dim;k++)
|
||||
a[k]=(book->valuelist+best*dim)[k];
|
||||
return(vorbis_book_encode(book,best,b));
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
#ifdef _V_SELFTEST
|
||||
/* Simple enough; pack a few candidate codebooks, unpack them. Code a
|
||||
number of vectors through (keeping track of the quantized values),
|
||||
and decode using the unpacked book. quantized version of in should
|
||||
exactly equal out */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vorbis/book/lsp20_0.vqh"
|
||||
#include "vorbis/book/res0a_13.vqh"
|
||||
#define TESTSIZE 40
|
||||
|
||||
float test1[TESTSIZE]={
|
||||
0.105939f,
|
||||
0.215373f,
|
||||
0.429117f,
|
||||
0.587974f,
|
||||
|
||||
0.181173f,
|
||||
0.296583f,
|
||||
0.515707f,
|
||||
0.715261f,
|
||||
|
||||
0.162327f,
|
||||
0.263834f,
|
||||
0.342876f,
|
||||
0.406025f,
|
||||
|
||||
0.103571f,
|
||||
0.223561f,
|
||||
0.368513f,
|
||||
0.540313f,
|
||||
|
||||
0.136672f,
|
||||
0.395882f,
|
||||
0.587183f,
|
||||
0.652476f,
|
||||
|
||||
0.114338f,
|
||||
0.417300f,
|
||||
0.525486f,
|
||||
0.698679f,
|
||||
|
||||
0.147492f,
|
||||
0.324481f,
|
||||
0.643089f,
|
||||
0.757582f,
|
||||
|
||||
0.139556f,
|
||||
0.215795f,
|
||||
0.324559f,
|
||||
0.399387f,
|
||||
|
||||
0.120236f,
|
||||
0.267420f,
|
||||
0.446940f,
|
||||
0.608760f,
|
||||
|
||||
0.115587f,
|
||||
0.287234f,
|
||||
0.571081f,
|
||||
0.708603f,
|
||||
};
|
||||
|
||||
float test3[TESTSIZE]={
|
||||
0,1,-2,3,4,-5,6,7,8,9,
|
||||
8,-2,7,-1,4,6,8,3,1,-9,
|
||||
10,11,12,13,14,15,26,17,18,19,
|
||||
30,-25,-30,-1,-5,-32,4,3,-2,0};
|
||||
|
||||
static_codebook *testlist[]={&_vq_book_lsp20_0,
|
||||
&_vq_book_res0a_13,NULL};
|
||||
float *testvec[]={test1,test3};
|
||||
|
||||
int main(){
|
||||
oggpack_buffer write;
|
||||
oggpack_buffer read;
|
||||
long ptr=0,i;
|
||||
oggpack_writeinit(&write);
|
||||
|
||||
fprintf(stderr,"Testing codebook abstraction...:\n");
|
||||
|
||||
while(testlist[ptr]){
|
||||
codebook c;
|
||||
static_codebook s;
|
||||
float *qv=alloca(sizeof(*qv)*TESTSIZE);
|
||||
float *iv=alloca(sizeof(*iv)*TESTSIZE);
|
||||
memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE);
|
||||
memset(iv,0,sizeof(*iv)*TESTSIZE);
|
||||
|
||||
fprintf(stderr,"\tpacking/coding %ld... ",ptr);
|
||||
|
||||
/* pack the codebook, write the testvector */
|
||||
oggpack_reset(&write);
|
||||
vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory
|
||||
we can write */
|
||||
vorbis_staticbook_pack(testlist[ptr],&write);
|
||||
fprintf(stderr,"Codebook size %ld bytes... ",oggpack_bytes(&write));
|
||||
for(i=0;i<TESTSIZE;i+=c.dim){
|
||||
int best=_best(&c,qv+i,1);
|
||||
vorbis_book_encodev(&c,best,qv+i,&write);
|
||||
}
|
||||
vorbis_book_clear(&c);
|
||||
|
||||
fprintf(stderr,"OK.\n");
|
||||
fprintf(stderr,"\tunpacking/decoding %ld... ",ptr);
|
||||
|
||||
/* transfer the write data to a read buffer and unpack/read */
|
||||
oggpack_readinit(&read,oggpack_get_buffer(&write),oggpack_bytes(&write));
|
||||
if(vorbis_staticbook_unpack(&read,&s)){
|
||||
fprintf(stderr,"Error unpacking codebook.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(vorbis_book_init_decode(&c,&s)){
|
||||
fprintf(stderr,"Error initializing codebook.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i=0;i<TESTSIZE;i+=c.dim)
|
||||
if(vorbis_book_decodev_set(&c,iv+i,&read,c.dim)==-1){
|
||||
fprintf(stderr,"Error reading codebook test data (EOP).\n");
|
||||
exit(1);
|
||||
}
|
||||
for(i=0;i<TESTSIZE;i++)
|
||||
if(fabs(qv[i]-iv[i])>.000001){
|
||||
fprintf(stderr,"read (%g) != written (%g) at position (%ld)\n",
|
||||
iv[i],qv[i],i);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr,"OK\n");
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* The above is the trivial stuff; now try unquantizing a log scale codebook */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,382 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis
|
||||
last mod: $Id: envelope.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
|
||||
#include "os.h"
|
||||
#include "scales.h"
|
||||
#include "envelope.h"
|
||||
#include "mdct.h"
|
||||
#include "misc.h"
|
||||
|
||||
void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
vorbis_info_psy_global *gi=&ci->psy_g_param;
|
||||
int ch=vi->channels;
|
||||
int i,j;
|
||||
int n=e->winlength=128;
|
||||
e->searchstep=64; /* not random */
|
||||
|
||||
e->minenergy=gi->preecho_minenergy;
|
||||
e->ch=ch;
|
||||
e->storage=128;
|
||||
e->cursor=ci->blocksizes[1]/2;
|
||||
e->mdct_win=_ogg_calloc(n,sizeof(*e->mdct_win));
|
||||
mdct_init(&e->mdct,n);
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
e->mdct_win[i]=sin(i/(n-1.)*M_PI);
|
||||
e->mdct_win[i]*=e->mdct_win[i];
|
||||
}
|
||||
|
||||
/* magic follows */
|
||||
e->band[0].begin=2; e->band[0].end=4;
|
||||
e->band[1].begin=4; e->band[1].end=5;
|
||||
e->band[2].begin=6; e->band[2].end=6;
|
||||
e->band[3].begin=9; e->band[3].end=8;
|
||||
e->band[4].begin=13; e->band[4].end=8;
|
||||
e->band[5].begin=17; e->band[5].end=8;
|
||||
e->band[6].begin=22; e->band[6].end=8;
|
||||
|
||||
for(j=0;j<VE_BANDS;j++){
|
||||
n=e->band[j].end;
|
||||
e->band[j].window=_ogg_malloc(n*sizeof(*e->band[0].window));
|
||||
for(i=0;i<n;i++){
|
||||
e->band[j].window[i]=sin((i+.5)/n*M_PI);
|
||||
e->band[j].total+=e->band[j].window[i];
|
||||
}
|
||||
e->band[j].total=1./e->band[j].total;
|
||||
}
|
||||
|
||||
e->filter=_ogg_calloc(VE_BANDS*ch,sizeof(*e->filter));
|
||||
e->mark=_ogg_calloc(e->storage,sizeof(*e->mark));
|
||||
|
||||
}
|
||||
|
||||
void _ve_envelope_clear(envelope_lookup *e){
|
||||
int i;
|
||||
mdct_clear(&e->mdct);
|
||||
for(i=0;i<VE_BANDS;i++)
|
||||
_ogg_free(e->band[i].window);
|
||||
_ogg_free(e->mdct_win);
|
||||
_ogg_free(e->filter);
|
||||
_ogg_free(e->mark);
|
||||
memset(e,0,sizeof(*e));
|
||||
}
|
||||
|
||||
/* fairly straight threshhold-by-band based until we find something
|
||||
that works better and isn't patented. */
|
||||
|
||||
static int _ve_amp(envelope_lookup *ve,
|
||||
vorbis_info_psy_global *gi,
|
||||
float *data,
|
||||
envelope_band *bands,
|
||||
envelope_filter_state *filters,
|
||||
long pos){
|
||||
long n=ve->winlength;
|
||||
int ret=0;
|
||||
long i,j;
|
||||
float decay;
|
||||
|
||||
/* we want to have a 'minimum bar' for energy, else we're just
|
||||
basing blocks on quantization noise that outweighs the signal
|
||||
itself (for low power signals) */
|
||||
|
||||
float minV=ve->minenergy;
|
||||
float *vec=alloca(n*sizeof(*vec));
|
||||
|
||||
/* stretch is used to gradually lengthen the number of windows
|
||||
considered prevoius-to-potential-trigger */
|
||||
int stretch=max(VE_MINSTRETCH,ve->stretch/2);
|
||||
float penalty=gi->stretch_penalty-(ve->stretch/2-VE_MINSTRETCH);
|
||||
if(penalty<0.f)penalty=0.f;
|
||||
if(penalty>gi->stretch_penalty)penalty=gi->stretch_penalty;
|
||||
|
||||
/*_analysis_output_always("lpcm",seq2,data,n,0,0,
|
||||
totalshift+pos*ve->searchstep);*/
|
||||
|
||||
/* window and transform */
|
||||
for(i=0;i<n;i++)
|
||||
vec[i]=data[i]*ve->mdct_win[i];
|
||||
mdct_forward(&ve->mdct,vec,vec);
|
||||
|
||||
/*_analysis_output_always("mdct",seq2,vec,n/2,0,1,0); */
|
||||
|
||||
/* near-DC spreading function; this has nothing to do with
|
||||
psychoacoustics, just sidelobe leakage and window size */
|
||||
{
|
||||
float temp=vec[0]*vec[0]+.7*vec[1]*vec[1]+.2*vec[2]*vec[2];
|
||||
int ptr=filters->nearptr;
|
||||
|
||||
/* the accumulation is regularly refreshed from scratch to avoid
|
||||
floating point creep */
|
||||
if(ptr==0){
|
||||
decay=filters->nearDC_acc=filters->nearDC_partialacc+temp;
|
||||
filters->nearDC_partialacc=temp;
|
||||
}else{
|
||||
decay=filters->nearDC_acc+=temp;
|
||||
filters->nearDC_partialacc+=temp;
|
||||
}
|
||||
filters->nearDC_acc-=filters->nearDC[ptr];
|
||||
filters->nearDC[ptr]=temp;
|
||||
|
||||
decay*=(1./(VE_NEARDC+1));
|
||||
filters->nearptr++;
|
||||
if(filters->nearptr>=VE_NEARDC)filters->nearptr=0;
|
||||
decay=todB(&decay)*.5-15.f;
|
||||
}
|
||||
|
||||
/* perform spreading and limiting, also smooth the spectrum. yes,
|
||||
the MDCT results in all real coefficients, but it still *behaves*
|
||||
like real/imaginary pairs */
|
||||
for(i=0;i<n/2;i+=2){
|
||||
float val=vec[i]*vec[i]+vec[i+1]*vec[i+1];
|
||||
val=todB(&val)*.5f;
|
||||
if(val<decay)val=decay;
|
||||
if(val<minV)val=minV;
|
||||
vec[i>>1]=val;
|
||||
decay-=8.;
|
||||
}
|
||||
|
||||
/*_analysis_output_always("spread",seq2++,vec,n/4,0,0,0);*/
|
||||
|
||||
/* perform preecho/postecho triggering by band */
|
||||
for(j=0;j<VE_BANDS;j++){
|
||||
float acc=0.;
|
||||
float valmax,valmin;
|
||||
|
||||
/* accumulate amplitude */
|
||||
for(i=0;i<bands[j].end;i++)
|
||||
acc+=vec[i+bands[j].begin]*bands[j].window[i];
|
||||
|
||||
acc*=bands[j].total;
|
||||
|
||||
/* convert amplitude to delta */
|
||||
{
|
||||
int p,this=filters[j].ampptr;
|
||||
float postmax,postmin,premax=-99999.f,premin=99999.f;
|
||||
|
||||
p=this;
|
||||
p--;
|
||||
if(p<0)p+=VE_AMP;
|
||||
postmax=max(acc,filters[j].ampbuf[p]);
|
||||
postmin=min(acc,filters[j].ampbuf[p]);
|
||||
|
||||
for(i=0;i<stretch;i++){
|
||||
p--;
|
||||
if(p<0)p+=VE_AMP;
|
||||
premax=max(premax,filters[j].ampbuf[p]);
|
||||
premin=min(premin,filters[j].ampbuf[p]);
|
||||
}
|
||||
|
||||
valmin=postmin-premin;
|
||||
valmax=postmax-premax;
|
||||
|
||||
/*filters[j].markers[pos]=valmax;*/
|
||||
filters[j].ampbuf[this]=acc;
|
||||
filters[j].ampptr++;
|
||||
if(filters[j].ampptr>=VE_AMP)filters[j].ampptr=0;
|
||||
}
|
||||
|
||||
/* look at min/max, decide trigger */
|
||||
if(valmax>gi->preecho_thresh[j]+penalty){
|
||||
ret|=1;
|
||||
ret|=4;
|
||||
}
|
||||
if(valmin<gi->postecho_thresh[j]-penalty)ret|=2;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int seq=0;
|
||||
static ogg_int64_t totalshift=-1024;
|
||||
#endif
|
||||
|
||||
long _ve_envelope_search(vorbis_dsp_state *v){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
vorbis_info_psy_global *gi=&ci->psy_g_param;
|
||||
envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
|
||||
long i,j;
|
||||
|
||||
int first=ve->current/ve->searchstep;
|
||||
int last=v->pcm_current/ve->searchstep-VE_WIN;
|
||||
if(first<0)first=0;
|
||||
|
||||
/* make sure we have enough storage to match the PCM */
|
||||
if(last+VE_WIN+VE_POST>ve->storage){
|
||||
ve->storage=last+VE_WIN+VE_POST; /* be sure */
|
||||
ve->mark=_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark));
|
||||
}
|
||||
|
||||
for(j=first;j<last;j++){
|
||||
int ret=0;
|
||||
|
||||
ve->stretch++;
|
||||
if(ve->stretch>VE_MAXSTRETCH*2)
|
||||
ve->stretch=VE_MAXSTRETCH*2;
|
||||
|
||||
for(i=0;i<ve->ch;i++){
|
||||
float *pcm=v->pcm[i]+ve->searchstep*(j);
|
||||
ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS,j);
|
||||
}
|
||||
|
||||
ve->mark[j+VE_POST]=0;
|
||||
if(ret&1){
|
||||
ve->mark[j]=1;
|
||||
ve->mark[j+1]=1;
|
||||
}
|
||||
|
||||
if(ret&2){
|
||||
ve->mark[j]=1;
|
||||
if(j>0)ve->mark[j-1]=1;
|
||||
}
|
||||
|
||||
if(ret&4)ve->stretch=-1;
|
||||
}
|
||||
|
||||
ve->current=last*ve->searchstep;
|
||||
|
||||
{
|
||||
long centerW=v->centerW;
|
||||
long testW=
|
||||
centerW+
|
||||
ci->blocksizes[v->W]/4+
|
||||
ci->blocksizes[1]/2+
|
||||
ci->blocksizes[0]/4;
|
||||
|
||||
j=ve->cursor;
|
||||
|
||||
while(j<ve->current-(ve->searchstep)){/* account for postecho
|
||||
working back one window */
|
||||
if(j>=testW)return(1);
|
||||
|
||||
ve->cursor=j;
|
||||
|
||||
if(ve->mark[j/ve->searchstep]){
|
||||
if(j>centerW){
|
||||
|
||||
#if 0
|
||||
if(j>ve->curmark){
|
||||
float *marker=alloca(v->pcm_current*sizeof(*marker));
|
||||
int l,m;
|
||||
memset(marker,0,sizeof(*marker)*v->pcm_current);
|
||||
fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n",
|
||||
seq,
|
||||
(totalshift+ve->cursor)/44100.,
|
||||
(totalshift+j)/44100.);
|
||||
_analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift);
|
||||
_analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift);
|
||||
|
||||
_analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift);
|
||||
_analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift);
|
||||
|
||||
for(m=0;m<VE_BANDS;m++){
|
||||
char buf[80];
|
||||
sprintf(buf,"delL%d",m);
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m].markers[l]*.1;
|
||||
_analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
|
||||
}
|
||||
|
||||
for(m=0;m<VE_BANDS;m++){
|
||||
char buf[80];
|
||||
sprintf(buf,"delR%d",m);
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m+VE_BANDS].markers[l]*.1;
|
||||
_analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
|
||||
}
|
||||
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->mark[l]*.4;
|
||||
_analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift);
|
||||
|
||||
|
||||
seq++;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
ve->curmark=j;
|
||||
if(j>=testW)return(1);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
j+=ve->searchstep;
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int _ve_envelope_mark(vorbis_dsp_state *v){
|
||||
envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
long centerW=v->centerW;
|
||||
long beginW=centerW-ci->blocksizes[v->W]/4;
|
||||
long endW=centerW+ci->blocksizes[v->W]/4;
|
||||
if(v->W){
|
||||
beginW-=ci->blocksizes[v->lW]/4;
|
||||
endW+=ci->blocksizes[v->nW]/4;
|
||||
}else{
|
||||
beginW-=ci->blocksizes[0]/4;
|
||||
endW+=ci->blocksizes[0]/4;
|
||||
}
|
||||
|
||||
if(ve->curmark>=beginW && ve->curmark<endW)return(1);
|
||||
{
|
||||
long first=beginW/ve->searchstep;
|
||||
long last=endW/ve->searchstep;
|
||||
long i;
|
||||
for(i=first;i<last;i++)
|
||||
if(ve->mark[i])return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void _ve_envelope_shift(envelope_lookup *e,long shift){
|
||||
int smallsize=e->current/e->searchstep+VE_POST; /* adjust for placing marks
|
||||
ahead of ve->current */
|
||||
int smallshift=shift/e->searchstep;
|
||||
|
||||
memmove(e->mark,e->mark+smallshift,(smallsize-smallshift)*sizeof(*e->mark));
|
||||
|
||||
#if 0
|
||||
for(i=0;i<VE_BANDS*e->ch;i++)
|
||||
memmove(e->filter[i].markers,
|
||||
e->filter[i].markers+smallshift,
|
||||
(1024-smallshift)*sizeof(*(*e->filter).markers));
|
||||
totalshift+=shift;
|
||||
#endif
|
||||
|
||||
e->current-=shift;
|
||||
if(e->curmark>=0)
|
||||
e->curmark-=shift;
|
||||
e->cursor-=shift;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,223 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: floor backend 0 implementation
|
||||
last mod: $Id: floor0.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "lpc.h"
|
||||
#include "lsp.h"
|
||||
#include "codebook.h"
|
||||
#include "scales.h"
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
int ln;
|
||||
int m;
|
||||
int **linearmap;
|
||||
int n[2];
|
||||
|
||||
vorbis_info_floor0 *vi;
|
||||
|
||||
long bits;
|
||||
long frames;
|
||||
} vorbis_look_floor0;
|
||||
|
||||
|
||||
/***********************************************/
|
||||
|
||||
static void floor0_free_info(vorbis_info_floor *i){
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
|
||||
if(info){
|
||||
memset(info,0,sizeof(*info));
|
||||
_ogg_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
static void floor0_free_look(vorbis_look_floor *i){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
if(look){
|
||||
|
||||
if(look->linearmap){
|
||||
|
||||
if(look->linearmap[0])_ogg_free(look->linearmap[0]);
|
||||
if(look->linearmap[1])_ogg_free(look->linearmap[1]);
|
||||
|
||||
_ogg_free(look->linearmap);
|
||||
}
|
||||
memset(look,0,sizeof(*look));
|
||||
_ogg_free(look);
|
||||
}
|
||||
}
|
||||
|
||||
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
int j;
|
||||
|
||||
vorbis_info_floor0 *info=_ogg_malloc(sizeof(*info));
|
||||
info->order=oggpack_read(opb,8);
|
||||
info->rate=oggpack_read(opb,16);
|
||||
info->barkmap=oggpack_read(opb,16);
|
||||
info->ampbits=oggpack_read(opb,6);
|
||||
info->ampdB=oggpack_read(opb,8);
|
||||
info->numbooks=oggpack_read(opb,4)+1;
|
||||
|
||||
if(info->order<1)goto err_out;
|
||||
if(info->rate<1)goto err_out;
|
||||
if(info->barkmap<1)goto err_out;
|
||||
if(info->numbooks<1)goto err_out;
|
||||
|
||||
for(j=0;j<info->numbooks;j++){
|
||||
info->books[j]=oggpack_read(opb,8);
|
||||
if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
|
||||
}
|
||||
return(info);
|
||||
|
||||
err_out:
|
||||
floor0_free_info(info);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* initialize Bark scale and normalization lookups. We could do this
|
||||
with static tables, but Vorbis allows a number of possible
|
||||
combinations, so it's best to do it computationally.
|
||||
|
||||
The below is authoritative in terms of defining scale mapping.
|
||||
Note that the scale depends on the sampling rate as well as the
|
||||
linear block and mapping sizes */
|
||||
|
||||
static void floor0_map_lazy_init(vorbis_block *vb,
|
||||
vorbis_info_floor *infoX,
|
||||
vorbis_look_floor0 *look){
|
||||
if(!look->linearmap[vb->W]){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
|
||||
int W=vb->W;
|
||||
int n=ci->blocksizes[W]/2,j;
|
||||
|
||||
/* we choose a scaling constant so that:
|
||||
floor(bark(rate/2-1)*C)=mapped-1
|
||||
floor(bark(rate/2)*C)=mapped */
|
||||
float scale=look->ln/toBARK(info->rate/2.f);
|
||||
|
||||
/* the mapping from a linear scale to a smaller bark scale is
|
||||
straightforward. We do *not* make sure that the linear mapping
|
||||
does not skip bark-scale bins; the decoder simply skips them and
|
||||
the encoder may do what it wishes in filling them. They're
|
||||
necessary in some mapping combinations to keep the scale spacing
|
||||
accurate */
|
||||
look->linearmap[W]=_ogg_malloc((n+1)*sizeof(**look->linearmap));
|
||||
for(j=0;j<n;j++){
|
||||
int val=floor( toBARK((info->rate/2.f)/n*j)
|
||||
*scale); /* bark numbers represent band edges */
|
||||
if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
|
||||
look->linearmap[W][j]=val;
|
||||
}
|
||||
look->linearmap[W][j]=-1;
|
||||
look->n[W]=n;
|
||||
}
|
||||
}
|
||||
|
||||
static vorbis_look_floor *floor0_look(vorbis_dsp_state *vd,
|
||||
vorbis_info_floor *i){
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
|
||||
vorbis_look_floor0 *look=_ogg_calloc(1,sizeof(*look));
|
||||
look->m=info->order;
|
||||
look->ln=info->barkmap;
|
||||
look->vi=info;
|
||||
|
||||
look->linearmap=_ogg_calloc(2,sizeof(*look->linearmap));
|
||||
|
||||
return look;
|
||||
}
|
||||
|
||||
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
vorbis_info_floor0 *info=look->vi;
|
||||
int j,k;
|
||||
|
||||
int ampraw=oggpack_read(&vb->opb,info->ampbits);
|
||||
if(ampraw>0){ /* also handles the -1 out of data case */
|
||||
long maxval=(1<<info->ampbits)-1;
|
||||
float amp=(float)ampraw/maxval*info->ampdB;
|
||||
int booknum=oggpack_read(&vb->opb,_ilog(info->numbooks));
|
||||
|
||||
if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
|
||||
codec_setup_info *ci=vb->vd->vi->codec_setup;
|
||||
codebook *b=ci->fullbooks+info->books[booknum];
|
||||
float last=0.f;
|
||||
|
||||
/* the additional b->dim is a guard against any possible stack
|
||||
smash; b->dim is provably more than we can overflow the
|
||||
vector */
|
||||
float *lsp=_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
|
||||
|
||||
for(j=0;j<look->m;j+=b->dim)
|
||||
if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
|
||||
for(j=0;j<look->m;){
|
||||
for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
|
||||
last=lsp[j-1];
|
||||
}
|
||||
|
||||
lsp[look->m]=amp;
|
||||
return(lsp);
|
||||
}
|
||||
}
|
||||
eop:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
|
||||
void *memo,float *out){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
vorbis_info_floor0 *info=look->vi;
|
||||
|
||||
floor0_map_lazy_init(vb,info,look);
|
||||
|
||||
if(memo){
|
||||
float *lsp=(float *)memo;
|
||||
float amp=lsp[look->m];
|
||||
|
||||
/* take the coefficients back to a spectral envelope curve */
|
||||
vorbis_lsp_to_curve(out,
|
||||
look->linearmap[vb->W],
|
||||
look->n[vb->W],
|
||||
look->ln,
|
||||
lsp,look->m,amp,(float)info->ampdB);
|
||||
return(1);
|
||||
}
|
||||
memset(out,0,sizeof(*out)*look->n[vb->W]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* export hooks */
|
||||
vorbis_func_floor floor0_exportbundle={
|
||||
NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
|
||||
&floor0_free_look,&floor0_inverse1,&floor0_inverse2
|
||||
};
|
||||
|
||||
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,644 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: maintain the info structure, info <-> header packets
|
||||
last mod: $Id: info.c 13293 2007-07-24 00:09:47Z 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"
|
||||
|
||||
/* 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,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,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, char *tag, char *contents){
|
||||
char *comment=alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
|
||||
strcpy(comment, tag);
|
||||
strcat(comment, "=");
|
||||
strcat(comment, contents);
|
||||
vorbis_comment_add(vc, comment);
|
||||
}
|
||||
|
||||
/* This is more or less the same as strncasecmp - but that doesn't exist
|
||||
* everywhere, and this is a fairly trivial function, so we include it */
|
||||
static int tagcompare(const char *s1, const char *s2, int n){
|
||||
int c=0;
|
||||
while(c < n){
|
||||
if(toupper(s1[c]) != toupper(s2[c]))
|
||||
return !0;
|
||||
c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count){
|
||||
long i;
|
||||
int found = 0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = alloca(taglen+ 1);
|
||||
|
||||
strcpy(fulltag, tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
|
||||
if(count == found)
|
||||
/* We return a pointer to the data, not a copy */
|
||||
return vc->user_comments[i] + taglen;
|
||||
else
|
||||
found++;
|
||||
}
|
||||
}
|
||||
return NULL; /* didn't find anything */
|
||||
}
|
||||
|
||||
int vorbis_comment_query_count(vorbis_comment *vc, char *tag){
|
||||
int i,count=0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = alloca(taglen+1);
|
||||
strcpy(fulltag,tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(!tagcompare(vc->user_comments[i], fulltag, taglen))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void vorbis_comment_clear(vorbis_comment *vc){
|
||||
if(vc){
|
||||
long i;
|
||||
for(i=0;i<vc->comments;i++)
|
||||
if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
|
||||
if(vc->user_comments)_ogg_free(vc->user_comments);
|
||||
if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
|
||||
if(vc->vendor)_ogg_free(vc->vendor);
|
||||
memset(vc,0,sizeof(*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;
|
||||
vc->vendor=_ogg_calloc(vendorlen+1,1);
|
||||
_v_readstring(opb,vc->vendor,vendorlen);
|
||||
vc->comments=oggpack_read(opb,32);
|
||||
if(vc->comments<0)goto err_out;
|
||||
vc->user_comments=_ogg_calloc(vc->comments+1,sizeof(*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;
|
||||
vc->comment_lengths[i]=len;
|
||||
vc->user_comments[i]=_ogg_calloc(len+1,1);
|
||||
_v_readstring(opb,vc->user_comments[i],len);
|
||||
}
|
||||
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_comment_clear(vc);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
/* all of the real encoding details are here. The modes, books,
|
||||
everything */
|
||||
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
int i;
|
||||
if(!ci)return(OV_EFAULT);
|
||||
|
||||
/* codebooks */
|
||||
ci->books=oggpack_read(opb,8)+1;
|
||||
/*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
|
||||
for(i=0;i<ci->books;i++){
|
||||
ci->book_param[i]=_ogg_calloc(1,sizeof(*ci->book_param[i]));
|
||||
if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
|
||||
}
|
||||
|
||||
/* time backend settings; hooks are unused */
|
||||
{
|
||||
int times=oggpack_read(opb,6)+1;
|
||||
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;
|
||||
/*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
|
||||
/*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
|
||||
for(i=0;i<ci->floors;i++){
|
||||
ci->floor_type[i]=oggpack_read(opb,16);
|
||||
if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
|
||||
ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
|
||||
if(!ci->floor_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* residue backend settings */
|
||||
ci->residues=oggpack_read(opb,6)+1;
|
||||
/*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
|
||||
/*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
|
||||
for(i=0;i<ci->residues;i++){
|
||||
ci->residue_type[i]=oggpack_read(opb,16);
|
||||
if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
|
||||
ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
|
||||
if(!ci->residue_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* map backend settings */
|
||||
ci->maps=oggpack_read(opb,6)+1;
|
||||
/*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
|
||||
/*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
|
||||
for(i=0;i<ci->maps;i++){
|
||||
ci->map_type[i]=oggpack_read(opb,16);
|
||||
if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
|
||||
ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
|
||||
if(!ci->map_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* mode settings */
|
||||
ci->modes=oggpack_read(opb,6)+1;
|
||||
/*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
|
||||
for(i=0;i<ci->modes;i++){
|
||||
ci->mode_param[i]=_ogg_calloc(1,sizeof(*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(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){
|
||||
char temp[]="Xiph.Org libVorbis I 20070622";
|
||||
int bytes = strlen(temp);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(opb,0x03,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* vendor */
|
||||
oggpack_write(opb,bytes,32);
|
||||
_v_writestring(opb,temp, 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:
|
||||
oggpack_writeclear(&opb);
|
||||
memset(op,0,sizeof(*op));
|
||||
memset(op_comm,0,sizeof(*op_comm));
|
||||
memset(op_code,0,sizeof(*op_code));
|
||||
|
||||
if(b){
|
||||
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>=0)
|
||||
return((double)granulepos/v->vi->rate);
|
||||
return(-1);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
last mod: $Id: lookup.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include "lookup.h"
|
||||
#include "lookup_data.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
float vorbis_coslook(float a){
|
||||
double d=a*(.31830989*(float)COS_LOOKUP_SZ);
|
||||
int i=vorbis_ftoi(d-.5);
|
||||
|
||||
return COS_LOOKUP[i]+ (d-i)*(COS_LOOKUP[i+1]-COS_LOOKUP[i]);
|
||||
}
|
||||
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
float vorbis_invsqlook(float a){
|
||||
double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
|
||||
int i=vorbis_ftoi(d-.5f);
|
||||
return INVSQ_LOOKUP[i]+ (d-i)*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]);
|
||||
}
|
||||
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
float vorbis_invsq2explook(int a){
|
||||
return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN];
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
float vorbis_fromdBlook(float a){
|
||||
int i=vorbis_ftoi(a*((float)(-(1<<FROMdB2_SHIFT)))-.5f);
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
|
||||
16.16 format
|
||||
|
||||
returns in m.8 format */
|
||||
long vorbis_invsqlook_i(long a,long e){
|
||||
long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
|
||||
long d=(a&INVSQ_LOOKUP_I_MASK)<<(16-INVSQ_LOOKUP_I_SHIFT); /* 0.16 */
|
||||
long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
|
||||
(((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */
|
||||
d)>>16); /* result 1.16 */
|
||||
|
||||
e+=32;
|
||||
if(e&1)val=(val*5792)>>13; /* multiply val by 1/sqrt(2) */
|
||||
e=(e>>1)-8;
|
||||
|
||||
return(val>>e);
|
||||
}
|
||||
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
/* a is in n.12 format */
|
||||
float vorbis_fromdBlook_i(long a){
|
||||
int i=(-a)>>(12-FROMdB2_SHIFT);
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
|
||||
long vorbis_coslook_i(long a){
|
||||
int i=a>>COS_LOOKUP_I_SHIFT;
|
||||
int d=a&COS_LOOKUP_I_MASK;
|
||||
return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
|
||||
COS_LOOKUP_I_SHIFT);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,149 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
last mod: $Id: lpc.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Some of these routines (autocorrelator, LPC coefficient estimator)
|
||||
are derived from code written by Jutta Degener and Carsten Bormann;
|
||||
thus we include their copyright below. The entirety of this file
|
||||
is freely redistributable on the condition that both of these
|
||||
copyright notices are preserved without modification. */
|
||||
|
||||
/* Preserved Copyright: *********************************************/
|
||||
|
||||
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universita"t Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universita"t
|
||||
Berlin are deemed to have made any representations as to the
|
||||
suitability of this software for any purpose nor are held responsible
|
||||
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
|
||||
THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "os.h"
|
||||
#include "smallft.h"
|
||||
#include "lpc.h"
|
||||
#include "scales.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* Autocorrelation LPC coeff generation algorithm invented by
|
||||
N. Levinson in 1947, modified by J. Durbin in 1959. */
|
||||
|
||||
/* Input : n elements of time doamin data
|
||||
Output: m lpc coefficients, excitation energy */
|
||||
|
||||
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
|
||||
double *aut=alloca(sizeof(*aut)*(m+1));
|
||||
double *lpc=alloca(sizeof(*lpc)*(m));
|
||||
double error;
|
||||
int i,j;
|
||||
|
||||
/* autocorrelation, p+1 lag coefficients */
|
||||
j=m+1;
|
||||
while(j--){
|
||||
double d=0; /* double needed for accumulator depth */
|
||||
for(i=j;i<n;i++)d+=(double)data[i]*data[i-j];
|
||||
aut[j]=d;
|
||||
}
|
||||
|
||||
/* Generate lpc coefficients from autocorr values */
|
||||
|
||||
error=aut[0];
|
||||
|
||||
for(i=0;i<m;i++){
|
||||
double r= -aut[i+1];
|
||||
|
||||
if(error==0){
|
||||
memset(lpci,0,m*sizeof(*lpci));
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Sum up this iteration's reflection coefficient; note that in
|
||||
Vorbis we don't save it. If anyone wants to recycle this code
|
||||
and needs reflection coefficients, save the results of 'r' from
|
||||
each iteration. */
|
||||
|
||||
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
|
||||
r/=error;
|
||||
|
||||
/* Update LPC coefficients and total error */
|
||||
|
||||
lpc[i]=r;
|
||||
for(j=0;j<i/2;j++){
|
||||
double tmp=lpc[j];
|
||||
|
||||
lpc[j]+=r*lpc[i-1-j];
|
||||
lpc[i-1-j]+=r*tmp;
|
||||
}
|
||||
if(i%2)lpc[j]+=lpc[j]*r;
|
||||
|
||||
error*=1.f-r*r;
|
||||
}
|
||||
|
||||
for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
|
||||
|
||||
/* we need the error value to know how big an impulse to hit the
|
||||
filter with later */
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||
float *data,long n){
|
||||
|
||||
/* in: coeff[0...m-1] LPC coefficients
|
||||
prime[0...m-1] initial values (allocated size of n+m-1)
|
||||
out: data[0...n-1] data samples */
|
||||
|
||||
long i,j,o,p;
|
||||
float y;
|
||||
float *work=alloca(sizeof(*work)*(m+n));
|
||||
|
||||
if(!prime)
|
||||
for(i=0;i<m;i++)
|
||||
work[i]=0.f;
|
||||
else
|
||||
for(i=0;i<m;i++)
|
||||
work[i]=prime[i];
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
y=0;
|
||||
o=i;
|
||||
p=m;
|
||||
for(j=0;j<m;j++)
|
||||
y-=work[o++]*coeff[--p];
|
||||
|
||||
data[i]=work[o]=y;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LSP (also called LSF) conversion routines
|
||||
last mod: $Id: lsp.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
The LSP generation code is taken (with minimal modification and a
|
||||
few bugfixes) from "On the Computation of the LSP Frequencies" by
|
||||
Joseph Rothweiler (see http://www.rothweiler.us for contact info).
|
||||
The paper is available at:
|
||||
|
||||
http://www.myown1.com/joe/lsf
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Note that the lpc-lsp conversion finds the roots of polynomial with
|
||||
an iterative root polisher (CACM algorithm 283). It *is* possible
|
||||
to confuse this algorithm into not converging; that should only
|
||||
happen with absurdly closely spaced roots (very sharp peaks in the
|
||||
LPC f response) which in turn should be impossible in our use of
|
||||
the code. If this *does* happen anyway, it's a bug in the floor
|
||||
finder; find the cause of the confusion (probably a single bin
|
||||
spike or accidental near-float-limit resolution problems) and
|
||||
correct it. */
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lsp.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
#include "lookup.h"
|
||||
#include "scales.h"
|
||||
|
||||
/* three possible LSP to f curve functions; the exact computation
|
||||
(float), a lookup based float implementation, and an integer
|
||||
implementation. The float lookup is likely the optimal choice on
|
||||
any machine with an FPU. The integer implementation is *not* fixed
|
||||
point (due to the need for a large dynamic range and thus a
|
||||
seperately tracked exponent) and thus much more complex than the
|
||||
relatively simple float implementations. It's mostly for future
|
||||
work on a fully fixed point implementation for processors like the
|
||||
ARM family. */
|
||||
|
||||
/* undefine both for the 'old' but more precise implementation */
|
||||
#define FLOAT_LOOKUP
|
||||
#undef INT_LOOKUP
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
#include "vorbis_lookup.c" /* catch this in the build system; we #include for
|
||||
compilers (like gcc) that can't inline across
|
||||
modules */
|
||||
|
||||
/* side effect: changes *lsp to cosines of lsp */
|
||||
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
|
||||
float amp,float ampoffset){
|
||||
int i;
|
||||
float wdel=M_PI/ln;
|
||||
vorbis_fpu_control fpu;
|
||||
|
||||
vorbis_fpu_setround(&fpu);
|
||||
for(i=0;i<m;i++)lsp[i]=vorbis_coslook(lsp[i]);
|
||||
|
||||
i=0;
|
||||
while(i<n){
|
||||
int k=map[i];
|
||||
int qexp;
|
||||
float p=.7071067812f;
|
||||
float q=.7071067812f;
|
||||
float w=vorbis_coslook(wdel*k);
|
||||
float *ftmp=lsp;
|
||||
int c=m>>1;
|
||||
|
||||
do{
|
||||
q*=ftmp[0]-w;
|
||||
p*=ftmp[1]-w;
|
||||
ftmp+=2;
|
||||
}while(--c);
|
||||
|
||||
if(m&1){
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
q*=ftmp[0]-w;
|
||||
q*=q;
|
||||
p*=p*(1.f-w*w);
|
||||
}else{
|
||||
/* even order filter; still symmetric */
|
||||
q*=q*(1.f+w);
|
||||
p*=p*(1.f-w);
|
||||
}
|
||||
|
||||
q=frexp(p+q,&qexp);
|
||||
q=vorbis_fromdBlook(amp*
|
||||
vorbis_invsqlook(q)*
|
||||
vorbis_invsq2explook(qexp+m)-
|
||||
ampoffset);
|
||||
|
||||
do{
|
||||
curve[i++]*=q;
|
||||
}while(map[i]==k);
|
||||
}
|
||||
vorbis_fpu_restore(fpu);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
#include "vorbis_lookup.c" /* catch this in the build system; we #include for
|
||||
compilers (like gcc) that can't inline across
|
||||
modules */
|
||||
|
||||
static int MLOOP_1[64]={
|
||||
0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
|
||||
14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
|
||||
15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
|
||||
15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
|
||||
};
|
||||
|
||||
static int MLOOP_2[64]={
|
||||
0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
|
||||
8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
|
||||
9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
|
||||
9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
|
||||
};
|
||||
|
||||
static int MLOOP_3[8]={0,1,2,2,3,3,3,3};
|
||||
|
||||
|
||||
/* side effect: changes *lsp to cosines of lsp */
|
||||
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
|
||||
float amp,float ampoffset){
|
||||
|
||||
/* 0 <= m < 256 */
|
||||
|
||||
/* set up for using all int later */
|
||||
int i;
|
||||
int ampoffseti=rint(ampoffset*4096.f);
|
||||
int ampi=rint(amp*16.f);
|
||||
long *ilsp=alloca(m*sizeof(*ilsp));
|
||||
for(i=0;i<m;i++)ilsp[i]=vorbis_coslook_i(lsp[i]/M_PI*65536.f+.5f);
|
||||
|
||||
i=0;
|
||||
while(i<n){
|
||||
int j,k=map[i];
|
||||
unsigned long pi=46341; /* 2**-.5 in 0.16 */
|
||||
unsigned long qi=46341;
|
||||
int qexp=0,shift;
|
||||
long wi=vorbis_coslook_i(k*65536/ln);
|
||||
|
||||
qi*=labs(ilsp[0]-wi);
|
||||
pi*=labs(ilsp[1]-wi);
|
||||
|
||||
for(j=3;j<m;j+=2){
|
||||
if(!(shift=MLOOP_1[(pi|qi)>>25]))
|
||||
if(!(shift=MLOOP_2[(pi|qi)>>19]))
|
||||
shift=MLOOP_3[(pi|qi)>>16];
|
||||
qi=(qi>>shift)*labs(ilsp[j-1]-wi);
|
||||
pi=(pi>>shift)*labs(ilsp[j]-wi);
|
||||
qexp+=shift;
|
||||
}
|
||||
if(!(shift=MLOOP_1[(pi|qi)>>25]))
|
||||
if(!(shift=MLOOP_2[(pi|qi)>>19]))
|
||||
shift=MLOOP_3[(pi|qi)>>16];
|
||||
|
||||
/* pi,qi normalized collectively, both tracked using qexp */
|
||||
|
||||
if(m&1){
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
qi=(qi>>shift)*labs(ilsp[j-1]-wi);
|
||||
pi=(pi>>shift)<<14;
|
||||
qexp+=shift;
|
||||
|
||||
if(!(shift=MLOOP_1[(pi|qi)>>25]))
|
||||
if(!(shift=MLOOP_2[(pi|qi)>>19]))
|
||||
shift=MLOOP_3[(pi|qi)>>16];
|
||||
|
||||
pi>>=shift;
|
||||
qi>>=shift;
|
||||
qexp+=shift-14*((m+1)>>1);
|
||||
|
||||
pi=((pi*pi)>>16);
|
||||
qi=((qi*qi)>>16);
|
||||
qexp=qexp*2+m;
|
||||
|
||||
pi*=(1<<14)-((wi*wi)>>14);
|
||||
qi+=pi>>14;
|
||||
|
||||
}else{
|
||||
/* even order filter; still symmetric */
|
||||
|
||||
/* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
|
||||
worth tracking step by step */
|
||||
|
||||
pi>>=shift;
|
||||
qi>>=shift;
|
||||
qexp+=shift-7*m;
|
||||
|
||||
pi=((pi*pi)>>16);
|
||||
qi=((qi*qi)>>16);
|
||||
qexp=qexp*2+m;
|
||||
|
||||
pi*=(1<<14)-wi;
|
||||
qi*=(1<<14)+wi;
|
||||
qi=(qi+pi)>>14;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* we've let the normalization drift because it wasn't important;
|
||||
however, for the lookup, things must be normalized again. We
|
||||
need at most one right shift or a number of left shifts */
|
||||
|
||||
if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
|
||||
qi>>=1; qexp++;
|
||||
}else
|
||||
while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
|
||||
qi<<=1; qexp--;
|
||||
}
|
||||
|
||||
amp=vorbis_fromdBlook_i(ampi* /* n.4 */
|
||||
vorbis_invsqlook_i(qi,qexp)-
|
||||
/* m.8, m+n<=8 */
|
||||
ampoffseti); /* 8.12[0] */
|
||||
|
||||
curve[i]*=amp;
|
||||
while(map[++i]==k)curve[i]*=amp;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* old, nonoptimized but simple version for any poor sap who needs to
|
||||
figure out what the hell this code does, or wants the other
|
||||
fraction of a dB precision */
|
||||
|
||||
/* side effect: changes *lsp to cosines of lsp */
|
||||
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
|
||||
float amp,float ampoffset){
|
||||
int i;
|
||||
float wdel=M_PI/ln;
|
||||
for(i=0;i<m;i++)lsp[i]=2.f*cos(lsp[i]);
|
||||
|
||||
i=0;
|
||||
while(i<n){
|
||||
int j,k=map[i];
|
||||
float p=.5f;
|
||||
float q=.5f;
|
||||
float w=2.f*cos(wdel*k);
|
||||
for(j=1;j<m;j+=2){
|
||||
q *= w-lsp[j-1];
|
||||
p *= w-lsp[j];
|
||||
}
|
||||
if(j==m){
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
q*=w-lsp[j-1];
|
||||
p*=p*(4.f-w*w);
|
||||
q*=q;
|
||||
}else{
|
||||
/* even order filter; still symmetric */
|
||||
p*=p*(2.f-w);
|
||||
q*=q*(2.f+w);
|
||||
}
|
||||
|
||||
q=fromdB(amp/sqrt(p+q)-ampoffset);
|
||||
|
||||
curve[i]*=q;
|
||||
while(map[++i]==k)curve[i]*=q;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void cheby(float *g, int ord) {
|
||||
int i, j;
|
||||
|
||||
g[0] *= .5f;
|
||||
for(i=2; i<= ord; i++) {
|
||||
for(j=ord; j >= i; j--) {
|
||||
g[j-2] -= g[j];
|
||||
g[j] += g[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int comp(const void *a,const void *b){
|
||||
return (*(float *)a<*(float *)b)-(*(float *)a>*(float *)b);
|
||||
}
|
||||
|
||||
/* Newton-Raphson-Maehly actually functioned as a decent root finder,
|
||||
but there are root sets for which it gets into limit cycles
|
||||
(exacerbated by zero suppression) and fails. We can't afford to
|
||||
fail, even if the failure is 1 in 100,000,000, so we now use
|
||||
Laguerre and later polish with Newton-Raphson (which can then
|
||||
afford to fail) */
|
||||
|
||||
#define EPSILON 10e-7
|
||||
static int Laguerre_With_Deflation(float *a,int ord,float *r){
|
||||
int i,m;
|
||||
double lastdelta=0.f;
|
||||
double *defl=alloca(sizeof(*defl)*(ord+1));
|
||||
for(i=0;i<=ord;i++)defl[i]=a[i];
|
||||
|
||||
for(m=ord;m>0;m--){
|
||||
double new=0.f,delta;
|
||||
|
||||
/* iterate a root */
|
||||
while(1){
|
||||
double p=defl[m],pp=0.f,ppp=0.f,denom;
|
||||
|
||||
/* eval the polynomial and its first two derivatives */
|
||||
for(i=m;i>0;i--){
|
||||
ppp = new*ppp + pp;
|
||||
pp = new*pp + p;
|
||||
p = new*p + defl[i-1];
|
||||
}
|
||||
|
||||
/* Laguerre's method */
|
||||
denom=(m-1) * ((m-1)*pp*pp - m*p*ppp);
|
||||
if(denom<0)
|
||||
return(-1); /* complex root! The LPC generator handed us a bad filter */
|
||||
|
||||
if(pp>0){
|
||||
denom = pp + sqrt(denom);
|
||||
if(denom<EPSILON)denom=EPSILON;
|
||||
}else{
|
||||
denom = pp - sqrt(denom);
|
||||
if(denom>-(EPSILON))denom=-(EPSILON);
|
||||
}
|
||||
|
||||
delta = m*p/denom;
|
||||
new -= delta;
|
||||
|
||||
if(delta<0.f)delta*=-1;
|
||||
|
||||
if(fabs(delta/new)<10e-12)break;
|
||||
lastdelta=delta;
|
||||
}
|
||||
|
||||
r[m-1]=new;
|
||||
|
||||
/* forward deflation */
|
||||
|
||||
for(i=m;i>0;i--)
|
||||
defl[i-1]+=new*defl[i];
|
||||
defl++;
|
||||
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* for spit-and-polish only */
|
||||
static int Newton_Raphson(float *a,int ord,float *r){
|
||||
int i, k, count=0;
|
||||
double error=1.f;
|
||||
double *root=alloca(ord*sizeof(*root));
|
||||
|
||||
for(i=0; i<ord;i++) root[i] = r[i];
|
||||
|
||||
while(error>1e-20){
|
||||
error=0;
|
||||
|
||||
for(i=0; i<ord; i++) { /* Update each point. */
|
||||
double pp=0.,delta;
|
||||
double rooti=root[i];
|
||||
double p=a[ord];
|
||||
for(k=ord-1; k>= 0; k--) {
|
||||
|
||||
pp= pp* rooti + p;
|
||||
p = p * rooti + a[k];
|
||||
}
|
||||
|
||||
delta = p/pp;
|
||||
root[i] -= delta;
|
||||
error+= delta*delta;
|
||||
}
|
||||
|
||||
if(count>40)return(-1);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Replaced the original bubble sort with a real sort. With your
|
||||
help, we can eliminate the bubble sort in our lifetime. --Monty */
|
||||
|
||||
for(i=0; i<ord;i++) r[i] = root[i];
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Convert lpc coefficients to lsp coefficients */
|
||||
int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){
|
||||
int order2=(m+1)>>1;
|
||||
int g1_order,g2_order;
|
||||
float *g1=alloca(sizeof(*g1)*(order2+1));
|
||||
float *g2=alloca(sizeof(*g2)*(order2+1));
|
||||
float *g1r=alloca(sizeof(*g1r)*(order2+1));
|
||||
float *g2r=alloca(sizeof(*g2r)*(order2+1));
|
||||
int i;
|
||||
|
||||
/* even and odd are slightly different base cases */
|
||||
g1_order=(m+1)>>1;
|
||||
g2_order=(m) >>1;
|
||||
|
||||
/* Compute the lengths of the x polynomials. */
|
||||
/* Compute the first half of K & R F1 & F2 polynomials. */
|
||||
/* Compute half of the symmetric and antisymmetric polynomials. */
|
||||
/* Remove the roots at +1 and -1. */
|
||||
|
||||
g1[g1_order] = 1.f;
|
||||
for(i=1;i<=g1_order;i++) g1[g1_order-i] = lpc[i-1]+lpc[m-i];
|
||||
g2[g2_order] = 1.f;
|
||||
for(i=1;i<=g2_order;i++) g2[g2_order-i] = lpc[i-1]-lpc[m-i];
|
||||
|
||||
if(g1_order>g2_order){
|
||||
for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2];
|
||||
}else{
|
||||
for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1];
|
||||
for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1];
|
||||
}
|
||||
|
||||
/* Convert into polynomials in cos(alpha) */
|
||||
cheby(g1,g1_order);
|
||||
cheby(g2,g2_order);
|
||||
|
||||
/* Find the roots of the 2 even polynomials.*/
|
||||
if(Laguerre_With_Deflation(g1,g1_order,g1r) ||
|
||||
Laguerre_With_Deflation(g2,g2_order,g2r))
|
||||
return(-1);
|
||||
|
||||
Newton_Raphson(g1,g1_order,g1r); /* if it fails, it leaves g1r alone */
|
||||
Newton_Raphson(g2,g2_order,g2r); /* if it fails, it leaves g2r alone */
|
||||
|
||||
qsort(g1r,g1_order,sizeof(*g1r),comp);
|
||||
qsort(g2r,g2_order,sizeof(*g2r),comp);
|
||||
|
||||
for(i=0;i<g1_order;i++)
|
||||
lsp[i*2] = acos(g1r[i]);
|
||||
|
||||
for(i=0;i<g2_order;i++)
|
||||
lsp[i*2+1] = acos(g2r[i]);
|
||||
return(0);
|
||||
}
|
|
@ -0,0 +1,844 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: channel mapping 0 implementation
|
||||
last mod: $Id: mapping0.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "codebook.h"
|
||||
#include "window.h"
|
||||
#include "registry.h"
|
||||
#include "psy.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* simplistic, wasteful way of doing this (unique lookup for each
|
||||
mode/submapping); there should be a central repository for
|
||||
identical lookups. That will require minor work, so I'm putting it
|
||||
off as low priority.
|
||||
|
||||
Why a lookup for each backend in a given mode? Because the
|
||||
blocksize is set by the mode, and low backend lookups may require
|
||||
parameters from other areas of the mode/mapping */
|
||||
|
||||
static void mapping0_free_info(vorbis_info_mapping *i){
|
||||
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)i;
|
||||
if(info){
|
||||
memset(info,0,sizeof(*info));
|
||||
_ogg_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
static int ilog(unsigned int v){
|
||||
int ret=0;
|
||||
if(v)--v;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static void mapping0_pack(vorbis_info *vi,vorbis_info_mapping *vm,
|
||||
oggpack_buffer *opb){
|
||||
int i;
|
||||
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)vm;
|
||||
|
||||
/* another 'we meant to do it this way' hack... up to beta 4, we
|
||||
packed 4 binary zeros here to signify one submapping in use. We
|
||||
now redefine that to mean four bitflags that indicate use of
|
||||
deeper features; bit0:submappings, bit1:coupling,
|
||||
bit2,3:reserved. This is backward compatable with all actual uses
|
||||
of the beta code. */
|
||||
|
||||
if(info->submaps>1){
|
||||
oggpack_write(opb,1,1);
|
||||
oggpack_write(opb,info->submaps-1,4);
|
||||
}else
|
||||
oggpack_write(opb,0,1);
|
||||
|
||||
if(info->coupling_steps>0){
|
||||
oggpack_write(opb,1,1);
|
||||
oggpack_write(opb,info->coupling_steps-1,8);
|
||||
|
||||
for(i=0;i<info->coupling_steps;i++){
|
||||
oggpack_write(opb,info->coupling_mag[i],ilog(vi->channels));
|
||||
oggpack_write(opb,info->coupling_ang[i],ilog(vi->channels));
|
||||
}
|
||||
}else
|
||||
oggpack_write(opb,0,1);
|
||||
|
||||
oggpack_write(opb,0,2); /* 2,3:reserved */
|
||||
|
||||
/* we don't write the channel submappings if we only have one... */
|
||||
if(info->submaps>1){
|
||||
for(i=0;i<vi->channels;i++)
|
||||
oggpack_write(opb,info->chmuxlist[i],4);
|
||||
}
|
||||
for(i=0;i<info->submaps;i++){
|
||||
oggpack_write(opb,0,8); /* time submap unused */
|
||||
oggpack_write(opb,info->floorsubmap[i],8);
|
||||
oggpack_write(opb,info->residuesubmap[i],8);
|
||||
}
|
||||
}
|
||||
|
||||
/* also responsible for range checking */
|
||||
static vorbis_info_mapping *mapping0_unpack(vorbis_info *vi,oggpack_buffer *opb){
|
||||
int i;
|
||||
vorbis_info_mapping0 *info=_ogg_calloc(1,sizeof(*info));
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
memset(info,0,sizeof(*info));
|
||||
|
||||
if(oggpack_read(opb,1))
|
||||
info->submaps=oggpack_read(opb,4)+1;
|
||||
else
|
||||
info->submaps=1;
|
||||
|
||||
if(oggpack_read(opb,1)){
|
||||
info->coupling_steps=oggpack_read(opb,8)+1;
|
||||
|
||||
for(i=0;i<info->coupling_steps;i++){
|
||||
int testM=info->coupling_mag[i]=oggpack_read(opb,ilog(vi->channels));
|
||||
int testA=info->coupling_ang[i]=oggpack_read(opb,ilog(vi->channels));
|
||||
|
||||
if(testM<0 ||
|
||||
testA<0 ||
|
||||
testM==testA ||
|
||||
testM>=vi->channels ||
|
||||
testA>=vi->channels) goto err_out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(oggpack_read(opb,2)>0)goto err_out; /* 2,3:reserved */
|
||||
|
||||
if(info->submaps>1){
|
||||
for(i=0;i<vi->channels;i++){
|
||||
info->chmuxlist[i]=oggpack_read(opb,4);
|
||||
if(info->chmuxlist[i]>=info->submaps)goto err_out;
|
||||
}
|
||||
}
|
||||
for(i=0;i<info->submaps;i++){
|
||||
oggpack_read(opb,8); /* time submap unused */
|
||||
info->floorsubmap[i]=oggpack_read(opb,8);
|
||||
if(info->floorsubmap[i]>=ci->floors)goto err_out;
|
||||
info->residuesubmap[i]=oggpack_read(opb,8);
|
||||
if(info->residuesubmap[i]>=ci->residues)goto err_out;
|
||||
}
|
||||
|
||||
return info;
|
||||
|
||||
err_out:
|
||||
mapping0_free_info(info);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#include "os.h"
|
||||
#include "lpc.h"
|
||||
#include "lsp.h"
|
||||
#include "envelope.h"
|
||||
#include "mdct.h"
|
||||
#include "psy.h"
|
||||
#include "scales.h"
|
||||
|
||||
#if 0
|
||||
static long seq=0;
|
||||
static ogg_int64_t total=0;
|
||||
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,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
extern int *floor1_fit(vorbis_block *vb,vorbis_look_floor *look,
|
||||
const float *logmdct, /* in */
|
||||
const float *logmask);
|
||||
extern int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor *look,
|
||||
int *A,int *B,
|
||||
int del);
|
||||
extern int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
|
||||
vorbis_look_floor *look,
|
||||
int *post,int *ilogmask);
|
||||
|
||||
|
||||
static int mapping0_forward(vorbis_block *vb){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
private_state *b=vb->vd->backend_state;
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
|
||||
int n=vb->pcmend;
|
||||
int i,j,k;
|
||||
|
||||
int *nonzero = alloca(sizeof(*nonzero)*vi->channels);
|
||||
float **gmdct = _vorbis_block_alloc(vb,vi->channels*sizeof(*gmdct));
|
||||
int **ilogmaskch= _vorbis_block_alloc(vb,vi->channels*sizeof(*ilogmaskch));
|
||||
int ***floor_posts = _vorbis_block_alloc(vb,vi->channels*sizeof(*floor_posts));
|
||||
|
||||
float global_ampmax=vbi->ampmax;
|
||||
float *local_ampmax=alloca(sizeof(*local_ampmax)*vi->channels);
|
||||
int blocktype=vbi->blocktype;
|
||||
|
||||
int modenumber=vb->W;
|
||||
vorbis_info_mapping0 *info=ci->map_param[modenumber];
|
||||
vorbis_look_psy *psy_look=
|
||||
b->psy+blocktype+(vb->W?2:0);
|
||||
|
||||
vb->mode=modenumber;
|
||||
|
||||
for(i=0;i<vi->channels;i++){
|
||||
float scale=4.f/n;
|
||||
float scale_dB;
|
||||
|
||||
float *pcm =vb->pcm[i];
|
||||
float *logfft =pcm;
|
||||
|
||||
gmdct[i]=_vorbis_block_alloc(vb,n/2*sizeof(**gmdct));
|
||||
|
||||
scale_dB=todB(&scale) + .345; /* + .345 is a hack; the original
|
||||
todB estimation used on IEEE 754
|
||||
compliant machines had a bug that
|
||||
returned dB values about a third
|
||||
of a decibel too high. The bug
|
||||
was harmless because tunings
|
||||
implicitly took that into
|
||||
account. However, fixing the bug
|
||||
in the estimator requires
|
||||
changing all the tunings as well.
|
||||
For now, it's easier to sync
|
||||
things back up here, and
|
||||
recalibrate the tunings in the
|
||||
next major model upgrade. */
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2)
|
||||
if(i==0)
|
||||
_analysis_output("pcmL",seq,pcm,n,0,0,total-n/2);
|
||||
else
|
||||
_analysis_output("pcmR",seq,pcm,n,0,0,total-n/2);
|
||||
#endif
|
||||
|
||||
/* window the PCM data */
|
||||
_vorbis_apply_window(pcm,b->window,ci->blocksizes,vb->lW,vb->W,vb->nW);
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2)
|
||||
if(i==0)
|
||||
_analysis_output("windowedL",seq,pcm,n,0,0,total-n/2);
|
||||
else
|
||||
_analysis_output("windowedR",seq,pcm,n,0,0,total-n/2);
|
||||
#endif
|
||||
|
||||
/* transform the PCM data */
|
||||
/* only MDCT right now.... */
|
||||
mdct_forward(b->transform[vb->W][0],pcm,gmdct[i]);
|
||||
|
||||
/* FFT yields more accurate tonal estimation (not phase sensitive) */
|
||||
drft_forward(&b->fft_look[vb->W],pcm);
|
||||
logfft[0]=scale_dB+todB(pcm) + .345; /* + .345 is a hack; the
|
||||
original todB estimation used on
|
||||
IEEE 754 compliant machines had a
|
||||
bug that returned dB values about
|
||||
a third of a decibel too high.
|
||||
The bug was harmless because
|
||||
tunings implicitly took that into
|
||||
account. However, fixing the bug
|
||||
in the estimator requires
|
||||
changing all the tunings as well.
|
||||
For now, it's easier to sync
|
||||
things back up here, and
|
||||
recalibrate the tunings in the
|
||||
next major model upgrade. */
|
||||
local_ampmax[i]=logfft[0];
|
||||
for(j=1;j<n-1;j+=2){
|
||||
float temp=pcm[j]*pcm[j]+pcm[j+1]*pcm[j+1];
|
||||
temp=logfft[(j+1)>>1]=scale_dB+.5f*todB(&temp) + .345; /* +
|
||||
.345 is a hack; the original todB
|
||||
estimation used on IEEE 754
|
||||
compliant machines had a bug that
|
||||
returned dB values about a third
|
||||
of a decibel too high. The bug
|
||||
was harmless because tunings
|
||||
implicitly took that into
|
||||
account. However, fixing the bug
|
||||
in the estimator requires
|
||||
changing all the tunings as well.
|
||||
For now, it's easier to sync
|
||||
things back up here, and
|
||||
recalibrate the tunings in the
|
||||
next major model upgrade. */
|
||||
if(temp>local_ampmax[i])local_ampmax[i]=temp;
|
||||
}
|
||||
|
||||
if(local_ampmax[i]>0.f)local_ampmax[i]=0.f;
|
||||
if(local_ampmax[i]>global_ampmax)global_ampmax=local_ampmax[i];
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0){
|
||||
_analysis_output("fftL",seq,logfft,n/2,1,0,0);
|
||||
}else{
|
||||
_analysis_output("fftR",seq,logfft,n/2,1,0,0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
{
|
||||
float *noise = _vorbis_block_alloc(vb,n/2*sizeof(*noise));
|
||||
float *tone = _vorbis_block_alloc(vb,n/2*sizeof(*tone));
|
||||
|
||||
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];
|
||||
|
||||
/* the following makes things clearer to *me* anyway */
|
||||
float *mdct =gmdct[i];
|
||||
float *logfft =vb->pcm[i];
|
||||
|
||||
float *logmdct =logfft+n/2;
|
||||
float *logmask =logfft;
|
||||
|
||||
vb->mode=modenumber;
|
||||
|
||||
floor_posts[i]=_vorbis_block_alloc(vb,PACKETBLOBS*sizeof(**floor_posts));
|
||||
memset(floor_posts[i],0,sizeof(**floor_posts)*PACKETBLOBS);
|
||||
|
||||
for(j=0;j<n/2;j++)
|
||||
logmdct[j]=todB(mdct+j) + .345; /* + .345 is a hack; the original
|
||||
todB estimation used on IEEE 754
|
||||
compliant machines had a bug that
|
||||
returned dB values about a third
|
||||
of a decibel too high. The bug
|
||||
was harmless because tunings
|
||||
implicitly took that into
|
||||
account. However, fixing the bug
|
||||
in the estimator requires
|
||||
changing all the tunings as well.
|
||||
For now, it's easier to sync
|
||||
things back up here, and
|
||||
recalibrate the tunings in the
|
||||
next major model upgrade. */
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0)
|
||||
_analysis_output("mdctL",seq,logmdct,n/2,1,0,0);
|
||||
else
|
||||
_analysis_output("mdctR",seq,logmdct,n/2,1,0,0);
|
||||
}else{
|
||||
_analysis_output("mdct",seq,logmdct,n/2,1,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* first step; noise masking. Not only does 'noise masking'
|
||||
give us curves from which we can decide how much resolution
|
||||
to give noise parts of the spectrum, it also implicitly hands
|
||||
us a tonality estimate (the larger the value in the
|
||||
'noise_depth' vector, the more tonal that area is) */
|
||||
|
||||
_vp_noisemask(psy_look,
|
||||
logmdct,
|
||||
noise); /* noise does not have by-frequency offset
|
||||
bias applied yet */
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0)
|
||||
_analysis_output("noiseL",seq,noise,n/2,1,0,0);
|
||||
else
|
||||
_analysis_output("noiseR",seq,noise,n/2,1,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* second step: 'all the other crap'; all the stuff that isn't
|
||||
computed/fit for bitrate management goes in the second psy
|
||||
vector. This includes tone masking, peak limiting and ATH */
|
||||
|
||||
_vp_tonemask(psy_look,
|
||||
logfft,
|
||||
tone,
|
||||
global_ampmax,
|
||||
local_ampmax[i]);
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0)
|
||||
_analysis_output("toneL",seq,tone,n/2,1,0,0);
|
||||
else
|
||||
_analysis_output("toneR",seq,tone,n/2,1,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* third step; we offset the noise vectors, overlay tone
|
||||
masking. We then do a floor1-specific line fit. If we're
|
||||
performing bitrate management, the line fit is performed
|
||||
multiple times for up/down tweakage on demand. */
|
||||
|
||||
#if 0
|
||||
{
|
||||
float aotuv[psy_look->n];
|
||||
#endif
|
||||
|
||||
_vp_offset_and_mix(psy_look,
|
||||
noise,
|
||||
tone,
|
||||
1,
|
||||
logmask,
|
||||
mdct,
|
||||
logmdct);
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0)
|
||||
_analysis_output("aotuvM1_L",seq,aotuv,psy_look->n,1,1,0);
|
||||
else
|
||||
_analysis_output("aotuvM1_R",seq,aotuv,psy_look->n,1,1,0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0)
|
||||
_analysis_output("mask1L",seq,logmask,n/2,1,0,0);
|
||||
else
|
||||
_analysis_output("mask1R",seq,logmask,n/2,1,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* this algorithm is hardwired to floor 1 for now; abort out if
|
||||
we're *not* floor1. This won't happen unless someone has
|
||||
broken the encode setup lib. Guard it anyway. */
|
||||
if(ci->floor_type[info->floorsubmap[submap]]!=1)return(-1);
|
||||
|
||||
floor_posts[i][PACKETBLOBS/2]=
|
||||
floor1_fit(vb,b->flr[info->floorsubmap[submap]],
|
||||
logmdct,
|
||||
logmask);
|
||||
|
||||
/* are we managing bitrate? If so, perform two more fits for
|
||||
later rate tweaking (fits represent hi/lo) */
|
||||
if(vorbis_bitrate_managed(vb) && floor_posts[i][PACKETBLOBS/2]){
|
||||
/* higher rate by way of lower noise curve */
|
||||
|
||||
_vp_offset_and_mix(psy_look,
|
||||
noise,
|
||||
tone,
|
||||
2,
|
||||
logmask,
|
||||
mdct,
|
||||
logmdct);
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2){
|
||||
if(i==0)
|
||||
_analysis_output("mask2L",seq,logmask,n/2,1,0,0);
|
||||
else
|
||||
_analysis_output("mask2R",seq,logmask,n/2,1,0,0);
|
||||
}
|
||||
#endif
|
||||
|
||||
floor_posts[i][PACKETBLOBS-1]=
|
||||
floor1_fit(vb,b->flr[info->floorsubmap[submap]],
|
||||
logmdct,
|
||||
logmask);
|
||||
|
||||
/* lower rate by way of higher noise curve */
|
||||
_vp_offset_and_mix(psy_look,
|
||||
noise,
|
||||
tone,
|
||||
0,
|
||||
logmask,
|
||||
mdct,
|
||||
logmdct);
|
||||
|
||||
#if 0
|
||||
if(vi->channels==2)
|
||||
if(i==0)
|
||||
_analysis_output("mask0L",seq,logmask,n/2,1,0,0);
|
||||
else
|
||||
_analysis_output("mask0R",seq,logmask,n/2,1,0,0);
|
||||
#endif
|
||||
|
||||
floor_posts[i][0]=
|
||||
floor1_fit(vb,b->flr[info->floorsubmap[submap]],
|
||||
logmdct,
|
||||
logmask);
|
||||
|
||||
/* we also interpolate a range of intermediate curves for
|
||||
intermediate rates */
|
||||
for(k=1;k<PACKETBLOBS/2;k++)
|
||||
floor_posts[i][k]=
|
||||
floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]],
|
||||
floor_posts[i][0],
|
||||
floor_posts[i][PACKETBLOBS/2],
|
||||
k*65536/(PACKETBLOBS/2));
|
||||
for(k=PACKETBLOBS/2+1;k<PACKETBLOBS-1;k++)
|
||||
floor_posts[i][k]=
|
||||
floor1_interpolate_fit(vb,b->flr[info->floorsubmap[submap]],
|
||||
floor_posts[i][PACKETBLOBS/2],
|
||||
floor_posts[i][PACKETBLOBS-1],
|
||||
(k-PACKETBLOBS/2)*65536/(PACKETBLOBS/2));
|
||||
}
|
||||
}
|
||||
}
|
||||
vbi->ampmax=global_ampmax;
|
||||
|
||||
/*
|
||||
the next phases are performed once for vbr-only and PACKETBLOB
|
||||
times for bitrate managed modes.
|
||||
|
||||
1) encode actual mode being used
|
||||
2) encode the floor for each channel, compute coded mask curve/res
|
||||
3) normalize and couple.
|
||||
4) encode residue
|
||||
5) save packet bytes to the packetblob vector
|
||||
|
||||
*/
|
||||
|
||||
/* iterate over the many masking curve fits we've created */
|
||||
|
||||
{
|
||||
float **res_bundle=alloca(sizeof(*res_bundle)*vi->channels);
|
||||
float **couple_bundle=alloca(sizeof(*couple_bundle)*vi->channels);
|
||||
int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
|
||||
int **sortindex=alloca(sizeof(*sortindex)*vi->channels);
|
||||
float **mag_memo;
|
||||
int **mag_sort;
|
||||
|
||||
if(info->coupling_steps){
|
||||
mag_memo=_vp_quantize_couple_memo(vb,
|
||||
&ci->psy_g_param,
|
||||
psy_look,
|
||||
info,
|
||||
gmdct);
|
||||
|
||||
mag_sort=_vp_quantize_couple_sort(vb,
|
||||
psy_look,
|
||||
info,
|
||||
mag_memo);
|
||||
|
||||
hf_reduction(&ci->psy_g_param,
|
||||
psy_look,
|
||||
info,
|
||||
mag_memo);
|
||||
}
|
||||
|
||||
memset(sortindex,0,sizeof(*sortindex)*vi->channels);
|
||||
if(psy_look->vi->normal_channel_p){
|
||||
for(i=0;i<vi->channels;i++){
|
||||
float *mdct =gmdct[i];
|
||||
sortindex[i]=alloca(sizeof(**sortindex)*n/2);
|
||||
_vp_noise_normalize_sort(psy_look,mdct,sortindex[i]);
|
||||
}
|
||||
}
|
||||
|
||||
for(k=(vorbis_bitrate_managed(vb)?0:PACKETBLOBS/2);
|
||||
k<=(vorbis_bitrate_managed(vb)?PACKETBLOBS-1:PACKETBLOBS/2);
|
||||
k++){
|
||||
oggpack_buffer *opb=vbi->packetblob[k];
|
||||
|
||||
/* start out our new packet blob with packet type and mode */
|
||||
/* Encode the packet type */
|
||||
oggpack_write(opb,0,1);
|
||||
/* Encode the modenumber */
|
||||
/* Encode frame mode, pre,post windowsize, then dispatch */
|
||||
oggpack_write(opb,modenumber,b->modebits);
|
||||
if(vb->W){
|
||||
oggpack_write(opb,vb->lW,1);
|
||||
oggpack_write(opb,vb->nW,1);
|
||||
}
|
||||
|
||||
/* encode floor, compute masking curve, sep out residue */
|
||||
for(i=0;i<vi->channels;i++){
|
||||
int submap=info->chmuxlist[i];
|
||||
float *mdct =gmdct[i];
|
||||
float *res =vb->pcm[i];
|
||||
int *ilogmask=ilogmaskch[i]=
|
||||
_vorbis_block_alloc(vb,n/2*sizeof(**gmdct));
|
||||
|
||||
nonzero[i]=floor1_encode(opb,vb,b->flr[info->floorsubmap[submap]],
|
||||
floor_posts[i][k],
|
||||
ilogmask);
|
||||
#if 0
|
||||
{
|
||||
char buf[80];
|
||||
sprintf(buf,"maskI%c%d",i?'R':'L',k);
|
||||
float work[n/2];
|
||||
for(j=0;j<n/2;j++)
|
||||
work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]];
|
||||
_analysis_output(buf,seq,work,n/2,1,1,0);
|
||||
}
|
||||
#endif
|
||||
_vp_remove_floor(psy_look,
|
||||
mdct,
|
||||
ilogmask,
|
||||
res,
|
||||
ci->psy_g_param.sliding_lowpass[vb->W][k]);
|
||||
|
||||
_vp_noise_normalize(psy_look,res,res+n/2,sortindex[i]);
|
||||
|
||||
|
||||
#if 0
|
||||
{
|
||||
char buf[80];
|
||||
float work[n/2];
|
||||
for(j=0;j<n/2;j++)
|
||||
work[j]=FLOOR1_fromdB_LOOKUP[ilogmask[j]]*(res+n/2)[j];
|
||||
sprintf(buf,"resI%c%d",i?'R':'L',k);
|
||||
_analysis_output(buf,seq,work,n/2,1,1,0);
|
||||
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* our iteration is now based on masking curve, not prequant and
|
||||
coupling. Only one prequant/coupling step */
|
||||
|
||||
/* quantize/couple */
|
||||
/* incomplete implementation that assumes the tree is all depth
|
||||
one, or no tree at all */
|
||||
if(info->coupling_steps){
|
||||
_vp_couple(k,
|
||||
&ci->psy_g_param,
|
||||
psy_look,
|
||||
info,
|
||||
vb->pcm,
|
||||
mag_memo,
|
||||
mag_sort,
|
||||
ilogmaskch,
|
||||
nonzero,
|
||||
ci->psy_g_param.sliding_lowpass[vb->W][k]);
|
||||
}
|
||||
|
||||
/* classify and encode by submap */
|
||||
for(i=0;i<info->submaps;i++){
|
||||
int ch_in_bundle=0;
|
||||
long **classifications;
|
||||
int resnum=info->residuesubmap[i];
|
||||
|
||||
for(j=0;j<vi->channels;j++){
|
||||
if(info->chmuxlist[j]==i){
|
||||
zerobundle[ch_in_bundle]=0;
|
||||
if(nonzero[j])zerobundle[ch_in_bundle]=1;
|
||||
res_bundle[ch_in_bundle]=vb->pcm[j];
|
||||
couple_bundle[ch_in_bundle++]=vb->pcm[j]+n/2;
|
||||
}
|
||||
}
|
||||
|
||||
classifications=_residue_P[ci->residue_type[resnum]]->
|
||||
class(vb,b->residue[resnum],couple_bundle,zerobundle,ch_in_bundle);
|
||||
|
||||
_residue_P[ci->residue_type[resnum]]->
|
||||
forward(opb,vb,b->residue[resnum],
|
||||
couple_bundle,NULL,zerobundle,ch_in_bundle,classifications);
|
||||
}
|
||||
|
||||
/* ok, done encoding. Next protopacket. */
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
seq++;
|
||||
total+=ci->blocksizes[vb->W]/4+ci->blocksizes[vb->nW]/4;
|
||||
#endif
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int mapping0_inverse(vorbis_block *vb,vorbis_info_mapping *l){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
private_state *b=vd->backend_state;
|
||||
vorbis_info_mapping0 *info=(vorbis_info_mapping0 *)l;
|
||||
int hs=ci->halfrate_flag;
|
||||
|
||||
int i,j;
|
||||
long n=vb->pcmend=ci->blocksizes[vb->W];
|
||||
|
||||
float **pcmbundle=alloca(sizeof(*pcmbundle)*vi->channels);
|
||||
int *zerobundle=alloca(sizeof(*zerobundle)*vi->channels);
|
||||
|
||||
int *nonzero =alloca(sizeof(*nonzero)*vi->channels);
|
||||
void **floormemo=alloca(sizeof(*floormemo)*vi->channels);
|
||||
|
||||
/* recover the spectral envelope; store it in the PCM vector for now */
|
||||
for(i=0;i<vi->channels;i++){
|
||||
int submap=info->chmuxlist[i];
|
||||
floormemo[i]=_floor_P[ci->floor_type[info->floorsubmap[submap]]]->
|
||||
inverse1(vb,b->flr[info->floorsubmap[submap]]);
|
||||
if(floormemo[i])
|
||||
nonzero[i]=1;
|
||||
else
|
||||
nonzero[i]=0;
|
||||
memset(vb->pcm[i],0,sizeof(*vb->pcm[i])*n/2);
|
||||
}
|
||||
|
||||
/* channel coupling can 'dirty' the nonzero listing */
|
||||
for(i=0;i<info->coupling_steps;i++){
|
||||
if(nonzero[info->coupling_mag[i]] ||
|
||||
nonzero[info->coupling_ang[i]]){
|
||||
nonzero[info->coupling_mag[i]]=1;
|
||||
nonzero[info->coupling_ang[i]]=1;
|
||||
}
|
||||
}
|
||||
|
||||
/* recover the residue into our working vectors */
|
||||
for(i=0;i<info->submaps;i++){
|
||||
int ch_in_bundle=0;
|
||||
for(j=0;j<vi->channels;j++){
|
||||
if(info->chmuxlist[j]==i){
|
||||
if(nonzero[j])
|
||||
zerobundle[ch_in_bundle]=1;
|
||||
else
|
||||
zerobundle[ch_in_bundle]=0;
|
||||
pcmbundle[ch_in_bundle++]=vb->pcm[j];
|
||||
}
|
||||
}
|
||||
|
||||
_residue_P[ci->residue_type[info->residuesubmap[i]]]->
|
||||
inverse(vb,b->residue[info->residuesubmap[i]],
|
||||
pcmbundle,zerobundle,ch_in_bundle);
|
||||
}
|
||||
|
||||
/* channel coupling */
|
||||
for(i=info->coupling_steps-1;i>=0;i--){
|
||||
float *pcmM=vb->pcm[info->coupling_mag[i]];
|
||||
float *pcmA=vb->pcm[info->coupling_ang[i]];
|
||||
|
||||
for(j=0;j<n/2;j++){
|
||||
float mag=pcmM[j];
|
||||
float ang=pcmA[j];
|
||||
|
||||
if(mag>0)
|
||||
if(ang>0){
|
||||
pcmM[j]=mag;
|
||||
pcmA[j]=mag-ang;
|
||||
}else{
|
||||
pcmA[j]=mag;
|
||||
pcmM[j]=mag+ang;
|
||||
}
|
||||
else
|
||||
if(ang>0){
|
||||
pcmM[j]=mag;
|
||||
pcmA[j]=mag+ang;
|
||||
}else{
|
||||
pcmA[j]=mag;
|
||||
pcmM[j]=mag-ang;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* compute and apply spectral envelope */
|
||||
for(i=0;i<vi->channels;i++){
|
||||
float *pcm=vb->pcm[i];
|
||||
int submap=info->chmuxlist[i];
|
||||
_floor_P[ci->floor_type[info->floorsubmap[submap]]]->
|
||||
inverse2(vb,b->flr[info->floorsubmap[submap]],
|
||||
floormemo[i],pcm);
|
||||
}
|
||||
|
||||
/* transform the PCM data; takes PCM vector, vb; modifies PCM vector */
|
||||
/* only MDCT right now.... */
|
||||
for(i=0;i<vi->channels;i++){
|
||||
float *pcm=vb->pcm[i];
|
||||
mdct_backward(b->transform[vb->W][0],pcm,pcm);
|
||||
}
|
||||
|
||||
/* all done! */
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* export hooks */
|
||||
vorbis_func_mapping mapping0_exportbundle={
|
||||
&mapping0_pack,
|
||||
&mapping0_unpack,
|
||||
&mapping0_free_info,
|
||||
&mapping0_forward,
|
||||
&mapping0_inverse
|
||||
};
|
||||
|
|
@ -0,0 +1,564 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: normalized modified discrete cosine transform
|
||||
power of two length transform only [64 <= n ]
|
||||
last mod: $Id: mdct.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
Original algorithm adapted long ago from _The use of multirate filter
|
||||
banks for coding of high quality digital audio_, by T. Sporer,
|
||||
K. Brandenburg and B. Edler, collection of the European Signal
|
||||
Processing Conference (EUSIPCO), Amsterdam, June 1992, Vol.1, pp
|
||||
211-214
|
||||
|
||||
The below code implements an algorithm that no longer looks much like
|
||||
that presented in the paper, but the basic structure remains if you
|
||||
dig deep enough to see it.
|
||||
|
||||
This module DOES NOT INCLUDE code to generate/apply the window
|
||||
function. Everybody has their own weird favorite including me... I
|
||||
happen to like the properties of y=sin(.5PI*sin^2(x)), but others may
|
||||
vehemently disagree.
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* this can also be run as an integer transform by uncommenting a
|
||||
define in mdct.h; the integerization is a first pass and although
|
||||
it's likely stable for Vorbis, the dynamic range is constrained and
|
||||
roundoff isn't done (so it's noisy). Consider it functional, but
|
||||
only a starting point. There's no point on a machine with an FPU */
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "mdct.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* build lookups for trig functions; also pre-figure scaling and
|
||||
some window function algebra. */
|
||||
|
||||
void mdct_init(mdct_lookup *lookup,int n){
|
||||
int *bitrev=_ogg_malloc(sizeof(*bitrev)*(n/4));
|
||||
DATA_TYPE *T=_ogg_malloc(sizeof(*T)*(n+n/4));
|
||||
|
||||
int i;
|
||||
int n2=n>>1;
|
||||
int log2n=lookup->log2n=rint(log((float)n)/log(2.f));
|
||||
lookup->n=n;
|
||||
lookup->trig=T;
|
||||
lookup->bitrev=bitrev;
|
||||
|
||||
/* trig lookups... */
|
||||
|
||||
for(i=0;i<n/4;i++){
|
||||
T[i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i)));
|
||||
T[i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i)));
|
||||
T[n2+i*2]=FLOAT_CONV(cos((M_PI/(2*n))*(2*i+1)));
|
||||
T[n2+i*2+1]=FLOAT_CONV(sin((M_PI/(2*n))*(2*i+1)));
|
||||
}
|
||||
for(i=0;i<n/8;i++){
|
||||
T[n+i*2]=FLOAT_CONV(cos((M_PI/n)*(4*i+2))*.5);
|
||||
T[n+i*2+1]=FLOAT_CONV(-sin((M_PI/n)*(4*i+2))*.5);
|
||||
}
|
||||
|
||||
/* bitreverse lookup... */
|
||||
|
||||
{
|
||||
int mask=(1<<(log2n-1))-1,i,j;
|
||||
int msb=1<<(log2n-2);
|
||||
for(i=0;i<n/8;i++){
|
||||
int acc=0;
|
||||
for(j=0;msb>>j;j++)
|
||||
if((msb>>j)&i)acc|=1<<j;
|
||||
bitrev[i*2]=((~acc)&mask)-1;
|
||||
bitrev[i*2+1]=acc;
|
||||
|
||||
}
|
||||
}
|
||||
lookup->scale=FLOAT_CONV(4.f/n);
|
||||
}
|
||||
|
||||
/* 8 point butterfly (in place, 4 register) */
|
||||
STIN void mdct_butterfly_8(DATA_TYPE *x){
|
||||
REG_TYPE r0 = x[6] + x[2];
|
||||
REG_TYPE r1 = x[6] - x[2];
|
||||
REG_TYPE r2 = x[4] + x[0];
|
||||
REG_TYPE r3 = x[4] - x[0];
|
||||
|
||||
x[6] = r0 + r2;
|
||||
x[4] = r0 - r2;
|
||||
|
||||
r0 = x[5] - x[1];
|
||||
r2 = x[7] - x[3];
|
||||
x[0] = r1 + r0;
|
||||
x[2] = r1 - r0;
|
||||
|
||||
r0 = x[5] + x[1];
|
||||
r1 = x[7] + x[3];
|
||||
x[3] = r2 + r3;
|
||||
x[1] = r2 - r3;
|
||||
x[7] = r1 + r0;
|
||||
x[5] = r1 - r0;
|
||||
|
||||
}
|
||||
|
||||
/* 16 point butterfly (in place, 4 register) */
|
||||
STIN void mdct_butterfly_16(DATA_TYPE *x){
|
||||
REG_TYPE r0 = x[1] - x[9];
|
||||
REG_TYPE r1 = x[0] - x[8];
|
||||
|
||||
x[8] += x[0];
|
||||
x[9] += x[1];
|
||||
x[0] = MULT_NORM((r0 + r1) * cPI2_8);
|
||||
x[1] = MULT_NORM((r0 - r1) * cPI2_8);
|
||||
|
||||
r0 = x[3] - x[11];
|
||||
r1 = x[10] - x[2];
|
||||
x[10] += x[2];
|
||||
x[11] += x[3];
|
||||
x[2] = r0;
|
||||
x[3] = r1;
|
||||
|
||||
r0 = x[12] - x[4];
|
||||
r1 = x[13] - x[5];
|
||||
x[12] += x[4];
|
||||
x[13] += x[5];
|
||||
x[4] = MULT_NORM((r0 - r1) * cPI2_8);
|
||||
x[5] = MULT_NORM((r0 + r1) * cPI2_8);
|
||||
|
||||
r0 = x[14] - x[6];
|
||||
r1 = x[15] - x[7];
|
||||
x[14] += x[6];
|
||||
x[15] += x[7];
|
||||
x[6] = r0;
|
||||
x[7] = r1;
|
||||
|
||||
mdct_butterfly_8(x);
|
||||
mdct_butterfly_8(x+8);
|
||||
}
|
||||
|
||||
/* 32 point butterfly (in place, 4 register) */
|
||||
STIN void mdct_butterfly_32(DATA_TYPE *x){
|
||||
REG_TYPE r0 = x[30] - x[14];
|
||||
REG_TYPE r1 = x[31] - x[15];
|
||||
|
||||
x[30] += x[14];
|
||||
x[31] += x[15];
|
||||
x[14] = r0;
|
||||
x[15] = r1;
|
||||
|
||||
r0 = x[28] - x[12];
|
||||
r1 = x[29] - x[13];
|
||||
x[28] += x[12];
|
||||
x[29] += x[13];
|
||||
x[12] = MULT_NORM( r0 * cPI1_8 - r1 * cPI3_8 );
|
||||
x[13] = MULT_NORM( r0 * cPI3_8 + r1 * cPI1_8 );
|
||||
|
||||
r0 = x[26] - x[10];
|
||||
r1 = x[27] - x[11];
|
||||
x[26] += x[10];
|
||||
x[27] += x[11];
|
||||
x[10] = MULT_NORM(( r0 - r1 ) * cPI2_8);
|
||||
x[11] = MULT_NORM(( r0 + r1 ) * cPI2_8);
|
||||
|
||||
r0 = x[24] - x[8];
|
||||
r1 = x[25] - x[9];
|
||||
x[24] += x[8];
|
||||
x[25] += x[9];
|
||||
x[8] = MULT_NORM( r0 * cPI3_8 - r1 * cPI1_8 );
|
||||
x[9] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 );
|
||||
|
||||
r0 = x[22] - x[6];
|
||||
r1 = x[7] - x[23];
|
||||
x[22] += x[6];
|
||||
x[23] += x[7];
|
||||
x[6] = r1;
|
||||
x[7] = r0;
|
||||
|
||||
r0 = x[4] - x[20];
|
||||
r1 = x[5] - x[21];
|
||||
x[20] += x[4];
|
||||
x[21] += x[5];
|
||||
x[4] = MULT_NORM( r1 * cPI1_8 + r0 * cPI3_8 );
|
||||
x[5] = MULT_NORM( r1 * cPI3_8 - r0 * cPI1_8 );
|
||||
|
||||
r0 = x[2] - x[18];
|
||||
r1 = x[3] - x[19];
|
||||
x[18] += x[2];
|
||||
x[19] += x[3];
|
||||
x[2] = MULT_NORM(( r1 + r0 ) * cPI2_8);
|
||||
x[3] = MULT_NORM(( r1 - r0 ) * cPI2_8);
|
||||
|
||||
r0 = x[0] - x[16];
|
||||
r1 = x[1] - x[17];
|
||||
x[16] += x[0];
|
||||
x[17] += x[1];
|
||||
x[0] = MULT_NORM( r1 * cPI3_8 + r0 * cPI1_8 );
|
||||
x[1] = MULT_NORM( r1 * cPI1_8 - r0 * cPI3_8 );
|
||||
|
||||
mdct_butterfly_16(x);
|
||||
mdct_butterfly_16(x+16);
|
||||
|
||||
}
|
||||
|
||||
/* N point first stage butterfly (in place, 2 register) */
|
||||
STIN void mdct_butterfly_first(DATA_TYPE *T,
|
||||
DATA_TYPE *x,
|
||||
int points){
|
||||
|
||||
DATA_TYPE *x1 = x + points - 8;
|
||||
DATA_TYPE *x2 = x + (points>>1) - 8;
|
||||
REG_TYPE r0;
|
||||
REG_TYPE r1;
|
||||
|
||||
do{
|
||||
|
||||
r0 = x1[6] - x2[6];
|
||||
r1 = x1[7] - x2[7];
|
||||
x1[6] += x2[6];
|
||||
x1[7] += x2[7];
|
||||
x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]);
|
||||
x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]);
|
||||
|
||||
r0 = x1[4] - x2[4];
|
||||
r1 = x1[5] - x2[5];
|
||||
x1[4] += x2[4];
|
||||
x1[5] += x2[5];
|
||||
x2[4] = MULT_NORM(r1 * T[5] + r0 * T[4]);
|
||||
x2[5] = MULT_NORM(r1 * T[4] - r0 * T[5]);
|
||||
|
||||
r0 = x1[2] - x2[2];
|
||||
r1 = x1[3] - x2[3];
|
||||
x1[2] += x2[2];
|
||||
x1[3] += x2[3];
|
||||
x2[2] = MULT_NORM(r1 * T[9] + r0 * T[8]);
|
||||
x2[3] = MULT_NORM(r1 * T[8] - r0 * T[9]);
|
||||
|
||||
r0 = x1[0] - x2[0];
|
||||
r1 = x1[1] - x2[1];
|
||||
x1[0] += x2[0];
|
||||
x1[1] += x2[1];
|
||||
x2[0] = MULT_NORM(r1 * T[13] + r0 * T[12]);
|
||||
x2[1] = MULT_NORM(r1 * T[12] - r0 * T[13]);
|
||||
|
||||
x1-=8;
|
||||
x2-=8;
|
||||
T+=16;
|
||||
|
||||
}while(x2>=x);
|
||||
}
|
||||
|
||||
/* N/stage point generic N stage butterfly (in place, 2 register) */
|
||||
STIN void mdct_butterfly_generic(DATA_TYPE *T,
|
||||
DATA_TYPE *x,
|
||||
int points,
|
||||
int trigint){
|
||||
|
||||
DATA_TYPE *x1 = x + points - 8;
|
||||
DATA_TYPE *x2 = x + (points>>1) - 8;
|
||||
REG_TYPE r0;
|
||||
REG_TYPE r1;
|
||||
|
||||
do{
|
||||
|
||||
r0 = x1[6] - x2[6];
|
||||
r1 = x1[7] - x2[7];
|
||||
x1[6] += x2[6];
|
||||
x1[7] += x2[7];
|
||||
x2[6] = MULT_NORM(r1 * T[1] + r0 * T[0]);
|
||||
x2[7] = MULT_NORM(r1 * T[0] - r0 * T[1]);
|
||||
|
||||
T+=trigint;
|
||||
|
||||
r0 = x1[4] - x2[4];
|
||||
r1 = x1[5] - x2[5];
|
||||
x1[4] += x2[4];
|
||||
x1[5] += x2[5];
|
||||
x2[4] = MULT_NORM(r1 * T[1] + r0 * T[0]);
|
||||
x2[5] = MULT_NORM(r1 * T[0] - r0 * T[1]);
|
||||
|
||||
T+=trigint;
|
||||
|
||||
r0 = x1[2] - x2[2];
|
||||
r1 = x1[3] - x2[3];
|
||||
x1[2] += x2[2];
|
||||
x1[3] += x2[3];
|
||||
x2[2] = MULT_NORM(r1 * T[1] + r0 * T[0]);
|
||||
x2[3] = MULT_NORM(r1 * T[0] - r0 * T[1]);
|
||||
|
||||
T+=trigint;
|
||||
|
||||
r0 = x1[0] - x2[0];
|
||||
r1 = x1[1] - x2[1];
|
||||
x1[0] += x2[0];
|
||||
x1[1] += x2[1];
|
||||
x2[0] = MULT_NORM(r1 * T[1] + r0 * T[0]);
|
||||
x2[1] = MULT_NORM(r1 * T[0] - r0 * T[1]);
|
||||
|
||||
T+=trigint;
|
||||
x1-=8;
|
||||
x2-=8;
|
||||
|
||||
}while(x2>=x);
|
||||
}
|
||||
|
||||
STIN void mdct_butterflies(mdct_lookup *init,
|
||||
DATA_TYPE *x,
|
||||
int points){
|
||||
|
||||
DATA_TYPE *T=init->trig;
|
||||
int stages=init->log2n-5;
|
||||
int i,j;
|
||||
|
||||
if(--stages>0){
|
||||
mdct_butterfly_first(T,x,points);
|
||||
}
|
||||
|
||||
for(i=1;--stages>0;i++){
|
||||
for(j=0;j<(1<<i);j++)
|
||||
mdct_butterfly_generic(T,x+(points>>i)*j,points>>i,4<<i);
|
||||
}
|
||||
|
||||
for(j=0;j<points;j+=32)
|
||||
mdct_butterfly_32(x+j);
|
||||
|
||||
}
|
||||
|
||||
void mdct_clear(mdct_lookup *l){
|
||||
if(l){
|
||||
if(l->trig)_ogg_free(l->trig);
|
||||
if(l->bitrev)_ogg_free(l->bitrev);
|
||||
memset(l,0,sizeof(*l));
|
||||
}
|
||||
}
|
||||
|
||||
STIN void mdct_bitreverse(mdct_lookup *init,
|
||||
DATA_TYPE *x){
|
||||
int n = init->n;
|
||||
int *bit = init->bitrev;
|
||||
DATA_TYPE *w0 = x;
|
||||
DATA_TYPE *w1 = x = w0+(n>>1);
|
||||
DATA_TYPE *T = init->trig+n;
|
||||
|
||||
do{
|
||||
DATA_TYPE *x0 = x+bit[0];
|
||||
DATA_TYPE *x1 = x+bit[1];
|
||||
|
||||
REG_TYPE r0 = x0[1] - x1[1];
|
||||
REG_TYPE r1 = x0[0] + x1[0];
|
||||
REG_TYPE r2 = MULT_NORM(r1 * T[0] + r0 * T[1]);
|
||||
REG_TYPE r3 = MULT_NORM(r1 * T[1] - r0 * T[0]);
|
||||
|
||||
w1 -= 4;
|
||||
|
||||
r0 = HALVE(x0[1] + x1[1]);
|
||||
r1 = HALVE(x0[0] - x1[0]);
|
||||
|
||||
w0[0] = r0 + r2;
|
||||
w1[2] = r0 - r2;
|
||||
w0[1] = r1 + r3;
|
||||
w1[3] = r3 - r1;
|
||||
|
||||
x0 = x+bit[2];
|
||||
x1 = x+bit[3];
|
||||
|
||||
r0 = x0[1] - x1[1];
|
||||
r1 = x0[0] + x1[0];
|
||||
r2 = MULT_NORM(r1 * T[2] + r0 * T[3]);
|
||||
r3 = MULT_NORM(r1 * T[3] - r0 * T[2]);
|
||||
|
||||
r0 = HALVE(x0[1] + x1[1]);
|
||||
r1 = HALVE(x0[0] - x1[0]);
|
||||
|
||||
w0[2] = r0 + r2;
|
||||
w1[0] = r0 - r2;
|
||||
w0[3] = r1 + r3;
|
||||
w1[1] = r3 - r1;
|
||||
|
||||
T += 4;
|
||||
bit += 4;
|
||||
w0 += 4;
|
||||
|
||||
}while(w0<w1);
|
||||
}
|
||||
|
||||
void mdct_backward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
|
||||
int n=init->n;
|
||||
int n2=n>>1;
|
||||
int n4=n>>2;
|
||||
|
||||
/* rotate */
|
||||
|
||||
DATA_TYPE *iX = in+n2-7;
|
||||
DATA_TYPE *oX = out+n2+n4;
|
||||
DATA_TYPE *T = init->trig+n4;
|
||||
|
||||
do{
|
||||
oX -= 4;
|
||||
oX[0] = MULT_NORM(-iX[2] * T[3] - iX[0] * T[2]);
|
||||
oX[1] = MULT_NORM (iX[0] * T[3] - iX[2] * T[2]);
|
||||
oX[2] = MULT_NORM(-iX[6] * T[1] - iX[4] * T[0]);
|
||||
oX[3] = MULT_NORM (iX[4] * T[1] - iX[6] * T[0]);
|
||||
iX -= 8;
|
||||
T += 4;
|
||||
}while(iX>=in);
|
||||
|
||||
iX = in+n2-8;
|
||||
oX = out+n2+n4;
|
||||
T = init->trig+n4;
|
||||
|
||||
do{
|
||||
T -= 4;
|
||||
oX[0] = MULT_NORM (iX[4] * T[3] + iX[6] * T[2]);
|
||||
oX[1] = MULT_NORM (iX[4] * T[2] - iX[6] * T[3]);
|
||||
oX[2] = MULT_NORM (iX[0] * T[1] + iX[2] * T[0]);
|
||||
oX[3] = MULT_NORM (iX[0] * T[0] - iX[2] * T[1]);
|
||||
iX -= 8;
|
||||
oX += 4;
|
||||
}while(iX>=in);
|
||||
|
||||
mdct_butterflies(init,out+n2,n2);
|
||||
mdct_bitreverse(init,out);
|
||||
|
||||
/* roatate + window */
|
||||
|
||||
{
|
||||
DATA_TYPE *oX1=out+n2+n4;
|
||||
DATA_TYPE *oX2=out+n2+n4;
|
||||
DATA_TYPE *iX =out;
|
||||
T =init->trig+n2;
|
||||
|
||||
do{
|
||||
oX1-=4;
|
||||
|
||||
oX1[3] = MULT_NORM (iX[0] * T[1] - iX[1] * T[0]);
|
||||
oX2[0] = -MULT_NORM (iX[0] * T[0] + iX[1] * T[1]);
|
||||
|
||||
oX1[2] = MULT_NORM (iX[2] * T[3] - iX[3] * T[2]);
|
||||
oX2[1] = -MULT_NORM (iX[2] * T[2] + iX[3] * T[3]);
|
||||
|
||||
oX1[1] = MULT_NORM (iX[4] * T[5] - iX[5] * T[4]);
|
||||
oX2[2] = -MULT_NORM (iX[4] * T[4] + iX[5] * T[5]);
|
||||
|
||||
oX1[0] = MULT_NORM (iX[6] * T[7] - iX[7] * T[6]);
|
||||
oX2[3] = -MULT_NORM (iX[6] * T[6] + iX[7] * T[7]);
|
||||
|
||||
oX2+=4;
|
||||
iX += 8;
|
||||
T += 8;
|
||||
}while(iX<oX1);
|
||||
|
||||
iX=out+n2+n4;
|
||||
oX1=out+n4;
|
||||
oX2=oX1;
|
||||
|
||||
do{
|
||||
oX1-=4;
|
||||
iX-=4;
|
||||
|
||||
oX2[0] = -(oX1[3] = iX[3]);
|
||||
oX2[1] = -(oX1[2] = iX[2]);
|
||||
oX2[2] = -(oX1[1] = iX[1]);
|
||||
oX2[3] = -(oX1[0] = iX[0]);
|
||||
|
||||
oX2+=4;
|
||||
}while(oX2<iX);
|
||||
|
||||
iX=out+n2+n4;
|
||||
oX1=out+n2+n4;
|
||||
oX2=out+n2;
|
||||
do{
|
||||
oX1-=4;
|
||||
oX1[0]= iX[3];
|
||||
oX1[1]= iX[2];
|
||||
oX1[2]= iX[1];
|
||||
oX1[3]= iX[0];
|
||||
iX+=4;
|
||||
}while(oX1>oX2);
|
||||
}
|
||||
}
|
||||
|
||||
void mdct_forward(mdct_lookup *init, DATA_TYPE *in, DATA_TYPE *out){
|
||||
int n=init->n;
|
||||
int n2=n>>1;
|
||||
int n4=n>>2;
|
||||
int n8=n>>3;
|
||||
DATA_TYPE *w=alloca(n*sizeof(*w)); /* forward needs working space */
|
||||
DATA_TYPE *w2=w+n2;
|
||||
|
||||
/* rotate */
|
||||
|
||||
/* window + rotate + step 1 */
|
||||
|
||||
REG_TYPE r0;
|
||||
REG_TYPE r1;
|
||||
DATA_TYPE *x0=in+n2+n4;
|
||||
DATA_TYPE *x1=x0+1;
|
||||
DATA_TYPE *T=init->trig+n2;
|
||||
|
||||
int i=0;
|
||||
|
||||
for(i=0;i<n8;i+=2){
|
||||
x0 -=4;
|
||||
T-=2;
|
||||
r0= x0[2] + x1[0];
|
||||
r1= x0[0] + x1[2];
|
||||
w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
|
||||
w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
|
||||
x1 +=4;
|
||||
}
|
||||
|
||||
x1=in+1;
|
||||
|
||||
for(;i<n2-n8;i+=2){
|
||||
T-=2;
|
||||
x0 -=4;
|
||||
r0= x0[2] - x1[0];
|
||||
r1= x0[0] - x1[2];
|
||||
w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
|
||||
w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
|
||||
x1 +=4;
|
||||
}
|
||||
|
||||
x0=in+n;
|
||||
|
||||
for(;i<n2;i+=2){
|
||||
T-=2;
|
||||
x0 -=4;
|
||||
r0= -x0[2] - x1[0];
|
||||
r1= -x0[0] - x1[2];
|
||||
w2[i]= MULT_NORM(r1*T[1] + r0*T[0]);
|
||||
w2[i+1]= MULT_NORM(r1*T[0] - r0*T[1]);
|
||||
x1 +=4;
|
||||
}
|
||||
|
||||
|
||||
mdct_butterflies(init,w+n2,n2);
|
||||
mdct_bitreverse(init,w);
|
||||
|
||||
/* roatate + window */
|
||||
|
||||
T=init->trig+n2;
|
||||
x0=out+n2;
|
||||
|
||||
for(i=0;i<n4;i++){
|
||||
x0--;
|
||||
out[i] =MULT_NORM((w[0]*T[0]+w[1]*T[1])*init->scale);
|
||||
x0[0] =MULT_NORM((w[0]*T[1]-w[1]*T[0])*init->scale);
|
||||
w+=2;
|
||||
T+=2;
|
||||
}
|
||||
}
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,46 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: registry for time, floor, res backends and channel mappings
|
||||
last mod: $Id: registry.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "misc.h"
|
||||
/* seems like major overkill now; the backend numbers will grow into
|
||||
the infrastructure soon enough */
|
||||
|
||||
extern vorbis_func_floor floor0_exportbundle;
|
||||
extern vorbis_func_floor floor1_exportbundle;
|
||||
extern vorbis_func_residue residue0_exportbundle;
|
||||
extern vorbis_func_residue residue1_exportbundle;
|
||||
extern vorbis_func_residue residue2_exportbundle;
|
||||
extern vorbis_func_mapping mapping0_exportbundle;
|
||||
|
||||
vorbis_func_floor *_floor_P[]={
|
||||
&floor0_exportbundle,
|
||||
&floor1_exportbundle,
|
||||
};
|
||||
|
||||
vorbis_func_residue *_residue_P[]={
|
||||
&residue0_exportbundle,
|
||||
&residue1_exportbundle,
|
||||
&residue2_exportbundle,
|
||||
};
|
||||
|
||||
vorbis_func_mapping *_mapping_P[]={
|
||||
&mapping0_exportbundle,
|
||||
};
|
||||
|
|
@ -0,0 +1,919 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: residue backend 0, 1 and 2 implementation
|
||||
last mod: $Id: res0.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Slow, slow, slow, simpleminded and did I mention it was slow? The
|
||||
encode/decode loops are coded for clarity and performance is not
|
||||
yet even a nagging little idea lurking in the shadows. Oh and BTW,
|
||||
it's slow. */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "codebook.h"
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
|
||||
#if defined(TRAIN_RES) || defined (TRAIN_RESAUX)
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
vorbis_info_residue0 *info;
|
||||
|
||||
int parts;
|
||||
int stages;
|
||||
codebook *fullbooks;
|
||||
codebook *phrasebook;
|
||||
codebook ***partbooks;
|
||||
|
||||
int partvals;
|
||||
int **decodemap;
|
||||
|
||||
long postbits;
|
||||
long phrasebits;
|
||||
long frames;
|
||||
|
||||
#if defined(TRAIN_RES) || defined(TRAIN_RESAUX)
|
||||
int train_seq;
|
||||
long *training_data[8][64];
|
||||
float training_max[8][64];
|
||||
float training_min[8][64];
|
||||
float tmin;
|
||||
float tmax;
|
||||
#endif
|
||||
|
||||
} vorbis_look_residue0;
|
||||
|
||||
void res0_free_info(vorbis_info_residue *i){
|
||||
vorbis_info_residue0 *info=(vorbis_info_residue0 *)i;
|
||||
if(info){
|
||||
memset(info,0,sizeof(*info));
|
||||
_ogg_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
void res0_free_look(vorbis_look_residue *i){
|
||||
int j;
|
||||
if(i){
|
||||
|
||||
vorbis_look_residue0 *look=(vorbis_look_residue0 *)i;
|
||||
|
||||
#ifdef TRAIN_RES
|
||||
{
|
||||
int j,k,l;
|
||||
for(j=0;j<look->parts;j++){
|
||||
/*fprintf(stderr,"partition %d: ",j);*/
|
||||
for(k=0;k<8;k++)
|
||||
if(look->training_data[k][j]){
|
||||
char buffer[80];
|
||||
FILE *of;
|
||||
codebook *statebook=look->partbooks[j][k];
|
||||
|
||||
/* long and short into the same bucket by current convention */
|
||||
sprintf(buffer,"res_part%d_pass%d.vqd",j,k);
|
||||
of=fopen(buffer,"a");
|
||||
|
||||
for(l=0;l<statebook->entries;l++)
|
||||
fprintf(of,"%d:%ld\n",l,look->training_data[k][j][l]);
|
||||
|
||||
fclose(of);
|
||||
|
||||
/*fprintf(stderr,"%d(%.2f|%.2f) ",k,
|
||||
look->training_min[k][j],look->training_max[k][j]);*/
|
||||
|
||||
_ogg_free(look->training_data[k][j]);
|
||||
look->training_data[k][j]=NULL;
|
||||
}
|
||||
/*fprintf(stderr,"\n");*/
|
||||
}
|
||||
}
|
||||
fprintf(stderr,"min/max residue: %g::%g\n",look->tmin,look->tmax);
|
||||
|
||||
/*fprintf(stderr,"residue bit usage %f:%f (%f total)\n",
|
||||
(float)look->phrasebits/look->frames,
|
||||
(float)look->postbits/look->frames,
|
||||
(float)(look->postbits+look->phrasebits)/look->frames);*/
|
||||
#endif
|
||||
|
||||
|
||||
/*vorbis_info_residue0 *info=look->info;
|
||||
|
||||
fprintf(stderr,
|
||||
"%ld frames encoded in %ld phrasebits and %ld residue bits "
|
||||
"(%g/frame) \n",look->frames,look->phrasebits,
|
||||
look->resbitsflat,
|
||||
(look->phrasebits+look->resbitsflat)/(float)look->frames);
|
||||
|
||||
for(j=0;j<look->parts;j++){
|
||||
long acc=0;
|
||||
fprintf(stderr,"\t[%d] == ",j);
|
||||
for(k=0;k<look->stages;k++)
|
||||
if((info->secondstages[j]>>k)&1){
|
||||
fprintf(stderr,"%ld,",look->resbits[j][k]);
|
||||
acc+=look->resbits[j][k];
|
||||
}
|
||||
|
||||
fprintf(stderr,":: (%ld vals) %1.2fbits/sample\n",look->resvals[j],
|
||||
acc?(float)acc/(look->resvals[j]*info->grouping):0);
|
||||
}
|
||||
fprintf(stderr,"\n");*/
|
||||
|
||||
for(j=0;j<look->parts;j++)
|
||||
if(look->partbooks[j])_ogg_free(look->partbooks[j]);
|
||||
_ogg_free(look->partbooks);
|
||||
for(j=0;j<look->partvals;j++)
|
||||
_ogg_free(look->decodemap[j]);
|
||||
_ogg_free(look->decodemap);
|
||||
|
||||
memset(look,0,sizeof(*look));
|
||||
_ogg_free(look);
|
||||
}
|
||||
}
|
||||
|
||||
static int ilog(unsigned int v){
|
||||
int ret=0;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int icount(unsigned int v){
|
||||
int ret=0;
|
||||
while(v){
|
||||
ret+=v&1;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
void res0_pack(vorbis_info_residue *vr,oggpack_buffer *opb){
|
||||
vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr;
|
||||
int j,acc=0;
|
||||
oggpack_write(opb,info->begin,24);
|
||||
oggpack_write(opb,info->end,24);
|
||||
|
||||
oggpack_write(opb,info->grouping-1,24); /* residue vectors to group and
|
||||
code with a partitioned book */
|
||||
oggpack_write(opb,info->partitions-1,6); /* possible partition choices */
|
||||
oggpack_write(opb,info->groupbook,8); /* group huffman book */
|
||||
|
||||
/* secondstages is a bitmask; as encoding progresses pass by pass, a
|
||||
bitmask of one indicates this partition class has bits to write
|
||||
this pass */
|
||||
for(j=0;j<info->partitions;j++){
|
||||
if(ilog(info->secondstages[j])>3){
|
||||
/* yes, this is a minor hack due to not thinking ahead */
|
||||
oggpack_write(opb,info->secondstages[j],3);
|
||||
oggpack_write(opb,1,1);
|
||||
oggpack_write(opb,info->secondstages[j]>>3,5);
|
||||
}else
|
||||
oggpack_write(opb,info->secondstages[j],4); /* trailing zero */
|
||||
acc+=icount(info->secondstages[j]);
|
||||
}
|
||||
for(j=0;j<acc;j++)
|
||||
oggpack_write(opb,info->booklist[j],8);
|
||||
|
||||
}
|
||||
|
||||
/* vorbis_info is for range checking */
|
||||
vorbis_info_residue *res0_unpack(vorbis_info *vi,oggpack_buffer *opb){
|
||||
int j,acc=0;
|
||||
vorbis_info_residue0 *info=_ogg_calloc(1,sizeof(*info));
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
|
||||
info->begin=oggpack_read(opb,24);
|
||||
info->end=oggpack_read(opb,24);
|
||||
info->grouping=oggpack_read(opb,24)+1;
|
||||
info->partitions=oggpack_read(opb,6)+1;
|
||||
info->groupbook=oggpack_read(opb,8);
|
||||
|
||||
for(j=0;j<info->partitions;j++){
|
||||
int cascade=oggpack_read(opb,3);
|
||||
if(oggpack_read(opb,1))
|
||||
cascade|=(oggpack_read(opb,5)<<3);
|
||||
info->secondstages[j]=cascade;
|
||||
|
||||
acc+=icount(cascade);
|
||||
}
|
||||
for(j=0;j<acc;j++)
|
||||
info->booklist[j]=oggpack_read(opb,8);
|
||||
|
||||
if(info->groupbook>=ci->books)goto errout;
|
||||
for(j=0;j<acc;j++)
|
||||
if(info->booklist[j]>=ci->books)goto errout;
|
||||
|
||||
return(info);
|
||||
errout:
|
||||
res0_free_info(info);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
vorbis_look_residue *res0_look(vorbis_dsp_state *vd,
|
||||
vorbis_info_residue *vr){
|
||||
vorbis_info_residue0 *info=(vorbis_info_residue0 *)vr;
|
||||
vorbis_look_residue0 *look=_ogg_calloc(1,sizeof(*look));
|
||||
codec_setup_info *ci=vd->vi->codec_setup;
|
||||
|
||||
int j,k,acc=0;
|
||||
int dim;
|
||||
int maxstage=0;
|
||||
look->info=info;
|
||||
|
||||
look->parts=info->partitions;
|
||||
look->fullbooks=ci->fullbooks;
|
||||
look->phrasebook=ci->fullbooks+info->groupbook;
|
||||
dim=look->phrasebook->dim;
|
||||
|
||||
look->partbooks=_ogg_calloc(look->parts,sizeof(*look->partbooks));
|
||||
|
||||
for(j=0;j<look->parts;j++){
|
||||
int stages=ilog(info->secondstages[j]);
|
||||
if(stages){
|
||||
if(stages>maxstage)maxstage=stages;
|
||||
look->partbooks[j]=_ogg_calloc(stages,sizeof(*look->partbooks[j]));
|
||||
for(k=0;k<stages;k++)
|
||||
if(info->secondstages[j]&(1<<k)){
|
||||
look->partbooks[j][k]=ci->fullbooks+info->booklist[acc++];
|
||||
#ifdef TRAIN_RES
|
||||
look->training_data[k][j]=_ogg_calloc(look->partbooks[j][k]->entries,
|
||||
sizeof(***look->training_data));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
look->partvals=rint(pow((float)look->parts,(float)dim));
|
||||
look->stages=maxstage;
|
||||
look->decodemap=_ogg_malloc(look->partvals*sizeof(*look->decodemap));
|
||||
for(j=0;j<look->partvals;j++){
|
||||
long val=j;
|
||||
long mult=look->partvals/look->parts;
|
||||
look->decodemap[j]=_ogg_malloc(dim*sizeof(*look->decodemap[j]));
|
||||
for(k=0;k<dim;k++){
|
||||
long deco=val/mult;
|
||||
val-=deco*mult;
|
||||
mult/=look->parts;
|
||||
look->decodemap[j][k]=deco;
|
||||
}
|
||||
}
|
||||
#if defined(TRAIN_RES) || defined (TRAIN_RESAUX)
|
||||
{
|
||||
static int train_seq=0;
|
||||
look->train_seq=train_seq++;
|
||||
}
|
||||
#endif
|
||||
return(look);
|
||||
}
|
||||
|
||||
/* break an abstraction and copy some code for performance purposes */
|
||||
static int local_book_besterror(codebook *book,float *a){
|
||||
int dim=book->dim,i,k,o;
|
||||
int best=0;
|
||||
encode_aux_threshmatch *tt=book->c->thresh_tree;
|
||||
|
||||
/* find the quant val of each scalar */
|
||||
for(k=0,o=dim;k<dim;++k){
|
||||
float val=a[--o];
|
||||
i=tt->threshvals>>1;
|
||||
|
||||
if(val<tt->quantthresh[i]){
|
||||
if(val<tt->quantthresh[i-1]){
|
||||
for(--i;i>0;--i)
|
||||
if(val>=tt->quantthresh[i-1])
|
||||
break;
|
||||
}
|
||||
}else{
|
||||
|
||||
for(++i;i<tt->threshvals-1;++i)
|
||||
if(val<tt->quantthresh[i])break;
|
||||
|
||||
}
|
||||
|
||||
best=(best*tt->quantvals)+tt->quantmap[i];
|
||||
}
|
||||
/* regular lattices are easy :-) */
|
||||
|
||||
if(book->c->lengthlist[best]<=0){
|
||||
const static_codebook *c=book->c;
|
||||
int i,j;
|
||||
float bestf=0.f;
|
||||
float *e=book->valuelist;
|
||||
best=-1;
|
||||
for(i=0;i<book->entries;i++){
|
||||
if(c->lengthlist[i]>0){
|
||||
float this=0.f;
|
||||
for(j=0;j<dim;j++){
|
||||
float val=(e[j]-a[j]);
|
||||
this+=val*val;
|
||||
}
|
||||
if(best==-1 || this<bestf){
|
||||
bestf=this;
|
||||
best=i;
|
||||
}
|
||||
}
|
||||
e+=dim;
|
||||
}
|
||||
}
|
||||
|
||||
if(best>-1){
|
||||
float *ptr=book->valuelist+best*dim;
|
||||
for(i=0;i<dim;i++)
|
||||
*a++ -= *ptr++;
|
||||
}
|
||||
|
||||
return(best);
|
||||
}
|
||||
|
||||
static int _encodepart(oggpack_buffer *opb,float *vec, int n,
|
||||
codebook *book,long *acc){
|
||||
int i,bits=0;
|
||||
int dim=book->dim;
|
||||
int step=n/dim;
|
||||
|
||||
for(i=0;i<step;i++){
|
||||
int entry=local_book_besterror(book,vec+i*dim);
|
||||
|
||||
#ifdef TRAIN_RES
|
||||
if(entry>0)
|
||||
acc[entry]++;
|
||||
#endif
|
||||
|
||||
bits+=vorbis_book_encode(book,entry,opb);
|
||||
|
||||
}
|
||||
|
||||
return(bits);
|
||||
}
|
||||
|
||||
static long **_01class(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int ch){
|
||||
long i,j,k;
|
||||
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
||||
vorbis_info_residue0 *info=look->info;
|
||||
vorbis_info *vi=vb->vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
|
||||
/* move all this setup out later */
|
||||
int samples_per_partition=info->grouping;
|
||||
int possible_partitions=info->partitions;
|
||||
int n=info->end-info->begin;
|
||||
|
||||
int partvals=n/samples_per_partition;
|
||||
long **partword=_vorbis_block_alloc(vb,ch*sizeof(*partword));
|
||||
float scale=100./samples_per_partition;
|
||||
|
||||
/* we find the partition type for each partition of each
|
||||
channel. We'll go back and do the interleaved encoding in a
|
||||
bit. For now, clarity */
|
||||
|
||||
for(i=0;i<ch;i++){
|
||||
partword[i]=_vorbis_block_alloc(vb,n/samples_per_partition*sizeof(*partword[i]));
|
||||
memset(partword[i],0,n/samples_per_partition*sizeof(*partword[i]));
|
||||
}
|
||||
|
||||
for(i=0;i<partvals;i++){
|
||||
int offset=i*samples_per_partition+info->begin;
|
||||
for(j=0;j<ch;j++){
|
||||
float max=0.;
|
||||
float ent=0.;
|
||||
for(k=0;k<samples_per_partition;k++){
|
||||
if(fabs(in[j][offset+k])>max)max=fabs(in[j][offset+k]);
|
||||
ent+=fabs(rint(in[j][offset+k]));
|
||||
}
|
||||
ent*=scale;
|
||||
|
||||
for(k=0;k<possible_partitions-1;k++)
|
||||
if(max<=info->classmetric1[k] &&
|
||||
(info->classmetric2[k]<0 || (int)ent<info->classmetric2[k]))
|
||||
break;
|
||||
|
||||
partword[j][i]=k;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef TRAIN_RESAUX
|
||||
{
|
||||
FILE *of;
|
||||
char buffer[80];
|
||||
|
||||
for(i=0;i<ch;i++){
|
||||
sprintf(buffer,"resaux_%d.vqd",look->train_seq);
|
||||
of=fopen(buffer,"a");
|
||||
for(j=0;j<partvals;j++)
|
||||
fprintf(of,"%ld, ",partword[i][j]);
|
||||
fprintf(of,"\n");
|
||||
fclose(of);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
look->frames++;
|
||||
|
||||
return(partword);
|
||||
}
|
||||
|
||||
/* designed for stereo or other modes where the partition size is an
|
||||
integer multiple of the number of channels encoded in the current
|
||||
submap */
|
||||
static long **_2class(vorbis_block *vb,vorbis_look_residue *vl,float **in,
|
||||
int ch){
|
||||
long i,j,k,l;
|
||||
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
||||
vorbis_info_residue0 *info=look->info;
|
||||
|
||||
/* move all this setup out later */
|
||||
int samples_per_partition=info->grouping;
|
||||
int possible_partitions=info->partitions;
|
||||
int n=info->end-info->begin;
|
||||
|
||||
int partvals=n/samples_per_partition;
|
||||
long **partword=_vorbis_block_alloc(vb,sizeof(*partword));
|
||||
|
||||
#if defined(TRAIN_RES) || defined (TRAIN_RESAUX)
|
||||
FILE *of;
|
||||
char buffer[80];
|
||||
#endif
|
||||
|
||||
partword[0]=_vorbis_block_alloc(vb,n*ch/samples_per_partition*sizeof(*partword[0]));
|
||||
memset(partword[0],0,n*ch/samples_per_partition*sizeof(*partword[0]));
|
||||
|
||||
for(i=0,l=info->begin/ch;i<partvals;i++){
|
||||
float magmax=0.f;
|
||||
float angmax=0.f;
|
||||
for(j=0;j<samples_per_partition;j+=ch){
|
||||
if(fabs(in[0][l])>magmax)magmax=fabs(in[0][l]);
|
||||
for(k=1;k<ch;k++)
|
||||
if(fabs(in[k][l])>angmax)angmax=fabs(in[k][l]);
|
||||
l++;
|
||||
}
|
||||
|
||||
for(j=0;j<possible_partitions-1;j++)
|
||||
if(magmax<=info->classmetric1[j] &&
|
||||
angmax<=info->classmetric2[j])
|
||||
break;
|
||||
|
||||
partword[0][i]=j;
|
||||
|
||||
}
|
||||
|
||||
#ifdef TRAIN_RESAUX
|
||||
sprintf(buffer,"resaux_%d.vqd",look->train_seq);
|
||||
of=fopen(buffer,"a");
|
||||
for(i=0;i<partvals;i++)
|
||||
fprintf(of,"%ld, ",partword[0][i]);
|
||||
fprintf(of,"\n");
|
||||
fclose(of);
|
||||
#endif
|
||||
|
||||
look->frames++;
|
||||
|
||||
return(partword);
|
||||
}
|
||||
|
||||
static int _01forward(oggpack_buffer *opb,
|
||||
vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int ch,
|
||||
long **partword,
|
||||
int (*encode)(oggpack_buffer *,float *,int,
|
||||
codebook *,long *)){
|
||||
long i,j,k,s;
|
||||
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
||||
vorbis_info_residue0 *info=look->info;
|
||||
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
|
||||
/* move all this setup out later */
|
||||
int samples_per_partition=info->grouping;
|
||||
int possible_partitions=info->partitions;
|
||||
int partitions_per_word=look->phrasebook->dim;
|
||||
int n=info->end-info->begin;
|
||||
|
||||
int partvals=n/samples_per_partition;
|
||||
long resbits[128];
|
||||
long resvals[128];
|
||||
|
||||
#ifdef TRAIN_RES
|
||||
for(i=0;i<ch;i++)
|
||||
for(j=info->begin;j<end;j++){
|
||||
if(in[i][j]>look->tmax)look->tmax=in[i][j];
|
||||
if(in[i][j]<look->tmin)look->tmin=in[i][j];
|
||||
}
|
||||
#endif
|
||||
|
||||
memset(resbits,0,sizeof(resbits));
|
||||
memset(resvals,0,sizeof(resvals));
|
||||
|
||||
/* we code the partition words for each channel, then the residual
|
||||
words for a partition per channel until we've written all the
|
||||
residual words for that partition word. Then write the next
|
||||
partition channel words... */
|
||||
|
||||
for(s=0;s<look->stages;s++){
|
||||
|
||||
for(i=0;i<partvals;){
|
||||
|
||||
/* first we encode a partition codeword for each channel */
|
||||
if(s==0){
|
||||
for(j=0;j<ch;j++){
|
||||
long val=partword[j][i];
|
||||
for(k=1;k<partitions_per_word;k++){
|
||||
val*=possible_partitions;
|
||||
if(i+k<partvals)
|
||||
val+=partword[j][i+k];
|
||||
}
|
||||
|
||||
/* training hack */
|
||||
if(val<look->phrasebook->entries)
|
||||
look->phrasebits+=vorbis_book_encode(look->phrasebook,val,opb);
|
||||
#if 0 /*def TRAIN_RES*/
|
||||
else
|
||||
fprintf(stderr,"!");
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* now we encode interleaved residual values for the partitions */
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++){
|
||||
long offset=i*samples_per_partition+info->begin;
|
||||
|
||||
for(j=0;j<ch;j++){
|
||||
if(s==0)resvals[partword[j][i]]+=samples_per_partition;
|
||||
if(info->secondstages[partword[j][i]]&(1<<s)){
|
||||
codebook *statebook=look->partbooks[partword[j][i]][s];
|
||||
if(statebook){
|
||||
int ret;
|
||||
long *accumulator=NULL;
|
||||
|
||||
#ifdef TRAIN_RES
|
||||
accumulator=look->training_data[s][partword[j][i]];
|
||||
{
|
||||
int l;
|
||||
float *samples=in[j]+offset;
|
||||
for(l=0;l<samples_per_partition;l++){
|
||||
if(samples[l]<look->training_min[s][partword[j][i]])
|
||||
look->training_min[s][partword[j][i]]=samples[l];
|
||||
if(samples[l]>look->training_max[s][partword[j][i]])
|
||||
look->training_max[s][partword[j][i]]=samples[l];
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
ret=encode(opb,in[j]+offset,samples_per_partition,
|
||||
statebook,accumulator);
|
||||
|
||||
look->postbits+=ret;
|
||||
resbits[partword[j][i]]+=ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*{
|
||||
long total=0;
|
||||
long totalbits=0;
|
||||
fprintf(stderr,"%d :: ",vb->mode);
|
||||
for(k=0;k<possible_partitions;k++){
|
||||
fprintf(stderr,"%ld/%1.2g, ",resvals[k],(float)resbits[k]/resvals[k]);
|
||||
total+=resvals[k];
|
||||
totalbits+=resbits[k];
|
||||
}
|
||||
|
||||
fprintf(stderr,":: %ld:%1.2g\n",total,(double)totalbits/total);
|
||||
}*/
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* a truncated packet here just means 'stop working'; it's not an error */
|
||||
static int _01inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int ch,
|
||||
long (*decodepart)(codebook *, float *,
|
||||
oggpack_buffer *,int)){
|
||||
|
||||
long i,j,k,l,s;
|
||||
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
||||
vorbis_info_residue0 *info=look->info;
|
||||
|
||||
/* move all this setup out later */
|
||||
int samples_per_partition=info->grouping;
|
||||
int partitions_per_word=look->phrasebook->dim;
|
||||
int max=vb->pcmend>>1;
|
||||
int end=(info->end<max?info->end:max);
|
||||
int n=end-info->begin;
|
||||
|
||||
if(n>0){
|
||||
int partvals=n/samples_per_partition;
|
||||
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
||||
int ***partword=alloca(ch*sizeof(*partword));
|
||||
|
||||
for(j=0;j<ch;j++)
|
||||
partword[j]=_vorbis_block_alloc(vb,partwords*sizeof(*partword[j]));
|
||||
|
||||
for(s=0;s<look->stages;s++){
|
||||
|
||||
/* each loop decodes on partition codeword containing
|
||||
partitions_per_word partitions */
|
||||
for(i=0,l=0;i<partvals;l++){
|
||||
if(s==0){
|
||||
/* fetch the partition word for each channel */
|
||||
for(j=0;j<ch;j++){
|
||||
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
|
||||
|
||||
if(temp==-1)goto eopbreak;
|
||||
partword[j][l]=look->decodemap[temp];
|
||||
if(partword[j][l]==NULL)goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
/* now we decode residual values for the partitions */
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
||||
for(j=0;j<ch;j++){
|
||||
long offset=info->begin+i*samples_per_partition;
|
||||
if(info->secondstages[partword[j][l][k]]&(1<<s)){
|
||||
codebook *stagebook=look->partbooks[partword[j][l][k]][s];
|
||||
if(stagebook){
|
||||
if(decodepart(stagebook,in[j]+offset,&vb->opb,
|
||||
samples_per_partition)==-1)goto eopbreak;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
errout:
|
||||
eopbreak:
|
||||
return(0);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* residue 0 and 1 are just slight variants of one another. 0 is
|
||||
interleaved, 1 is not */
|
||||
long **res0_class(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int *nonzero,int ch){
|
||||
/* we encode only the nonzero parts of a bundle */
|
||||
int i,used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i])
|
||||
in[used++]=in[i];
|
||||
if(used)
|
||||
/*return(_01class(vb,vl,in,used,_interleaved_testhack));*/
|
||||
return(_01class(vb,vl,in,used));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
int res0_forward(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,float **out,int *nonzero,int ch,
|
||||
long **partword){
|
||||
/* we encode only the nonzero parts of a bundle */
|
||||
int i,j,used=0,n=vb->pcmend/2;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i]){
|
||||
if(out)
|
||||
for(j=0;j<n;j++)
|
||||
out[i][j]+=in[i][j];
|
||||
in[used++]=in[i];
|
||||
}
|
||||
if(used){
|
||||
int ret=_01forward(vb,vl,in,used,partword,
|
||||
_interleaved_encodepart);
|
||||
if(out){
|
||||
used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i]){
|
||||
for(j=0;j<n;j++)
|
||||
out[i][j]-=in[used][j];
|
||||
used++;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}else{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int res0_inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int *nonzero,int ch){
|
||||
int i,used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i])
|
||||
in[used++]=in[i];
|
||||
if(used)
|
||||
return(_01inverse(vb,vl,in,used,vorbis_book_decodevs_add));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
int res1_forward(oggpack_buffer *opb,vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,float **out,int *nonzero,int ch,
|
||||
long **partword){
|
||||
int i,j,used=0,n=vb->pcmend/2;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i]){
|
||||
if(out)
|
||||
for(j=0;j<n;j++)
|
||||
out[i][j]+=in[i][j];
|
||||
in[used++]=in[i];
|
||||
}
|
||||
|
||||
if(used){
|
||||
int ret=_01forward(opb,vb,vl,in,used,partword,_encodepart);
|
||||
if(out){
|
||||
used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i]){
|
||||
for(j=0;j<n;j++)
|
||||
out[i][j]-=in[used][j];
|
||||
used++;
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}else{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
long **res1_class(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int *nonzero,int ch){
|
||||
int i,used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i])
|
||||
in[used++]=in[i];
|
||||
if(used)
|
||||
return(_01class(vb,vl,in,used));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
int res1_inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int *nonzero,int ch){
|
||||
int i,used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i])
|
||||
in[used++]=in[i];
|
||||
if(used)
|
||||
return(_01inverse(vb,vl,in,used,vorbis_book_decodev_add));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
long **res2_class(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int *nonzero,int ch){
|
||||
int i,used=0;
|
||||
for(i=0;i<ch;i++)
|
||||
if(nonzero[i])used++;
|
||||
if(used)
|
||||
return(_2class(vb,vl,in,ch));
|
||||
else
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* res2 is slightly more different; all the channels are interleaved
|
||||
into a single vector and encoded. */
|
||||
|
||||
int res2_forward(oggpack_buffer *opb,
|
||||
vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,float **out,int *nonzero,int ch,
|
||||
long **partword){
|
||||
long i,j,k,n=vb->pcmend/2,used=0;
|
||||
|
||||
/* don't duplicate the code; use a working vector hack for now and
|
||||
reshape ourselves into a single channel res1 */
|
||||
/* ugly; reallocs for each coupling pass :-( */
|
||||
float *work=_vorbis_block_alloc(vb,ch*n*sizeof(*work));
|
||||
for(i=0;i<ch;i++){
|
||||
float *pcm=in[i];
|
||||
if(nonzero[i])used++;
|
||||
for(j=0,k=i;j<n;j++,k+=ch)
|
||||
work[k]=pcm[j];
|
||||
}
|
||||
|
||||
if(used){
|
||||
int ret=_01forward(opb,vb,vl,&work,1,partword,_encodepart);
|
||||
/* update the sofar vector */
|
||||
if(out){
|
||||
for(i=0;i<ch;i++){
|
||||
float *pcm=in[i];
|
||||
float *sofar=out[i];
|
||||
for(j=0,k=i;j<n;j++,k+=ch)
|
||||
sofar[j]+=pcm[j]-work[k];
|
||||
|
||||
}
|
||||
}
|
||||
return(ret);
|
||||
}else{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
/* duplicate code here as speed is somewhat more important */
|
||||
int res2_inverse(vorbis_block *vb,vorbis_look_residue *vl,
|
||||
float **in,int *nonzero,int ch){
|
||||
long i,k,l,s;
|
||||
vorbis_look_residue0 *look=(vorbis_look_residue0 *)vl;
|
||||
vorbis_info_residue0 *info=look->info;
|
||||
|
||||
/* move all this setup out later */
|
||||
int samples_per_partition=info->grouping;
|
||||
int partitions_per_word=look->phrasebook->dim;
|
||||
int max=(vb->pcmend*ch)>>1;
|
||||
int end=(info->end<max?info->end:max);
|
||||
int n=end-info->begin;
|
||||
|
||||
if(n>0){
|
||||
int partvals=n/samples_per_partition;
|
||||
int partwords=(partvals+partitions_per_word-1)/partitions_per_word;
|
||||
int **partword=_vorbis_block_alloc(vb,partwords*sizeof(*partword));
|
||||
|
||||
for(i=0;i<ch;i++)if(nonzero[i])break;
|
||||
if(i==ch)return(0); /* no nonzero vectors */
|
||||
|
||||
for(s=0;s<look->stages;s++){
|
||||
for(i=0,l=0;i<partvals;l++){
|
||||
|
||||
if(s==0){
|
||||
/* fetch the partition word */
|
||||
int temp=vorbis_book_decode(look->phrasebook,&vb->opb);
|
||||
if(temp==-1)goto eopbreak;
|
||||
partword[l]=look->decodemap[temp];
|
||||
if(partword[l]==NULL)goto errout;
|
||||
}
|
||||
|
||||
/* now we decode residual values for the partitions */
|
||||
for(k=0;k<partitions_per_word && i<partvals;k++,i++)
|
||||
if(info->secondstages[partword[l][k]]&(1<<s)){
|
||||
codebook *stagebook=look->partbooks[partword[l][k]][s];
|
||||
|
||||
if(stagebook){
|
||||
if(vorbis_book_decodevv_add(stagebook,in,
|
||||
i*samples_per_partition+info->begin,ch,
|
||||
&vb->opb,samples_per_partition)==-1)
|
||||
goto eopbreak;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
errout:
|
||||
eopbreak:
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
vorbis_func_residue residue0_exportbundle={
|
||||
NULL,
|
||||
&res0_unpack,
|
||||
&res0_look,
|
||||
&res0_free_info,
|
||||
&res0_free_look,
|
||||
NULL,
|
||||
NULL,
|
||||
&res0_inverse
|
||||
};
|
||||
|
||||
vorbis_func_residue residue1_exportbundle={
|
||||
&res0_pack,
|
||||
&res0_unpack,
|
||||
&res0_look,
|
||||
&res0_free_info,
|
||||
&res0_free_look,
|
||||
&res1_class,
|
||||
&res1_forward,
|
||||
&res1_inverse
|
||||
};
|
||||
|
||||
vorbis_func_residue residue2_exportbundle={
|
||||
&res0_pack,
|
||||
&res0_unpack,
|
||||
&res0_look,
|
||||
&res0_free_info,
|
||||
&res0_free_look,
|
||||
&res2_class,
|
||||
&res2_forward,
|
||||
&res2_inverse
|
||||
};
|
||||
|
|
@ -0,0 +1,735 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic shared codebook operations
|
||||
last mod: $Id: sharedbook.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
#include "vorbis/codec.h"
|
||||
#include "codebook.h"
|
||||
#include "scales.h"
|
||||
|
||||
/**** pack/unpack helpers ******************************************/
|
||||
int _ilog(unsigned int v){
|
||||
int ret=0;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* 32 bit float (not IEEE; nonnormalized mantissa +
|
||||
biased exponent) : neeeeeee eeemmmmm mmmmmmmm mmmmmmmm
|
||||
Why not IEEE? It's just not that important here. */
|
||||
|
||||
#define VQ_FEXP 10
|
||||
#define VQ_FMAN 21
|
||||
#define VQ_FEXP_BIAS 768 /* bias toward values smaller than 1. */
|
||||
|
||||
/* doesn't currently guard under/overflow */
|
||||
long _float32_pack(float val){
|
||||
int sign=0;
|
||||
long exp;
|
||||
long mant;
|
||||
if(val<0){
|
||||
sign=0x80000000;
|
||||
val= -val;
|
||||
}
|
||||
exp= floor(log(val)/log(2.f));
|
||||
mant=rint(ldexp(val,(VQ_FMAN-1)-exp));
|
||||
exp=(exp+VQ_FEXP_BIAS)<<VQ_FMAN;
|
||||
|
||||
return(sign|exp|mant);
|
||||
}
|
||||
|
||||
float _float32_unpack(long val){
|
||||
double mant=val&0x1fffff;
|
||||
int sign=val&0x80000000;
|
||||
long exp =(val&0x7fe00000L)>>VQ_FMAN;
|
||||
if(sign)mant= -mant;
|
||||
return(ldexp(mant,exp-(VQ_FMAN-1)-VQ_FEXP_BIAS));
|
||||
}
|
||||
|
||||
/* given a list of word lengths, generate a list of codewords. Works
|
||||
for length ordered or unordered, always assigns the lowest valued
|
||||
codewords first. Extended to handle unused entries (length 0) */
|
||||
ogg_uint32_t *_make_words(long *l,long n,long sparsecount){
|
||||
long i,j,count=0;
|
||||
ogg_uint32_t marker[33];
|
||||
ogg_uint32_t *r=_ogg_malloc((sparsecount?sparsecount:n)*sizeof(*r));
|
||||
memset(marker,0,sizeof(marker));
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
long length=l[i];
|
||||
if(length>0){
|
||||
ogg_uint32_t entry=marker[length];
|
||||
|
||||
/* when we claim a node for an entry, we also claim the nodes
|
||||
below it (pruning off the imagined tree that may have dangled
|
||||
from it) as well as blocking the use of any nodes directly
|
||||
above for leaves */
|
||||
|
||||
/* update ourself */
|
||||
if(length<32 && (entry>>length)){
|
||||
/* error condition; the lengths must specify an overpopulated tree */
|
||||
_ogg_free(r);
|
||||
return(NULL);
|
||||
}
|
||||
r[count++]=entry;
|
||||
|
||||
/* Look to see if the next shorter marker points to the node
|
||||
above. if so, update it and repeat. */
|
||||
{
|
||||
for(j=length;j>0;j--){
|
||||
|
||||
if(marker[j]&1){
|
||||
/* have to jump branches */
|
||||
if(j==1)
|
||||
marker[1]++;
|
||||
else
|
||||
marker[j]=marker[j-1]<<1;
|
||||
break; /* invariant says next upper marker would already
|
||||
have been moved if it was on the same path */
|
||||
}
|
||||
marker[j]++;
|
||||
}
|
||||
}
|
||||
|
||||
/* prune the tree; the implicit invariant says all the longer
|
||||
markers were dangling from our just-taken node. Dangle them
|
||||
from our *new* node. */
|
||||
for(j=length+1;j<33;j++)
|
||||
if((marker[j]>>1) == entry){
|
||||
entry=marker[j];
|
||||
marker[j]=marker[j-1]<<1;
|
||||
}else
|
||||
break;
|
||||
}else
|
||||
if(sparsecount==0)count++;
|
||||
}
|
||||
|
||||
/* bitreverse the words because our bitwise packer/unpacker is LSb
|
||||
endian */
|
||||
for(i=0,count=0;i<n;i++){
|
||||
ogg_uint32_t temp=0;
|
||||
for(j=0;j<l[i];j++){
|
||||
temp<<=1;
|
||||
temp|=(r[count]>>j)&1;
|
||||
}
|
||||
|
||||
if(sparsecount){
|
||||
if(l[i])
|
||||
r[count++]=temp;
|
||||
}else
|
||||
r[count++]=temp;
|
||||
}
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
/* there might be a straightforward one-line way to do the below
|
||||
that's portable and totally safe against roundoff, but I haven't
|
||||
thought of it. Therefore, we opt on the side of caution */
|
||||
long _book_maptype1_quantvals(const static_codebook *b){
|
||||
long vals=floor(pow((float)b->entries,1.f/b->dim));
|
||||
|
||||
/* the above *should* be reliable, but we'll not assume that FP is
|
||||
ever reliable when bitstream sync is at stake; verify via integer
|
||||
means that vals really is the greatest value of dim for which
|
||||
vals^b->bim <= b->entries */
|
||||
/* treat the above as an initial guess */
|
||||
while(1){
|
||||
long acc=1;
|
||||
long acc1=1;
|
||||
int i;
|
||||
for(i=0;i<b->dim;i++){
|
||||
acc*=vals;
|
||||
acc1*=vals+1;
|
||||
}
|
||||
if(acc<=b->entries && acc1>b->entries){
|
||||
return(vals);
|
||||
}else{
|
||||
if(acc>b->entries){
|
||||
vals--;
|
||||
}else{
|
||||
vals++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* unpack the quantized list of values for encode/decode ***********/
|
||||
/* we need to deal with two map types: in map type 1, the values are
|
||||
generated algorithmically (each column of the vector counts through
|
||||
the values in the quant vector). in map type 2, all the values came
|
||||
in in an explicit list. Both value lists must be unpacked */
|
||||
float *_book_unquantize(const static_codebook *b,int n,int *sparsemap){
|
||||
long j,k,count=0;
|
||||
if(b->maptype==1 || b->maptype==2){
|
||||
int quantvals;
|
||||
float mindel=_float32_unpack(b->q_min);
|
||||
float delta=_float32_unpack(b->q_delta);
|
||||
float *r=_ogg_calloc(n*b->dim,sizeof(*r));
|
||||
|
||||
/* maptype 1 and 2 both use a quantized value vector, but
|
||||
different sizes */
|
||||
switch(b->maptype){
|
||||
case 1:
|
||||
/* most of the time, entries%dimensions == 0, but we need to be
|
||||
well defined. We define that the possible vales at each
|
||||
scalar is values == entries/dim. If entries%dim != 0, we'll
|
||||
have 'too few' values (values*dim<entries), which means that
|
||||
we'll have 'left over' entries; left over entries use zeroed
|
||||
values (and are wasted). So don't generate codebooks like
|
||||
that */
|
||||
quantvals=_book_maptype1_quantvals(b);
|
||||
for(j=0;j<b->entries;j++){
|
||||
if((sparsemap && b->lengthlist[j]) || !sparsemap){
|
||||
float last=0.f;
|
||||
int indexdiv=1;
|
||||
for(k=0;k<b->dim;k++){
|
||||
int index= (j/indexdiv)%quantvals;
|
||||
float val=b->quantlist[index];
|
||||
val=fabs(val)*delta+mindel+last;
|
||||
if(b->q_sequencep)last=val;
|
||||
if(sparsemap)
|
||||
r[sparsemap[count]*b->dim+k]=val;
|
||||
else
|
||||
r[count*b->dim+k]=val;
|
||||
indexdiv*=quantvals;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(j=0;j<b->entries;j++){
|
||||
if((sparsemap && b->lengthlist[j]) || !sparsemap){
|
||||
float last=0.f;
|
||||
|
||||
for(k=0;k<b->dim;k++){
|
||||
float val=b->quantlist[j*b->dim+k];
|
||||
val=fabs(val)*delta+mindel+last;
|
||||
if(b->q_sequencep)last=val;
|
||||
if(sparsemap)
|
||||
r[sparsemap[count]*b->dim+k]=val;
|
||||
else
|
||||
r[count*b->dim+k]=val;
|
||||
}
|
||||
count++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
return(r);
|
||||
}
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
void vorbis_staticbook_clear(static_codebook *b){
|
||||
if(b->allocedp){
|
||||
if(b->quantlist)_ogg_free(b->quantlist);
|
||||
if(b->lengthlist)_ogg_free(b->lengthlist);
|
||||
if(b->nearest_tree){
|
||||
_ogg_free(b->nearest_tree->ptr0);
|
||||
_ogg_free(b->nearest_tree->ptr1);
|
||||
_ogg_free(b->nearest_tree->p);
|
||||
_ogg_free(b->nearest_tree->q);
|
||||
memset(b->nearest_tree,0,sizeof(*b->nearest_tree));
|
||||
_ogg_free(b->nearest_tree);
|
||||
}
|
||||
if(b->thresh_tree){
|
||||
_ogg_free(b->thresh_tree->quantthresh);
|
||||
_ogg_free(b->thresh_tree->quantmap);
|
||||
memset(b->thresh_tree,0,sizeof(*b->thresh_tree));
|
||||
_ogg_free(b->thresh_tree);
|
||||
}
|
||||
|
||||
memset(b,0,sizeof(*b));
|
||||
}
|
||||
}
|
||||
|
||||
void vorbis_staticbook_destroy(static_codebook *b){
|
||||
if(b->allocedp){
|
||||
vorbis_staticbook_clear(b);
|
||||
_ogg_free(b);
|
||||
}
|
||||
}
|
||||
|
||||
void vorbis_book_clear(codebook *b){
|
||||
/* static book is not cleared; we're likely called on the lookup and
|
||||
the static codebook belongs to the info struct */
|
||||
if(b->valuelist)_ogg_free(b->valuelist);
|
||||
if(b->codelist)_ogg_free(b->codelist);
|
||||
|
||||
if(b->dec_index)_ogg_free(b->dec_index);
|
||||
if(b->dec_codelengths)_ogg_free(b->dec_codelengths);
|
||||
if(b->dec_firsttable)_ogg_free(b->dec_firsttable);
|
||||
|
||||
memset(b,0,sizeof(*b));
|
||||
}
|
||||
|
||||
int vorbis_book_init_encode(codebook *c,const static_codebook *s){
|
||||
|
||||
memset(c,0,sizeof(*c));
|
||||
c->c=s;
|
||||
c->entries=s->entries;
|
||||
c->used_entries=s->entries;
|
||||
c->dim=s->dim;
|
||||
c->codelist=_make_words(s->lengthlist,s->entries,0);
|
||||
c->valuelist=_book_unquantize(s,s->entries,NULL);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static ogg_uint32_t bitreverse(ogg_uint32_t x){
|
||||
x= ((x>>16)&0x0000ffffUL) | ((x<<16)&0xffff0000UL);
|
||||
x= ((x>> 8)&0x00ff00ffUL) | ((x<< 8)&0xff00ff00UL);
|
||||
x= ((x>> 4)&0x0f0f0f0fUL) | ((x<< 4)&0xf0f0f0f0UL);
|
||||
x= ((x>> 2)&0x33333333UL) | ((x<< 2)&0xccccccccUL);
|
||||
return((x>> 1)&0x55555555UL) | ((x<< 1)&0xaaaaaaaaUL);
|
||||
}
|
||||
|
||||
static int sort32a(const void *a,const void *b){
|
||||
return ( **(ogg_uint32_t **)a>**(ogg_uint32_t **)b)-
|
||||
( **(ogg_uint32_t **)a<**(ogg_uint32_t **)b);
|
||||
}
|
||||
|
||||
/* decode codebook arrangement is more heavily optimized than encode */
|
||||
int vorbis_book_init_decode(codebook *c,const static_codebook *s){
|
||||
int i,j,n=0,tabn;
|
||||
int *sortindex;
|
||||
memset(c,0,sizeof(*c));
|
||||
|
||||
/* count actually used entries */
|
||||
for(i=0;i<s->entries;i++)
|
||||
if(s->lengthlist[i]>0)
|
||||
n++;
|
||||
|
||||
c->entries=s->entries;
|
||||
c->used_entries=n;
|
||||
c->dim=s->dim;
|
||||
|
||||
if(n>0){
|
||||
|
||||
/* two different remappings go on here.
|
||||
|
||||
First, we collapse the likely sparse codebook down only to
|
||||
actually represented values/words. This collapsing needs to be
|
||||
indexed as map-valueless books are used to encode original entry
|
||||
positions as integers.
|
||||
|
||||
Second, we reorder all vectors, including the entry index above,
|
||||
by sorted bitreversed codeword to allow treeless decode. */
|
||||
|
||||
/* perform sort */
|
||||
ogg_uint32_t *codes=_make_words(s->lengthlist,s->entries,c->used_entries);
|
||||
ogg_uint32_t **codep=alloca(sizeof(*codep)*n);
|
||||
|
||||
if(codes==NULL)goto err_out;
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
codes[i]=bitreverse(codes[i]);
|
||||
codep[i]=codes+i;
|
||||
}
|
||||
|
||||
qsort(codep,n,sizeof(*codep),sort32a);
|
||||
|
||||
sortindex=alloca(n*sizeof(*sortindex));
|
||||
c->codelist=_ogg_malloc(n*sizeof(*c->codelist));
|
||||
/* the index is a reverse index */
|
||||
for(i=0;i<n;i++){
|
||||
int position=codep[i]-codes;
|
||||
sortindex[position]=i;
|
||||
}
|
||||
|
||||
for(i=0;i<n;i++)
|
||||
c->codelist[sortindex[i]]=codes[i];
|
||||
_ogg_free(codes);
|
||||
|
||||
|
||||
c->valuelist=_book_unquantize(s,n,sortindex);
|
||||
c->dec_index=_ogg_malloc(n*sizeof(*c->dec_index));
|
||||
|
||||
for(n=0,i=0;i<s->entries;i++)
|
||||
if(s->lengthlist[i]>0)
|
||||
c->dec_index[sortindex[n++]]=i;
|
||||
|
||||
c->dec_codelengths=_ogg_malloc(n*sizeof(*c->dec_codelengths));
|
||||
for(n=0,i=0;i<s->entries;i++)
|
||||
if(s->lengthlist[i]>0)
|
||||
c->dec_codelengths[sortindex[n++]]=s->lengthlist[i];
|
||||
|
||||
c->dec_firsttablen=_ilog(c->used_entries)-4; /* this is magic */
|
||||
if(c->dec_firsttablen<5)c->dec_firsttablen=5;
|
||||
if(c->dec_firsttablen>8)c->dec_firsttablen=8;
|
||||
|
||||
tabn=1<<c->dec_firsttablen;
|
||||
c->dec_firsttable=_ogg_calloc(tabn,sizeof(*c->dec_firsttable));
|
||||
c->dec_maxlength=0;
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
if(c->dec_maxlength<c->dec_codelengths[i])
|
||||
c->dec_maxlength=c->dec_codelengths[i];
|
||||
if(c->dec_codelengths[i]<=c->dec_firsttablen){
|
||||
ogg_uint32_t orig=bitreverse(c->codelist[i]);
|
||||
for(j=0;j<(1<<(c->dec_firsttablen-c->dec_codelengths[i]));j++)
|
||||
c->dec_firsttable[orig|(j<<c->dec_codelengths[i])]=i+1;
|
||||
}
|
||||
}
|
||||
|
||||
/* now fill in 'unused' entries in the firsttable with hi/lo search
|
||||
hints for the non-direct-hits */
|
||||
{
|
||||
ogg_uint32_t mask=0xfffffffeUL<<(31-c->dec_firsttablen);
|
||||
long lo=0,hi=0;
|
||||
|
||||
for(i=0;i<tabn;i++){
|
||||
ogg_uint32_t word=i<<(32-c->dec_firsttablen);
|
||||
if(c->dec_firsttable[bitreverse(word)]==0){
|
||||
while((lo+1)<n && c->codelist[lo+1]<=word)lo++;
|
||||
while( hi<n && word>=(c->codelist[hi]&mask))hi++;
|
||||
|
||||
/* we only actually have 15 bits per hint to play with here.
|
||||
In order to overflow gracefully (nothing breaks, efficiency
|
||||
just drops), encode as the difference from the extremes. */
|
||||
{
|
||||
unsigned long loval=lo;
|
||||
unsigned long hival=n-hi;
|
||||
|
||||
if(loval>0x7fff)loval=0x7fff;
|
||||
if(hival>0x7fff)hival=0x7fff;
|
||||
c->dec_firsttable[bitreverse(word)]=
|
||||
0x80000000UL | (loval<<15) | hival;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_book_clear(c);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
static float _dist(int el,float *ref, float *b,int step){
|
||||
int i;
|
||||
float acc=0.f;
|
||||
for(i=0;i<el;i++){
|
||||
float val=(ref[i]-b[i*step]);
|
||||
acc+=val*val;
|
||||
}
|
||||
return(acc);
|
||||
}
|
||||
|
||||
int _best(codebook *book, float *a, int step){
|
||||
encode_aux_threshmatch *tt=book->c->thresh_tree;
|
||||
|
||||
#if 0
|
||||
encode_aux_nearestmatch *nt=book->c->nearest_tree;
|
||||
encode_aux_pigeonhole *pt=book->c->pigeon_tree;
|
||||
#endif
|
||||
int dim=book->dim;
|
||||
int k,o;
|
||||
/*int savebest=-1;
|
||||
float saverr;*/
|
||||
|
||||
/* do we have a threshhold encode hint? */
|
||||
if(tt){
|
||||
int index=0,i;
|
||||
/* find the quant val of each scalar */
|
||||
for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
|
||||
|
||||
i=tt->threshvals>>1;
|
||||
if(a[o]<tt->quantthresh[i]){
|
||||
|
||||
for(;i>0;i--)
|
||||
if(a[o]>=tt->quantthresh[i-1])
|
||||
break;
|
||||
|
||||
}else{
|
||||
|
||||
for(i++;i<tt->threshvals-1;i++)
|
||||
if(a[o]<tt->quantthresh[i])break;
|
||||
|
||||
}
|
||||
|
||||
index=(index*tt->quantvals)+tt->quantmap[i];
|
||||
}
|
||||
/* regular lattices are easy :-) */
|
||||
if(book->c->lengthlist[index]>0) /* is this unused? If so, we'll
|
||||
use a decision tree after all
|
||||
and fall through*/
|
||||
return(index);
|
||||
}
|
||||
|
||||
#if 0
|
||||
/* do we have a pigeonhole encode hint? */
|
||||
if(pt){
|
||||
const static_codebook *c=book->c;
|
||||
int i,besti=-1;
|
||||
float best=0.f;
|
||||
int entry=0;
|
||||
|
||||
/* dealing with sequentialness is a pain in the ass */
|
||||
if(c->q_sequencep){
|
||||
int pv;
|
||||
long mul=1;
|
||||
float qlast=0;
|
||||
for(k=0,o=0;k<dim;k++,o+=step){
|
||||
pv=(int)((a[o]-qlast-pt->min)/pt->del);
|
||||
if(pv<0 || pv>=pt->mapentries)break;
|
||||
entry+=pt->pigeonmap[pv]*mul;
|
||||
mul*=pt->quantvals;
|
||||
qlast+=pv*pt->del+pt->min;
|
||||
}
|
||||
}else{
|
||||
for(k=0,o=step*(dim-1);k<dim;k++,o-=step){
|
||||
int pv=(int)((a[o]-pt->min)/pt->del);
|
||||
if(pv<0 || pv>=pt->mapentries)break;
|
||||
entry=entry*pt->quantvals+pt->pigeonmap[pv];
|
||||
}
|
||||
}
|
||||
|
||||
/* must be within the pigeonholable range; if we quant outside (or
|
||||
in an entry that we define no list for), brute force it */
|
||||
if(k==dim && pt->fitlength[entry]){
|
||||
/* search the abbreviated list */
|
||||
long *list=pt->fitlist+pt->fitmap[entry];
|
||||
for(i=0;i<pt->fitlength[entry];i++){
|
||||
float this=_dist(dim,book->valuelist+list[i]*dim,a,step);
|
||||
if(besti==-1 || this<best){
|
||||
best=this;
|
||||
besti=list[i];
|
||||
}
|
||||
}
|
||||
|
||||
return(besti);
|
||||
}
|
||||
}
|
||||
|
||||
if(nt){
|
||||
/* optimized using the decision tree */
|
||||
while(1){
|
||||
float c=0.f;
|
||||
float *p=book->valuelist+nt->p[ptr];
|
||||
float *q=book->valuelist+nt->q[ptr];
|
||||
|
||||
for(k=0,o=0;k<dim;k++,o+=step)
|
||||
c+=(p[k]-q[k])*(a[o]-(p[k]+q[k])*.5);
|
||||
|
||||
if(c>0.f) /* in A */
|
||||
ptr= -nt->ptr0[ptr];
|
||||
else /* in B */
|
||||
ptr= -nt->ptr1[ptr];
|
||||
if(ptr<=0)break;
|
||||
}
|
||||
return(-ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* brute force it! */
|
||||
{
|
||||
const static_codebook *c=book->c;
|
||||
int i,besti=-1;
|
||||
float best=0.f;
|
||||
float *e=book->valuelist;
|
||||
for(i=0;i<book->entries;i++){
|
||||
if(c->lengthlist[i]>0){
|
||||
float this=_dist(dim,e,a,step);
|
||||
if(besti==-1 || this<best){
|
||||
best=this;
|
||||
besti=i;
|
||||
}
|
||||
}
|
||||
e+=dim;
|
||||
}
|
||||
|
||||
/*if(savebest!=-1 && savebest!=besti){
|
||||
fprintf(stderr,"brute force/pigeonhole disagreement:\n"
|
||||
"original:");
|
||||
for(i=0;i<dim*step;i+=step)fprintf(stderr,"%g,",a[i]);
|
||||
fprintf(stderr,"\n"
|
||||
"pigeonhole (entry %d, err %g):",savebest,saverr);
|
||||
for(i=0;i<dim;i++)fprintf(stderr,"%g,",
|
||||
(book->valuelist+savebest*dim)[i]);
|
||||
fprintf(stderr,"\n"
|
||||
"bruteforce (entry %d, err %g):",besti,best);
|
||||
for(i=0;i<dim;i++)fprintf(stderr,"%g,",
|
||||
(book->valuelist+besti*dim)[i]);
|
||||
fprintf(stderr,"\n");
|
||||
}*/
|
||||
return(besti);
|
||||
}
|
||||
}
|
||||
|
||||
long vorbis_book_codeword(codebook *book,int entry){
|
||||
if(book->c) /* only use with encode; decode optimizations are
|
||||
allowed to break this */
|
||||
return book->codelist[entry];
|
||||
return -1;
|
||||
}
|
||||
|
||||
long vorbis_book_codelen(codebook *book,int entry){
|
||||
if(book->c) /* only use with encode; decode optimizations are
|
||||
allowed to break this */
|
||||
return book->c->lengthlist[entry];
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifdef _V_SELFTEST
|
||||
|
||||
/* Unit tests of the dequantizer; this stuff will be OK
|
||||
cross-platform, I simply want to be sure that special mapping cases
|
||||
actually work properly; a bug could go unnoticed for a while */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* cases:
|
||||
|
||||
no mapping
|
||||
full, explicit mapping
|
||||
algorithmic mapping
|
||||
|
||||
nonsequential
|
||||
sequential
|
||||
*/
|
||||
|
||||
static long full_quantlist1[]={0,1,2,3, 4,5,6,7, 8,3,6,1};
|
||||
static long partial_quantlist1[]={0,7,2};
|
||||
|
||||
/* no mapping */
|
||||
static_codebook test1={
|
||||
4,16,
|
||||
NULL,
|
||||
0,
|
||||
0,0,0,0,
|
||||
NULL,
|
||||
NULL,NULL
|
||||
};
|
||||
static float *test1_result=NULL;
|
||||
|
||||
/* linear, full mapping, nonsequential */
|
||||
static_codebook test2={
|
||||
4,3,
|
||||
NULL,
|
||||
2,
|
||||
-533200896,1611661312,4,0,
|
||||
full_quantlist1,
|
||||
NULL,NULL
|
||||
};
|
||||
static float test2_result[]={-3,-2,-1,0, 1,2,3,4, 5,0,3,-2};
|
||||
|
||||
/* linear, full mapping, sequential */
|
||||
static_codebook test3={
|
||||
4,3,
|
||||
NULL,
|
||||
2,
|
||||
-533200896,1611661312,4,1,
|
||||
full_quantlist1,
|
||||
NULL,NULL
|
||||
};
|
||||
static float test3_result[]={-3,-5,-6,-6, 1,3,6,10, 5,5,8,6};
|
||||
|
||||
/* linear, algorithmic mapping, nonsequential */
|
||||
static_codebook test4={
|
||||
3,27,
|
||||
NULL,
|
||||
1,
|
||||
-533200896,1611661312,4,0,
|
||||
partial_quantlist1,
|
||||
NULL,NULL
|
||||
};
|
||||
static float test4_result[]={-3,-3,-3, 4,-3,-3, -1,-3,-3,
|
||||
-3, 4,-3, 4, 4,-3, -1, 4,-3,
|
||||
-3,-1,-3, 4,-1,-3, -1,-1,-3,
|
||||
-3,-3, 4, 4,-3, 4, -1,-3, 4,
|
||||
-3, 4, 4, 4, 4, 4, -1, 4, 4,
|
||||
-3,-1, 4, 4,-1, 4, -1,-1, 4,
|
||||
-3,-3,-1, 4,-3,-1, -1,-3,-1,
|
||||
-3, 4,-1, 4, 4,-1, -1, 4,-1,
|
||||
-3,-1,-1, 4,-1,-1, -1,-1,-1};
|
||||
|
||||
/* linear, algorithmic mapping, sequential */
|
||||
static_codebook test5={
|
||||
3,27,
|
||||
NULL,
|
||||
1,
|
||||
-533200896,1611661312,4,1,
|
||||
partial_quantlist1,
|
||||
NULL,NULL
|
||||
};
|
||||
static float test5_result[]={-3,-6,-9, 4, 1,-2, -1,-4,-7,
|
||||
-3, 1,-2, 4, 8, 5, -1, 3, 0,
|
||||
-3,-4,-7, 4, 3, 0, -1,-2,-5,
|
||||
-3,-6,-2, 4, 1, 5, -1,-4, 0,
|
||||
-3, 1, 5, 4, 8,12, -1, 3, 7,
|
||||
-3,-4, 0, 4, 3, 7, -1,-2, 2,
|
||||
-3,-6,-7, 4, 1, 0, -1,-4,-5,
|
||||
-3, 1, 0, 4, 8, 7, -1, 3, 2,
|
||||
-3,-4,-5, 4, 3, 2, -1,-2,-3};
|
||||
|
||||
void run_test(static_codebook *b,float *comp){
|
||||
float *out=_book_unquantize(b,b->entries,NULL);
|
||||
int i;
|
||||
|
||||
if(comp){
|
||||
if(!out){
|
||||
fprintf(stderr,"_book_unquantize incorrectly returned NULL\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i=0;i<b->entries*b->dim;i++)
|
||||
if(fabs(out[i]-comp[i])>.0001){
|
||||
fprintf(stderr,"disagreement in unquantized and reference data:\n"
|
||||
"position %d, %g != %g\n",i,out[i],comp[i]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}else{
|
||||
if(out){
|
||||
fprintf(stderr,"_book_unquantize returned a value array: \n"
|
||||
" correct result should have been NULL\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(){
|
||||
/* run the nine dequant tests, and compare to the hand-rolled results */
|
||||
fprintf(stderr,"Dequant test 1... ");
|
||||
run_test(&test1,test1_result);
|
||||
fprintf(stderr,"OK\nDequant test 2... ");
|
||||
run_test(&test2,test2_result);
|
||||
fprintf(stderr,"OK\nDequant test 3... ");
|
||||
run_test(&test3,test3_result);
|
||||
fprintf(stderr,"OK\nDequant test 4... ");
|
||||
run_test(&test4,test4_result);
|
||||
fprintf(stderr,"OK\nDequant test 5... ");
|
||||
run_test(&test5,test5_result);
|
||||
fprintf(stderr,"OK\n\n");
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#endif
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,170 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: single-block PCM synthesis
|
||||
last mod: $Id: synthesis.c 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include "vorbis/codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
|
||||
int vorbis_synthesis(vorbis_block *vb,ogg_packet *op){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=vd->backend_state;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
oggpack_buffer *opb=&vb->opb;
|
||||
int type,mode,i;
|
||||
|
||||
/* first things first. Make sure decode is ready */
|
||||
_vorbis_block_ripcord(vb);
|
||||
oggpack_readinit(opb,op->packet,op->bytes);
|
||||
|
||||
/* Check the packet type */
|
||||
if(oggpack_read(opb,1)!=0){
|
||||
/* Oops. This is not an audio data packet */
|
||||
return(OV_ENOTAUDIO);
|
||||
}
|
||||
|
||||
/* read our mode and pre/post windowsize */
|
||||
mode=oggpack_read(opb,b->modebits);
|
||||
if(mode==-1)return(OV_EBADPACKET);
|
||||
|
||||
vb->mode=mode;
|
||||
vb->W=ci->mode_param[mode]->blockflag;
|
||||
if(vb->W){
|
||||
|
||||
/* this doesn;t get mapped through mode selection as it's used
|
||||
only for window selection */
|
||||
vb->lW=oggpack_read(opb,1);
|
||||
vb->nW=oggpack_read(opb,1);
|
||||
if(vb->nW==-1) return(OV_EBADPACKET);
|
||||
}else{
|
||||
vb->lW=0;
|
||||
vb->nW=0;
|
||||
}
|
||||
|
||||
/* more setup */
|
||||
vb->granulepos=op->granulepos;
|
||||
vb->sequence=op->packetno;
|
||||
vb->eofflag=op->e_o_s;
|
||||
|
||||
/* alloc pcm passback storage */
|
||||
vb->pcmend=ci->blocksizes[vb->W];
|
||||
vb->pcm=_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
|
||||
for(i=0;i<vi->channels;i++)
|
||||
vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
|
||||
|
||||
/* unpack_header enforces range checking */
|
||||
type=ci->map_type[ci->mode_param[mode]->mapping];
|
||||
|
||||
return(_mapping_P[type]->inverse(vb,ci->map_param[ci->mode_param[mode]->
|
||||
mapping]));
|
||||
}
|
||||
|
||||
/* used to track pcm position without actually performing decode.
|
||||
Useful for sequential 'fast forward' */
|
||||
int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=vd->backend_state;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
oggpack_buffer *opb=&vb->opb;
|
||||
int mode;
|
||||
|
||||
/* first things first. Make sure decode is ready */
|
||||
_vorbis_block_ripcord(vb);
|
||||
oggpack_readinit(opb,op->packet,op->bytes);
|
||||
|
||||
/* Check the packet type */
|
||||
if(oggpack_read(opb,1)!=0){
|
||||
/* Oops. This is not an audio data packet */
|
||||
return(OV_ENOTAUDIO);
|
||||
}
|
||||
|
||||
/* read our mode and pre/post windowsize */
|
||||
mode=oggpack_read(opb,b->modebits);
|
||||
if(mode==-1)return(OV_EBADPACKET);
|
||||
|
||||
vb->mode=mode;
|
||||
vb->W=ci->mode_param[mode]->blockflag;
|
||||
if(vb->W){
|
||||
vb->lW=oggpack_read(opb,1);
|
||||
vb->nW=oggpack_read(opb,1);
|
||||
if(vb->nW==-1) return(OV_EBADPACKET);
|
||||
}else{
|
||||
vb->lW=0;
|
||||
vb->nW=0;
|
||||
}
|
||||
|
||||
/* more setup */
|
||||
vb->granulepos=op->granulepos;
|
||||
vb->sequence=op->packetno;
|
||||
vb->eofflag=op->e_o_s;
|
||||
|
||||
/* no pcm */
|
||||
vb->pcmend=0;
|
||||
vb->pcm=NULL;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op){
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
oggpack_buffer opb;
|
||||
int mode;
|
||||
|
||||
oggpack_readinit(&opb,op->packet,op->bytes);
|
||||
|
||||
/* Check the packet type */
|
||||
if(oggpack_read(&opb,1)!=0){
|
||||
/* Oops. This is not an audio data packet */
|
||||
return(OV_ENOTAUDIO);
|
||||
}
|
||||
|
||||
{
|
||||
int modebits=0;
|
||||
int v=ci->modes;
|
||||
while(v>1){
|
||||
modebits++;
|
||||
v>>=1;
|
||||
}
|
||||
|
||||
/* read our mode and pre/post windowsize */
|
||||
mode=oggpack_read(&opb,modebits);
|
||||
}
|
||||
if(mode==-1)return(OV_EBADPACKET);
|
||||
return(ci->blocksizes[ci->mode_param[mode]->blockflag]);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_halfrate(vorbis_info *vi,int flag){
|
||||
/* set / clear half-sample-rate mode */
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
|
||||
/* right now, our MDCT can't handle < 64 sample windows. */
|
||||
if(ci->blocksizes[0]<=64 && flag)return -1;
|
||||
ci->halfrate_flag=(flag?1:0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vorbis_synthesis_halfrate_p(vorbis_info *vi){
|
||||
codec_setup_info *ci=vi->codec_setup;
|
||||
return ci->halfrate_flag;
|
||||
}
|
||||
|
||||
|
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -0,0 +1,26 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: window functions
|
||||
last mod: $Id: window.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_WINDOW_
|
||||
#define _V_WINDOW_
|
||||
|
||||
extern float *_vorbis_window_get(int n);
|
||||
extern void _vorbis_apply_window(float *d,int *winno,long *blocksizes,
|
||||
int lW,int W,int nW);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
Open project list for further development:
|
||||
|
||||
libvorbis:
|
||||
|
||||
Meaningful error code returns
|
||||
|
||||
still some padding at EOS
|
||||
|
||||
Option for brute-forcing vq search on maptype 2 (helps on undertrained
|
||||
sets).
|
||||
|
||||
encoder switch interface for binary compat through changes; ioctl()-like?
|
||||
|
||||
API changes:
|
||||
break up some of the more monolithic calls (eg, allow access
|
||||
to MDCT domain data, additional low level framing capability)
|
||||
convenience calls for text comments
|
||||
|
||||
other:
|
||||
|
||||
command line suite
|
||||
'crashme'
|
|
@ -0,0 +1,48 @@
|
|||
# Usage: cp $1/update.sh <vorbis_src_directory>
|
||||
#
|
||||
# Copies the needed files from a directory containing the original
|
||||
# libvorbis source that we need for the Mozilla HTML5 media support.
|
||||
cp $1/lib/envelope.h ./lib/envelope.h
|
||||
cp $1/lib/lpc.h ./lib/lpc.h
|
||||
cp $1/lib/highlevel.h ./lib/highlevel.h
|
||||
cp $1/lib/floor0.c ./lib/vorbis_floor0.c
|
||||
cp $1/lib/lookup_data.h ./lib/lookup_data.h
|
||||
cp $1/lib/psy.c ./lib/vorbis_psy.c
|
||||
cp $1/lib/window.c ./lib/vorbis_window.c
|
||||
cp $1/lib/info.c ./lib/vorbis_info.c
|
||||
cp $1/lib/res0.c ./lib/vorbis_res0.c
|
||||
cp $1/lib/lookup.h ./lib/lookup.h
|
||||
cp $1/lib/lookup.c ./lib/vorbis_lookup.c
|
||||
sed s/lookup\.c/vorbis_lookup\.c/g $1/lib/lsp.c >./lib/vorbis_lsp.c
|
||||
cp $1/lib/codebook.h ./lib/codebook.h
|
||||
cp $1/lib/registry.c ./lib/vorbis_registry.c
|
||||
cp $1/lib/smallft.h ./lib/smallft.h
|
||||
cp $1/lib/synthesis.c ./lib/vorbis_synthesis.c
|
||||
cp $1/lib/masking.h ./lib/masking.h
|
||||
cp $1/lib/window.h ./lib/window.h
|
||||
cp $1/lib/scales.h ./lib/scales.h
|
||||
cp $1/lib/lsp.h ./lib/lsp.h
|
||||
cp $1/lib/analysis.c ./lib/vorbis_analysis.c
|
||||
cp $1/lib/misc.h ./lib/misc.h
|
||||
cp $1/lib/floor1.c ./lib/vorbis_floor1.c
|
||||
cp $1/lib/lpc.c ./lib/vorbis_lpc.c
|
||||
cp $1/lib/backends.h ./lib/backends.h
|
||||
cp $1/lib/sharedbook.c ./lib/vorbis_sharedbook.c
|
||||
cp $1/lib/mapping0.c ./lib/vorbis_mapping0.c
|
||||
cp $1/lib/smallft.c ./lib/vorbis_smallft.c
|
||||
cp $1/lib/psy.h ./lib/psy.h
|
||||
cp $1/lib/bitrate.h ./lib/bitrate.h
|
||||
cp $1/lib/envelope.c ./lib/vorbis_envelope.c
|
||||
cp $1/lib/os.h ./lib/os.h
|
||||
cp $1/lib/mdct.c ./lib/vorbis_mdct.c
|
||||
cp $1/lib/codec_internal.h ./lib/codec_internal.h
|
||||
cp $1/lib/mdct.h ./lib/mdct.h
|
||||
cp $1/lib/registry.h ./lib/registry.h
|
||||
cp $1/lib/codebook.c ./lib/vorbis_codebook.c
|
||||
cp $1/lib/bitrate.c ./lib/vorbis_bitrate.c
|
||||
cp $1/lib/block.c ./lib/vorbis_block.c
|
||||
cp $1/include/vorbis/codec.h ./include/vorbis/codec.h
|
||||
cp $1/todo.txt ./todo.txt
|
||||
cp $1/COPYING ./COPYING
|
||||
cp $1/README ./README
|
||||
cp $1/AUTHORS ./AUTHORS
|
Загрузка…
Ссылка в новой задаче