import esp audio lib

This commit is contained in:
2021-08-27 16:42:43 +02:00
parent 489174fdc8
commit 3d437de0e6
567 changed files with 267532 additions and 38 deletions

View File

@@ -0,0 +1,6 @@
Jean-Marc Valin (jmvalin@jmvalin.ca)
Koen Vos (koenvos74@gmail.com)
Timothy Terriberry (tterribe@xiph.org)
Karsten Vandborg Sorensen (karsten.vandborg.sorensen@skype.net)
Soren Skak Jensen (ssjensen@gn.com)
Gregory Maxwell (greg@xiph.org)

View File

@@ -0,0 +1,44 @@
Copyright 2001-2011 Xiph.Org, Skype Limited, Octasic,
Jean-Marc Valin, Timothy B. Terriberry,
CSIRO, Gregory Maxwell, Mark Borgerding,
Erik de Castro Lopo
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER
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.
Opus is subject to the royalty-free patent licenses which are
specified at:
Xiph.Org Foundation:
https://datatracker.ietf.org/ipr/1524/
Microsoft Corporation:
https://datatracker.ietf.org/ipr/1914/
Broadcom Corporation:
https://datatracker.ietf.org/ipr/1526/

View File

@@ -0,0 +1,368 @@
Installation Instructions
*************************
Copyright (C) 1994-1996, 1999-2002, 2004-2016 Free Software
Foundation, Inc.
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
Basic Installation
==================
Briefly, the shell command './configure && make && make install'
should configure, build, and install this package. The following
more-detailed instructions are generic; see the 'README' file for
instructions specific to this package. Some packages provide this
'INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
The 'configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a 'Makefile' in each directory of the package.
It may also create one or more '.h' files containing system-dependent
definitions. Finally, it creates a shell script 'config.status' that
you can run in the future to recreate the current configuration, and a
file 'config.log' containing compiler output (useful mainly for
debugging 'configure').
It can also use an optional file (typically called 'config.cache' and
enabled with '--cache-file=config.cache' or simply '-C') that saves the
results of its tests to speed up reconfiguring. Caching is disabled by
default to prevent problems with accidental use of stale cache files.
If you need to do unusual things to compile the package, please try
to figure out how 'configure' could check whether to do them, and mail
diffs or instructions to the address given in the 'README' so they can
be considered for the next release. If you are using the cache, and at
some point 'config.cache' contains results you don't want to keep, you
may remove or edit it.
The file 'configure.ac' (or 'configure.in') is used to create
'configure' by a program called 'autoconf'. You need 'configure.ac' if
you want to change it or regenerate 'configure' using a newer version of
'autoconf'.
The simplest way to compile this package is:
1. 'cd' to the directory containing the package's source code and type
'./configure' to configure the package for your system.
Running 'configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type 'make' to compile the package.
3. Optionally, type 'make check' to run any self-tests that come with
the package, generally using the just-built uninstalled binaries.
4. Type 'make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the 'make install' phase executed with root
privileges.
5. Optionally, type 'make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior 'make install' required
root privileges, verifies that the installation completed
correctly.
6. You can remove the program binaries and object files from the
source code directory by typing 'make clean'. To also remove the
files that 'configure' created (so you can compile the package for
a different kind of computer), type 'make distclean'. There is
also a 'make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
7. Often, you can also type 'make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide 'make
distcheck', which can by used by developers to test that all other
targets like 'make install' and 'make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the 'configure' script does not know about. Run './configure --help'
for details on some of the pertinent environment variables.
You can give 'configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here is
an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU 'make'. 'cd' to the
directory where you want the object files and executables to go and run
the 'configure' script. 'configure' automatically checks for the source
code in the directory that 'configure' is in and in '..'. This is known
as a "VPATH" build.
With a non-GNU 'make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use 'make distclean' before
reconfiguring for another architecture.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple '-arch' options to the
compiler but only a single '-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the 'lipo' tool if you have problems.
Installation Names
==================
By default, 'make install' installs the package's commands under
'/usr/local/bin', include files under '/usr/local/include', etc. You
can specify an installation prefix other than '/usr/local' by giving
'configure' the option '--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option '--exec-prefix=PREFIX' to 'configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like '--bindir=DIR' to specify different values for particular
kinds of files. Run 'configure --help' for a list of the directories
you can set and what kinds of files go in them. In general, the default
for these options is expressed in terms of '${prefix}', so that
specifying just '--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to 'configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
'make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, 'make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
'${prefix}'. Any directories that were specified during 'configure',
but not in terms of '${prefix}', must each be overridden at install time
for the entire installation to be relocated. The approach of makefile
variable overrides for each directory variable is required by the GNU
Coding Standards, and ideally causes no recompilation. However, some
platforms have known limitations with the semantics of shared libraries
that end up requiring recompilation when using this method, particularly
noticeable in packages that use GNU Libtool.
The second method involves providing the 'DESTDIR' variable. For
example, 'make install DESTDIR=/alternate/directory' will prepend
'/alternate/directory' before all installation names. The approach of
'DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of '${prefix}'
at 'configure' time.
Optional Features
=================
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving 'configure' the
option '--program-prefix=PREFIX' or '--program-suffix=SUFFIX'.
Some packages pay attention to '--enable-FEATURE' options to
'configure', where FEATURE indicates an optional part of the package.
They may also pay attention to '--with-PACKAGE' options, where PACKAGE
is something like 'gnu-as' or 'x' (for the X Window System). The
'README' should mention any '--enable-' and '--with-' options that the
package recognizes.
For packages that use the X Window System, 'configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the 'configure' options '--x-includes=DIR' and
'--x-libraries=DIR' to specify their locations.
Some packages offer the ability to configure how verbose the
execution of 'make' will be. For these packages, running './configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with 'make V=1'; while running './configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with 'make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU CC
is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX 'make' updates targets which have the same time stamps as their
prerequisites, which makes it generally unusable when shipped generated
files such as 'configure' are involved. Use GNU 'make' instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its '<wchar.h>' header file. The option '-nodtk' can be used as a
workaround. If GNU CC is not installed, it is therefore recommended to
try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put '/usr/ucb' early in your 'PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in '/usr/bin'. So, if you need '/usr/ucb'
in your 'PATH', put it _after_ '/usr/bin'.
On Haiku, software installed for all users goes in '/boot/common',
not '/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features 'configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, 'configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
'--build=TYPE' option. TYPE can either be a short name for the system
type, such as 'sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
See the file 'config.sub' for the possible values of each field. If
'config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option '--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with '--host=TYPE'.
Sharing Defaults
================
If you want to set default values for 'configure' scripts to share,
you can create a site shell script called 'config.site' that gives
default values for variables like 'CC', 'cache_file', and 'prefix'.
'configure' looks for 'PREFIX/share/config.site' if it exists, then
'PREFIX/etc/config.site' if it exists. Or, you can set the
'CONFIG_SITE' environment variable to the location of the site script.
A warning: not all 'configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to 'configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the 'configure' command line, using 'VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified 'gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for 'CONFIG_SHELL' due to an
Autoconf limitation. Until the limitation is lifted, you can use this
workaround:
CONFIG_SHELL=/bin/bash ./configure CONFIG_SHELL=/bin/bash
'configure' Invocation
======================
'configure' recognizes the following options to control how it
operates.
'--help'
'-h'
Print a summary of all of the options to 'configure', and exit.
'--help=short'
'--help=recursive'
Print a summary of the options unique to this package's
'configure', and exit. The 'short' variant lists options used only
in the top level, while the 'recursive' variant lists options also
present in any nested packages.
'--version'
'-V'
Print the version of Autoconf used to generate the 'configure'
script, and exit.
'--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally 'config.cache'. FILE defaults to '/dev/null' to
disable caching.
'--config-cache'
'-C'
Alias for '--cache-file=config.cache'.
'--quiet'
'--silent'
'-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to '/dev/null' (any error
messages will still be shown).
'--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
'configure' can determine that directory automatically.
'--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names:: for
more details, including other options available for fine-tuning the
installation locations.
'--no-create'
'-n'
Run the configure checks, but stop before creating any output
files.
'configure' also accepts some other, not widely useful, options. Run
'configure --help' for more details.

View File

@@ -0,0 +1,161 @@
== Opus audio codec ==
Opus is a codec for interactive speech and audio transmission over the Internet.
Opus can handle a wide range of interactive audio applications, including
Voice over IP, videoconferencing, in-game chat, and even remote live music
performances. It can scale from low bit-rate narrowband speech to very high
quality stereo music.
Opus, when coupled with an appropriate container format, is also suitable
for non-realtime stored-file applications such as music distribution, game
soundtracks, portable music players, jukeboxes, and other applications that
have historically used high latency formats such as MP3, AAC, or Vorbis.
Opus is specified by IETF RFC 6716:
https://tools.ietf.org/html/rfc6716
The Opus format and this implementation of it are subject to the royalty-
free patent and copyright licenses specified in the file COPYING.
This package implements a shared library for encoding and decoding raw Opus
bitstreams. Raw Opus bitstreams should be used over RTP according to
https://tools.ietf.org/html/rfc7587
The package also includes a number of test tools used for testing the
correct operation of the library. The bitstreams read/written by these
tools should not be used for Opus file distribution: They include
additional debugging data and cannot support seeking.
Opus stored in files should use the Ogg encapsulation for Opus which is
described at:
https://tools.ietf.org/html/rfc7845
An opus-tools package is available which provides encoding and decoding of
Ogg encapsulated Opus files and includes a number of useful features.
Opus-tools can be found at:
https://git.xiph.org/?p=opus-tools.git
or on the main Opus website:
https://opus-codec.org/
== Compiling libopus ==
To build from a distribution tarball, you only need to do the following:
% ./configure
% make
To build from the git repository, the following steps are necessary:
0) Set up a development environment:
On an Ubuntu or Debian family Linux distribution:
% sudo apt-get install git autoconf automake libtool gcc make
On a Fedora/Redhat based Linux:
% sudo dnf install git autoconf automake libtool gcc make
Or for older Redhat/Centos Linux releases:
% sudo yum install git autoconf automake libtool gcc make
On Apple macOS, install Xcode and brew.sh, then in the Terminal enter:
% brew install autoconf automake libtool
1) Clone the repository:
% git clone https://git.xiph.org/opus.git
% cd opus
2) Compiling the source
% ./autogen.sh
% ./configure
% make
3) Install the codec libraries (optional)
% sudo make install
Once you have compiled the codec, there will be a opus_demo executable
in the top directory.
Usage: opus_demo [-e] <application> <sampling rate (Hz)> <channels (1/2)>
<bits per second> [options] <input> <output>
opus_demo -d <sampling rate (Hz)> <channels (1/2)> [options]
<input> <output>
mode: voip | audio | restricted-lowdelay
options:
-e : only runs the encoder (output the bit-stream)
-d : only runs the decoder (reads the bit-stream as input)
-cbr : enable constant bitrate; default: variable bitrate
-cvbr : enable constrained variable bitrate; default:
unconstrained
-bandwidth <NB|MB|WB|SWB|FB>
: audio bandwidth (from narrowband to fullband);
default: sampling rate
-framesize <2.5|5|10|20|40|60>
: frame size in ms; default: 20
-max_payload <bytes>
: maximum payload size in bytes, default: 1024
-complexity <comp>
: complexity, 0 (lowest) ... 10 (highest); default: 10
-inbandfec : enable SILK inband FEC
-forcemono : force mono encoding, even for stereo input
-dtx : enable SILK DTX
-loss <perc> : simulate packet loss, in percent (0-100); default: 0
input and output are little-endian signed 16-bit PCM files or opus
bitstreams with simple opus_demo proprietary framing.
== Testing ==
This package includes a collection of automated unit and system tests
which SHOULD be run after compiling the package especially the first
time it is run on a new platform.
To run the integrated tests:
% make check
There is also collection of standard test vectors which are not
included in this package for size reasons but can be obtained from:
https://opus-codec.org/docs/opus_testvectors-rfc8251.tar.gz
To run compare the code to these test vectors:
% curl -OL https://opus-codec.org/docs/opus_testvectors-rfc8251.tar.gz
% tar -zxf opus_testvectors-rfc8251.tar.gz
% ./tests/run_vectors.sh ./ opus_newvectors 48000
== Portability notes ==
This implementation uses floating-point by default but can be compiled to
use only fixed-point arithmetic by setting --enable-fixed-point (if using
autoconf) or by defining the FIXED_POINT macro (if building manually).
The fixed point implementation has somewhat lower audio quality and is
slower on platforms with fast FPUs, it is normally only used in embedded
environments.
The implementation can be compiled with either a C89 or a C99 compiler.
While it does not rely on any _undefined behavior_ as defined by C89 or
C99, it relies on common _implementation-defined behavior_ for two's
complement architectures:
o Right shifts of negative values are consistent with two's
complement arithmetic, so that a>>b is equivalent to
floor(a/(2^b)),
o For conversion to a signed integer of N bits, the value is reduced
modulo 2^N to be within range of the type,
o The result of integer division of a negative value is truncated
towards zero, and
o The compiler provides a 64-bit integer type (a C99 requirement
which is supported by most C89 compilers).

View File

@@ -0,0 +1,103 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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.
*/
#ifndef ANALYSIS_H
#define ANALYSIS_H
#include "celt/celt.h"
#include "opus_private.h"
#include "mlp.h"
#define NB_FRAMES 8
#define NB_TBANDS 18
#define ANALYSIS_BUF_SIZE 720 /* 30 ms at 24 kHz */
/* At that point we can stop counting frames because it no longer matters. */
#define ANALYSIS_COUNT_MAX 10000
#define DETECT_SIZE 100
/* Uncomment this to print the MLP features on stdout. */
/*#define MLP_TRAINING*/
typedef struct {
int arch;
int application;
opus_int32 Fs;
#define TONALITY_ANALYSIS_RESET_START angle
float angle[240];
float d_angle[240];
float d2_angle[240];
opus_val32 inmem[ANALYSIS_BUF_SIZE];
int mem_fill; /* number of usable samples in the buffer */
float prev_band_tonality[NB_TBANDS];
float prev_tonality;
int prev_bandwidth;
float E[NB_FRAMES][NB_TBANDS];
float logE[NB_FRAMES][NB_TBANDS];
float lowE[NB_TBANDS];
float highE[NB_TBANDS];
float meanE[NB_TBANDS+1];
float mem[32];
float cmean[8];
float std[9];
float Etracker;
float lowECount;
int E_count;
int count;
int analysis_offset;
int write_pos;
int read_pos;
int read_subframe;
float hp_ener_accum;
int initialized;
float rnn_state[MAX_NEURONS];
opus_val32 downmix_state[3];
AnalysisInfo info[DETECT_SIZE];
} TonalityAnalysisState;
/** Initialize a TonalityAnalysisState struct.
*
* This performs some possibly slow initialization steps which should
* not be repeated every analysis step. No allocated memory is retained
* by the state struct, so no cleanup call is required.
*/
void tonality_analysis_init(TonalityAnalysisState *analysis, opus_int32 Fs);
/** Reset a TonalityAnalysisState stuct.
*
* Call this when there's a discontinuity in the data.
*/
void tonality_analysis_reset(TonalityAnalysisState *analysis);
void tonality_get_info(TonalityAnalysisState *tonal, AnalysisInfo *info_out, int len);
void run_analysis(TonalityAnalysisState *analysis, const CELTMode *celt_mode, const void *analysis_pcm,
int analysis_frame_size, int frame_size, int c1, int c2, int C, opus_int32 Fs,
int lsb_depth, downmix_func downmix, AnalysisInfo *analysis_info);
#endif

View File

@@ -0,0 +1,182 @@
/*Copyright (c) 2003-2004, Mark Borgerding
All rights reserved.
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.
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 COPYRIGHT OWNER 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.*/
#ifndef KISS_FFT_GUTS_H
#define KISS_FFT_GUTS_H
#define MIN(a,b) ((a)<(b) ? (a):(b))
#define MAX(a,b) ((a)>(b) ? (a):(b))
/* kiss_fft.h
defines kiss_fft_scalar as either short or a float type
and defines
typedef struct { kiss_fft_scalar r; kiss_fft_scalar i; }kiss_fft_cpx; */
#include "kiss_fft.h"
/*
Explanation of macros dealing with complex math:
C_MUL(m,a,b) : m = a*b
C_FIXDIV( c , div ) : if a fixed point impl., c /= div. noop otherwise
C_SUB( res, a,b) : res = a - b
C_SUBFROM( res , a) : res -= a
C_ADDTO( res , a) : res += a
* */
#ifdef FIXED_POINT
#include "arch.h"
#define SAMP_MAX 2147483647
#define TWID_MAX 32767
#define TRIG_UPSCALE 1
#define SAMP_MIN -SAMP_MAX
# define S_MUL(a,b) MULT16_32_Q15(b, a)
# define C_MUL(m,a,b) \
do{ (m).r = SUB32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
(m).i = ADD32_ovflw(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
# define C_MULC(m,a,b) \
do{ (m).r = ADD32_ovflw(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
(m).i = SUB32_ovflw(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
# define C_MULBYSCALAR( c, s ) \
do{ (c).r = S_MUL( (c).r , s ) ;\
(c).i = S_MUL( (c).i , s ) ; }while(0)
# define DIVSCALAR(x,k) \
(x) = S_MUL( x, (TWID_MAX-((k)>>1))/(k)+1 )
# define C_FIXDIV(c,div) \
do { DIVSCALAR( (c).r , div); \
DIVSCALAR( (c).i , div); }while (0)
#define C_ADD( res, a,b)\
do {(res).r=ADD32_ovflw((a).r,(b).r); (res).i=ADD32_ovflw((a).i,(b).i); \
}while(0)
#define C_SUB( res, a,b)\
do {(res).r=SUB32_ovflw((a).r,(b).r); (res).i=SUB32_ovflw((a).i,(b).i); \
}while(0)
#define C_ADDTO( res , a)\
do {(res).r = ADD32_ovflw((res).r, (a).r); (res).i = ADD32_ovflw((res).i,(a).i);\
}while(0)
#define C_SUBFROM( res , a)\
do {(res).r = ADD32_ovflw((res).r,(a).r); (res).i = SUB32_ovflw((res).i,(a).i); \
}while(0)
#if defined(OPUS_ARM_INLINE_ASM)
#include "arm/kiss_fft_armv4.h"
#endif
#if defined(OPUS_ARM_INLINE_EDSP)
#include "arm/kiss_fft_armv5e.h"
#endif
#if defined(MIPSr1_ASM)
#include "mips/kiss_fft_mipsr1.h"
#endif
#else /* not FIXED_POINT*/
# define S_MUL(a,b) ( (a)*(b) )
#define C_MUL(m,a,b) \
do{ (m).r = (a).r*(b).r - (a).i*(b).i;\
(m).i = (a).r*(b).i + (a).i*(b).r; }while(0)
#define C_MULC(m,a,b) \
do{ (m).r = (a).r*(b).r + (a).i*(b).i;\
(m).i = (a).i*(b).r - (a).r*(b).i; }while(0)
#define C_MUL4(m,a,b) C_MUL(m,a,b)
# define C_FIXDIV(c,div) /* NOOP */
# define C_MULBYSCALAR( c, s ) \
do{ (c).r *= (s);\
(c).i *= (s); }while(0)
#endif
#ifndef CHECK_OVERFLOW_OP
# define CHECK_OVERFLOW_OP(a,op,b) /* noop */
#endif
#ifndef C_ADD
#define C_ADD( res, a,b)\
do { \
CHECK_OVERFLOW_OP((a).r,+,(b).r)\
CHECK_OVERFLOW_OP((a).i,+,(b).i)\
(res).r=(a).r+(b).r; (res).i=(a).i+(b).i; \
}while(0)
#define C_SUB( res, a,b)\
do { \
CHECK_OVERFLOW_OP((a).r,-,(b).r)\
CHECK_OVERFLOW_OP((a).i,-,(b).i)\
(res).r=(a).r-(b).r; (res).i=(a).i-(b).i; \
}while(0)
#define C_ADDTO( res , a)\
do { \
CHECK_OVERFLOW_OP((res).r,+,(a).r)\
CHECK_OVERFLOW_OP((res).i,+,(a).i)\
(res).r += (a).r; (res).i += (a).i;\
}while(0)
#define C_SUBFROM( res , a)\
do {\
CHECK_OVERFLOW_OP((res).r,-,(a).r)\
CHECK_OVERFLOW_OP((res).i,-,(a).i)\
(res).r -= (a).r; (res).i -= (a).i; \
}while(0)
#endif /* C_ADD defined */
#ifdef FIXED_POINT
/*# define KISS_FFT_COS(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * cos (phase))))
# define KISS_FFT_SIN(phase) TRIG_UPSCALE*floor(MIN(32767,MAX(-32767,.5+32768 * sin (phase))))*/
# define KISS_FFT_COS(phase) floor(.5+TWID_MAX*cos (phase))
# define KISS_FFT_SIN(phase) floor(.5+TWID_MAX*sin (phase))
# define HALF_OF(x) ((x)>>1)
#elif defined(USE_SIMD)
# define KISS_FFT_COS(phase) _mm_set1_ps( cos(phase) )
# define KISS_FFT_SIN(phase) _mm_set1_ps( sin(phase) )
# define HALF_OF(x) ((x)*_mm_set1_ps(.5f))
#else
# define KISS_FFT_COS(phase) (kiss_fft_scalar) cos(phase)
# define KISS_FFT_SIN(phase) (kiss_fft_scalar) sin(phase)
# define HALF_OF(x) ((x)*.5f)
#endif
#define kf_cexp(x,phase) \
do{ \
(x)->r = KISS_FFT_COS(phase);\
(x)->i = KISS_FFT_SIN(phase);\
}while(0)
#define kf_cexp2(x,phase) \
do{ \
(x)->r = TRIG_UPSCALE*celt_cos_norm((phase));\
(x)->i = TRIG_UPSCALE*celt_cos_norm((phase)-32768);\
}while(0)
#endif /* KISS_FFT_GUTS_H */

View File

@@ -0,0 +1,288 @@
/* Copyright (c) 2003-2008 Jean-Marc Valin
Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/**
@file arch.h
@brief Various architecture definitions for CELT
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef ARCH_H
#define ARCH_H
#include "../opus_types.h"
#include "../opus_defines.h"
# if !defined(__GNUC_PREREQ)
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
# define __GNUC_PREREQ(_maj,_min) \
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
# else
# define __GNUC_PREREQ(_maj,_min) 0
# endif
# endif
#if OPUS_GNUC_PREREQ(3, 0)
#define opus_likely(x) (__builtin_expect(!!(x), 1))
#define opus_unlikely(x) (__builtin_expect(!!(x), 0))
#else
#define opus_likely(x) (!!(x))
#define opus_unlikely(x) (!!(x))
#endif
#define CELT_SIG_SCALE 32768.f
#define CELT_FATAL(str) celt_fatal(str, __FILE__, __LINE__);
#if defined(ENABLE_ASSERTIONS) || defined(ENABLE_HARDENING)
#ifdef __GNUC__
__attribute__((noreturn))
#endif
void celt_fatal(const char *str, const char *file, int line);
#if defined(CELT_C) && !defined(OVERRIDE_celt_fatal)
#include <stdio.h>
#include <stdlib.h>
#ifdef __GNUC__
__attribute__((noreturn))
#endif
void celt_fatal(const char *str, const char *file, int line)
{
fprintf (stderr, "Fatal (internal) error in %s, line %d: %s\n", file, line, str);
abort();
}
#endif
#define celt_assert(cond) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond);}}
#define celt_assert2(cond, message) {if (!(cond)) {CELT_FATAL("assertion failed: " #cond "\n" message);}}
#define MUST_SUCCEED(call) celt_assert((call) == OPUS_OK)
#else
#define celt_assert(cond)
#define celt_assert2(cond, message)
#define MUST_SUCCEED(call) do {if((call) != OPUS_OK) {RESTORE_STACK; return OPUS_INTERNAL_ERROR;} } while (0)
#endif
#if defined(ENABLE_ASSERTIONS)
#define celt_sig_assert(cond) {if (!(cond)) {CELT_FATAL("signal assertion failed: " #cond);}}
#else
#define celt_sig_assert(cond)
#endif
#define IMUL32(a,b) ((a)*(b))
#define MIN16(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 16-bit value. */
#define MAX16(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 16-bit value. */
#define MIN32(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum 32-bit value. */
#define MAX32(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum 32-bit value. */
#define IMIN(a,b) ((a) < (b) ? (a) : (b)) /**< Minimum int value. */
#define IMAX(a,b) ((a) > (b) ? (a) : (b)) /**< Maximum int value. */
#define UADD32(a,b) ((a)+(b))
#define USUB32(a,b) ((a)-(b))
/* Set this if opus_int64 is a native type of the CPU. */
/* Assume that all LP64 architectures have fast 64-bit types; also x86_64
(which can be ILP32 for x32) and Win64 (which is LLP64). */
#if defined(__x86_64__) || defined(__LP64__) || defined(_WIN64)
#define OPUS_FAST_INT64 1
#else
#define OPUS_FAST_INT64 0
#endif
#define PRINT_MIPS(file)
#ifdef FIXED_POINT
typedef opus_int16 opus_val16;
typedef opus_int32 opus_val32;
typedef opus_int64 opus_val64;
typedef opus_val32 celt_sig;
typedef opus_val16 celt_norm;
typedef opus_val32 celt_ener;
#define celt_isnan(x) 0
#define Q15ONE 32767
#define SIG_SHIFT 12
/* Safe saturation value for 32-bit signals. Should be less than
2^31*(1-0.85) to avoid blowing up on DC at deemphasis.*/
#define SIG_SAT (300000000)
#define NORM_SCALING 16384
#define DB_SHIFT 10
#define EPSILON 1
#define VERY_SMALL 0
#define VERY_LARGE16 ((opus_val16)32767)
#define Q15_ONE ((opus_val16)32767)
#define SCALEIN(a) (a)
#define SCALEOUT(a) (a)
#define ABS16(x) ((x) < 0 ? (-(x)) : (x))
#define ABS32(x) ((x) < 0 ? (-(x)) : (x))
static OPUS_INLINE opus_int16 SAT16(opus_int32 x) {
return x > 32767 ? 32767 : x < -32768 ? -32768 : (opus_int16)x;
}
#ifdef FIXED_DEBUG
#include "fixed_debug.h"
#else
#include "fixed_generic.h"
#ifdef OPUS_ARM_PRESUME_AARCH64_NEON_INTR
#include "arm/fixed_arm64.h"
#elif defined (OPUS_ARM_INLINE_EDSP)
#include "arm/fixed_armv5e.h"
#elif defined (OPUS_ARM_INLINE_ASM)
#include "arm/fixed_armv4.h"
#elif defined (BFIN_ASM)
#include "fixed_bfin.h"
#elif defined (TI_C5X_ASM)
#include "fixed_c5x.h"
#elif defined (TI_C6X_ASM)
#include "fixed_c6x.h"
#endif
#endif
#else /* FIXED_POINT */
typedef float opus_val16;
typedef float opus_val32;
typedef float opus_val64;
typedef float celt_sig;
typedef float celt_norm;
typedef float celt_ener;
#ifdef FLOAT_APPROX
/* This code should reliably detect NaN/inf even when -ffast-math is used.
Assumes IEEE 754 format. */
static OPUS_INLINE int celt_isnan(float x)
{
union {float f; opus_uint32 i;} in;
in.f = x;
return ((in.i>>23)&0xFF)==0xFF && (in.i&0x007FFFFF)!=0;
}
#else
#ifdef __FAST_MATH__
#error Cannot build libopus with -ffast-math unless FLOAT_APPROX is defined. This could result in crashes on extreme (e.g. NaN) input
#endif
#define celt_isnan(x) ((x)!=(x))
#endif
#define Q15ONE 1.0f
#define NORM_SCALING 1.f
#define EPSILON 1e-15f
#define VERY_SMALL 1e-30f
#define VERY_LARGE16 1e15f
#define Q15_ONE ((opus_val16)1.f)
/* This appears to be the same speed as C99's fabsf() but it's more portable. */
#define ABS16(x) ((float)fabs(x))
#define ABS32(x) ((float)fabs(x))
#define QCONST16(x,bits) (x)
#define QCONST32(x,bits) (x)
#define NEG16(x) (-(x))
#define NEG32(x) (-(x))
#define NEG32_ovflw(x) (-(x))
#define EXTRACT16(x) (x)
#define EXTEND32(x) (x)
#define SHR16(a,shift) (a)
#define SHL16(a,shift) (a)
#define SHR32(a,shift) (a)
#define SHL32(a,shift) (a)
#define PSHR32(a,shift) (a)
#define VSHR32(a,shift) (a)
#define PSHR(a,shift) (a)
#define SHR(a,shift) (a)
#define SHL(a,shift) (a)
#define SATURATE(x,a) (x)
#define SATURATE16(x) (x)
#define ROUND16(a,shift) (a)
#define SROUND16(a,shift) (a)
#define HALF16(x) (.5f*(x))
#define HALF32(x) (.5f*(x))
#define ADD16(a,b) ((a)+(b))
#define SUB16(a,b) ((a)-(b))
#define ADD32(a,b) ((a)+(b))
#define SUB32(a,b) ((a)-(b))
#define ADD32_ovflw(a,b) ((a)+(b))
#define SUB32_ovflw(a,b) ((a)-(b))
#define MULT16_16_16(a,b) ((a)*(b))
#define MULT16_16(a,b) ((opus_val32)(a)*(opus_val32)(b))
#define MAC16_16(c,a,b) ((c)+(opus_val32)(a)*(opus_val32)(b))
#define MULT16_32_Q15(a,b) ((a)*(b))
#define MULT16_32_Q16(a,b) ((a)*(b))
#define MULT32_32_Q31(a,b) ((a)*(b))
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
#define MAC16_32_Q16(c,a,b) ((c)+(a)*(b))
#define MULT16_16_Q11_32(a,b) ((a)*(b))
#define MULT16_16_Q11(a,b) ((a)*(b))
#define MULT16_16_Q13(a,b) ((a)*(b))
#define MULT16_16_Q14(a,b) ((a)*(b))
#define MULT16_16_Q15(a,b) ((a)*(b))
#define MULT16_16_P15(a,b) ((a)*(b))
#define MULT16_16_P13(a,b) ((a)*(b))
#define MULT16_16_P14(a,b) ((a)*(b))
#define MULT16_32_P16(a,b) ((a)*(b))
#define DIV32_16(a,b) (((opus_val32)(a))/(opus_val16)(b))
#define DIV32(a,b) (((opus_val32)(a))/(opus_val32)(b))
#define SCALEIN(a) ((a)*CELT_SIG_SCALE)
#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE))
#define SIG2WORD16(x) (x)
#endif /* !FIXED_POINT */
#ifndef GLOBAL_STACK_SIZE
#ifdef FIXED_POINT
#define GLOBAL_STACK_SIZE 120000
#else
#define GLOBAL_STACK_SIZE 120000
#endif
#endif
#endif /* ARCH_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,123 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008-2009 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef BANDS_H
#define BANDS_H
#include "arch.h"
#include "modes.h"
#include "entenc.h"
#include "entdec.h"
#include "rate.h"
opus_int16 bitexact_cos(opus_int16 x);
int bitexact_log2tan(int isin,int icos);
/** Compute the amplitude (sqrt energy) in each of the bands
* @param m Mode data
* @param X Spectrum
* @param bandE Square root of the energy for each band (returned)
*/
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bandE, int end, int C, int LM, int arch);
/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const opus_val16 *tonality, celt_ener *bandE);*/
/** Normalise each band of X such that the energy in each band is
equal to 1
* @param m Mode data
* @param X Spectrum (returned normalised)
* @param bandE Square root of the energy for each band
*/
void normalise_bands(const CELTMode *m, const celt_sig * OPUS_RESTRICT freq, celt_norm * OPUS_RESTRICT X, const celt_ener *bandE, int end, int C, int M);
/** Denormalise each band of X to restore full amplitude
* @param m Mode data
* @param X Spectrum (returned de-normalised)
* @param bandE Square root of the energy for each band
*/
void denormalise_bands(const CELTMode *m, const celt_norm * OPUS_RESTRICT X,
celt_sig * OPUS_RESTRICT freq, const opus_val16 *bandE, int start,
int end, int M, int downsample, int silence);
#define SPREAD_NONE (0)
#define SPREAD_LIGHT (1)
#define SPREAD_NORMAL (2)
#define SPREAD_AGGRESSIVE (3)
int spreading_decision(const CELTMode *m, const celt_norm *X, int *average,
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
int end, int C, int M, const int *spread_weight);
#ifdef MEASURE_NORM_MSE
void measure_norm_mse(const CELTMode *m, float *X, float *X0, float *bandE, float *bandE0, int M, int N, int C);
#endif
void haar1(celt_norm *X, int N0, int stride);
/** Quantisation/encoding of the residual spectrum
* @param encode flag that indicates whether we're encoding (1) or decoding (0)
* @param m Mode data
* @param start First band to process
* @param end Last band to process + 1
* @param X Residual (normalised)
* @param Y Residual (normalised) for second channel (or NULL for mono)
* @param collapse_masks Anti-collapse tracking mask
* @param bandE Square root of the energy for each band
* @param pulses Bit allocation (per band) for PVQ
* @param shortBlocks Zero for long blocks, non-zero for short blocks
* @param spread Amount of spreading to use
* @param dual_stereo Zero for MS stereo, non-zero for dual stereo
* @param intensity First band to use intensity stereo
* @param tf_res Time-frequency resolution change
* @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
* @param balance Number of unallocated bits
* @param en Entropy coder state
* @param LM log2() of the number of 2.5 subframes in the frame
* @param codedBands Last band to receive bits + 1
* @param seed Random generator seed
* @param arch Run-time architecture (see opus_select_arch())
*/
void quant_all_bands(int encode, const CELTMode *m, int start, int end,
celt_norm * X, celt_norm * Y, unsigned char *collapse_masks,
const celt_ener *bandE, int *pulses, int shortBlocks, int spread,
int dual_stereo, int intensity, int *tf_res, opus_int32 total_bits,
opus_int32 balance, ec_ctx *ec, int M, int codedBands, opus_uint32 *seed,
int complexity, int arch, int disable_inv);
void anti_collapse(const CELTMode *m, celt_norm *X_,
unsigned char *collapse_masks, int LM, int C, int size, int start,
int end, const opus_val16 *logE, const opus_val16 *prev1logE,
const opus_val16 *prev2logE, const int *pulses, opus_uint32 seed,
int arch);
opus_uint32 celt_lcg_rand(opus_uint32 seed);
int hysteresis_decision(opus_val16 val, const opus_val16 *thresholds, const opus_val16 *hysteresis, int N, int prev);
#endif /* BANDS_H */

View File

@@ -0,0 +1,316 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2010 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#define CELT_C
#include "os_support.h"
#include "mdct.h"
#include <math.h>
#include "celt.h"
#include "pitch.h"
#include "bands.h"
#include "modes.h"
#include "entcode.h"
#include "quant_bands.h"
#include "rate.h"
#include "stack_alloc.h"
#include "mathops.h"
#include "float_cast.h"
#include <stdarg.h>
#include "celt_lpc.h"
#include "vq.h"
#ifndef PACKAGE_VERSION
#define PACKAGE_VERSION "unknown"
#endif
#if defined(MIPSr1_ASM)
#include "mips/celt_mipsr1.h"
#endif
int resampling_factor(opus_int32 rate)
{
int ret;
switch (rate)
{
case 48000:
ret = 1;
break;
case 24000:
ret = 2;
break;
case 16000:
ret = 3;
break;
case 12000:
ret = 4;
break;
case 8000:
ret = 6;
break;
default:
#ifndef CUSTOM_MODES
celt_assert(0);
#endif
ret = 0;
break;
}
return ret;
}
#if !defined(OVERRIDE_COMB_FILTER_CONST) || defined(NON_STATIC_COMB_FILTER_CONST_C)
/* This version should be faster on ARM */
#ifdef OPUS_ARM_ASM
#ifndef NON_STATIC_COMB_FILTER_CONST_C
static
#endif
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12)
{
opus_val32 x0, x1, x2, x3, x4;
int i;
x4 = SHL32(x[-T-2], 1);
x3 = SHL32(x[-T-1], 1);
x2 = SHL32(x[-T], 1);
x1 = SHL32(x[-T+1], 1);
for (i=0;i<N-4;i+=5)
{
opus_val32 t;
x0=SHL32(x[i-T+2],1);
t = MAC16_32_Q16(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
t = SATURATE(t, SIG_SAT);
y[i] = t;
x4=SHL32(x[i-T+3],1);
t = MAC16_32_Q16(x[i+1], g10, x1);
t = MAC16_32_Q16(t, g11, ADD32(x0,x2));
t = MAC16_32_Q16(t, g12, ADD32(x4,x3));
t = SATURATE(t, SIG_SAT);
y[i+1] = t;
x3=SHL32(x[i-T+4],1);
t = MAC16_32_Q16(x[i+2], g10, x0);
t = MAC16_32_Q16(t, g11, ADD32(x4,x1));
t = MAC16_32_Q16(t, g12, ADD32(x3,x2));
t = SATURATE(t, SIG_SAT);
y[i+2] = t;
x2=SHL32(x[i-T+5],1);
t = MAC16_32_Q16(x[i+3], g10, x4);
t = MAC16_32_Q16(t, g11, ADD32(x3,x0));
t = MAC16_32_Q16(t, g12, ADD32(x2,x1));
t = SATURATE(t, SIG_SAT);
y[i+3] = t;
x1=SHL32(x[i-T+6],1);
t = MAC16_32_Q16(x[i+4], g10, x3);
t = MAC16_32_Q16(t, g11, ADD32(x2,x4));
t = MAC16_32_Q16(t, g12, ADD32(x1,x0));
t = SATURATE(t, SIG_SAT);
y[i+4] = t;
}
#ifdef CUSTOM_MODES
for (;i<N;i++)
{
opus_val32 t;
x0=SHL32(x[i-T+2],1);
t = MAC16_32_Q16(x[i], g10, x2);
t = MAC16_32_Q16(t, g11, ADD32(x1,x3));
t = MAC16_32_Q16(t, g12, ADD32(x0,x4));
t = SATURATE(t, SIG_SAT);
y[i] = t;
x4=x3;
x3=x2;
x2=x1;
x1=x0;
}
#endif
}
#else
#ifndef NON_STATIC_COMB_FILTER_CONST_C
static
#endif
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12)
{
opus_val32 x0, x1, x2, x3, x4;
int i;
x4 = x[-T-2];
x3 = x[-T-1];
x2 = x[-T];
x1 = x[-T+1];
for (i=0;i<N;i++)
{
x0=x[i-T+2];
y[i] = x[i]
+ MULT16_32_Q15(g10,x2)
+ MULT16_32_Q15(g11,ADD32(x1,x3))
+ MULT16_32_Q15(g12,ADD32(x0,x4));
y[i] = SATURATE(y[i], SIG_SAT);
x4=x3;
x3=x2;
x2=x1;
x1=x0;
}
}
#endif
#endif
#ifndef OVERRIDE_comb_filter
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap, int arch)
{
int i;
/* printf ("%d %d %f %f\n", T0, T1, g0, g1); */
opus_val16 g00, g01, g02, g10, g11, g12;
opus_val32 x0, x1, x2, x3, x4;
static const opus_val16 gains[3][3] = {
{QCONST16(0.3066406250f, 15), QCONST16(0.2170410156f, 15), QCONST16(0.1296386719f, 15)},
{QCONST16(0.4638671875f, 15), QCONST16(0.2680664062f, 15), QCONST16(0.f, 15)},
{QCONST16(0.7998046875f, 15), QCONST16(0.1000976562f, 15), QCONST16(0.f, 15)}};
if (g0==0 && g1==0)
{
/* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
if (x!=y)
OPUS_MOVE(y, x, N);
return;
}
/* When the gain is zero, T0 and/or T1 is set to zero. We need
to have then be at least 2 to avoid processing garbage data. */
T0 = IMAX(T0, COMBFILTER_MINPERIOD);
T1 = IMAX(T1, COMBFILTER_MINPERIOD);
g00 = MULT16_16_P15(g0, gains[tapset0][0]);
g01 = MULT16_16_P15(g0, gains[tapset0][1]);
g02 = MULT16_16_P15(g0, gains[tapset0][2]);
g10 = MULT16_16_P15(g1, gains[tapset1][0]);
g11 = MULT16_16_P15(g1, gains[tapset1][1]);
g12 = MULT16_16_P15(g1, gains[tapset1][2]);
x1 = x[-T1+1];
x2 = x[-T1 ];
x3 = x[-T1-1];
x4 = x[-T1-2];
/* If the filter didn't change, we don't need the overlap */
if (g0==g1 && T0==T1 && tapset0==tapset1)
overlap=0;
for (i=0;i<overlap;i++)
{
opus_val16 f;
x0=x[i-T1+2];
f = MULT16_16_Q15(window[i],window[i]);
y[i] = x[i]
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g00),x[i-T0])
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g01),ADD32(x[i-T0+1],x[i-T0-1]))
+ MULT16_32_Q15(MULT16_16_Q15((Q15ONE-f),g02),ADD32(x[i-T0+2],x[i-T0-2]))
+ MULT16_32_Q15(MULT16_16_Q15(f,g10),x2)
+ MULT16_32_Q15(MULT16_16_Q15(f,g11),ADD32(x1,x3))
+ MULT16_32_Q15(MULT16_16_Q15(f,g12),ADD32(x0,x4));
y[i] = SATURATE(y[i], SIG_SAT);
x4=x3;
x3=x2;
x2=x1;
x1=x0;
}
if (g1==0)
{
/* OPT: Happens to work without the OPUS_MOVE(), but only because the current encoder already copies x to y */
if (x!=y)
OPUS_MOVE(y+overlap, x+overlap, N-overlap);
return;
}
/* Compute the part with the constant filter. */
comb_filter_const(y+i, x+i, T1, N-i, g10, g11, g12, arch);
}
#endif /* OVERRIDE_comb_filter */
/* TF change table. Positive values mean better frequency resolution (longer
effective window), whereas negative values mean better time resolution
(shorter effective window). The second index is computed as:
4*isTransient + 2*tf_select + per_band_flag */
const signed char tf_select_table[4][8] = {
/*isTransient=0 isTransient=1 */
{0, -1, 0, -1, 0,-1, 0,-1}, /* 2.5 ms */
{0, -1, 0, -2, 1, 0, 1,-1}, /* 5 ms */
{0, -2, 0, -3, 2, 0, 1,-1}, /* 10 ms */
{0, -2, 0, -3, 3, 0, 1,-1}, /* 20 ms */
};
void init_caps(const CELTMode *m,int *cap,int LM,int C)
{
int i;
for (i=0;i<m->nbEBands;i++)
{
int N;
N=(m->eBands[i+1]-m->eBands[i])<<LM;
cap[i] = (m->cache.caps[m->nbEBands*(2*LM+C-1)+i]+64)*C*N>>2;
}
}
const char *opus_strerror(int error)
{
static const char * const error_strings[8] = {
"success",
"invalid argument",
"buffer too small",
"internal error",
"corrupted stream",
"request not implemented",
"invalid state",
"memory allocation failed"
};
if (error > 0 || error < -7)
return "unknown error";
else
return error_strings[-error];
}
const char *opus_get_version_string(void)
{
return "libopus " PACKAGE_VERSION
/* Applications may rely on the presence of this substring in the version
string to determine if they have a fixed-point or floating-point build
at runtime. */
#ifdef FIXED_POINT
"-fixed"
#endif
#ifdef FUZZING
"-fuzzing"
#endif
;
}

View File

@@ -0,0 +1,251 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/**
@file celt.h
@brief Contains all the functions for encoding and decoding audio
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef CELT_H
#define CELT_H
#include "../opus_types.h"
#include "../opus_defines.h"
#include "../opus_custom.h"
#include "entenc.h"
#include "entdec.h"
#include "arch.h"
#ifdef __cplusplus
extern "C" {
#endif
#define CELTEncoder OpusCustomEncoder
#define CELTDecoder OpusCustomDecoder
#define CELTMode OpusCustomMode
#define LEAK_BANDS 19
typedef struct {
int valid;
float tonality;
float tonality_slope;
float noisiness;
float activity;
float music_prob;
float music_prob_min;
float music_prob_max;
int bandwidth;
float activity_probability;
float max_pitch_ratio;
/* Store as Q6 char to save space. */
unsigned char leak_boost[LEAK_BANDS];
} AnalysisInfo;
typedef struct {
int signalType;
int offset;
} SILKInfo;
#define __celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
#define __celt_check_analysis_ptr(ptr) ((ptr) + ((ptr) - (const AnalysisInfo*)(ptr)))
#define __celt_check_silkinfo_ptr(ptr) ((ptr) + ((ptr) - (const SILKInfo*)(ptr)))
/* Encoder/decoder Requests */
#define CELT_SET_PREDICTION_REQUEST 10002
/** Controls the use of interframe prediction.
0=Independent frames
1=Short term interframe prediction allowed
2=Long term prediction allowed
*/
#define CELT_SET_PREDICTION(x) CELT_SET_PREDICTION_REQUEST, __opus_check_int(x)
#define CELT_SET_INPUT_CLIPPING_REQUEST 10004
#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, __opus_check_int(x)
#define CELT_GET_AND_CLEAR_ERROR_REQUEST 10007
#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, __opus_check_int_ptr(x)
#define CELT_SET_CHANNELS_REQUEST 10008
#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, __opus_check_int(x)
/* Internal */
#define CELT_SET_START_BAND_REQUEST 10010
#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, __opus_check_int(x)
#define CELT_SET_END_BAND_REQUEST 10012
#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, __opus_check_int(x)
#define CELT_GET_MODE_REQUEST 10015
/** Get the CELTMode used by an encoder or decoder */
#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, __celt_check_mode_ptr_ptr(x)
#define CELT_SET_SIGNALLING_REQUEST 10016
#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, __opus_check_int(x)
#define CELT_SET_TONALITY_REQUEST 10018
#define CELT_SET_TONALITY(x) CELT_SET_TONALITY_REQUEST, __opus_check_int(x)
#define CELT_SET_TONALITY_SLOPE_REQUEST 10020
#define CELT_SET_TONALITY_SLOPE(x) CELT_SET_TONALITY_SLOPE_REQUEST, __opus_check_int(x)
#define CELT_SET_ANALYSIS_REQUEST 10022
#define CELT_SET_ANALYSIS(x) CELT_SET_ANALYSIS_REQUEST, __celt_check_analysis_ptr(x)
#define OPUS_SET_LFE_REQUEST 10024
#define OPUS_SET_LFE(x) OPUS_SET_LFE_REQUEST, __opus_check_int(x)
#define OPUS_SET_ENERGY_MASK_REQUEST 10026
#define OPUS_SET_ENERGY_MASK(x) OPUS_SET_ENERGY_MASK_REQUEST, __opus_check_val16_ptr(x)
#define CELT_SET_SILK_INFO_REQUEST 10028
#define CELT_SET_SILK_INFO(x) CELT_SET_SILK_INFO_REQUEST, __celt_check_silkinfo_ptr(x)
/* Encoder stuff */
int celt_encoder_get_size(int channels);
int celt_encode_with_ec(OpusCustomEncoder * OPUS_RESTRICT st, const opus_val16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
int celt_encoder_init(CELTEncoder *st, opus_int32 sampling_rate, int channels,
int arch);
/* Decoder stuff */
int celt_decoder_get_size(int channels);
int celt_decoder_init(CELTDecoder *st, opus_int32 sampling_rate, int channels);
int celt_decode_with_ec(OpusCustomDecoder * OPUS_RESTRICT st, const unsigned char *data,
int len, opus_val16 * OPUS_RESTRICT pcm, int frame_size, ec_dec *dec, int accum);
#define celt_encoder_ctl opus_custom_encoder_ctl
#define celt_decoder_ctl opus_custom_decoder_ctl
#ifdef CUSTOM_MODES
#define OPUS_CUSTOM_NOSTATIC
#else
#define OPUS_CUSTOM_NOSTATIC static OPUS_INLINE
#endif
static const unsigned char trim_icdf[11] = {126, 124, 119, 109, 87, 41, 19, 9, 4, 2, 0};
/* Probs: NONE: 21.875%, LIGHT: 6.25%, NORMAL: 65.625%, AGGRESSIVE: 6.25% */
static const unsigned char spread_icdf[4] = {25, 23, 2, 0};
static const unsigned char tapset_icdf[3]={2,1,0};
#ifdef CUSTOM_MODES
static const unsigned char toOpusTable[20] = {
0xE0, 0xE8, 0xF0, 0xF8,
0xC0, 0xC8, 0xD0, 0xD8,
0xA0, 0xA8, 0xB0, 0xB8,
0x00, 0x00, 0x00, 0x00,
0x80, 0x88, 0x90, 0x98,
};
static const unsigned char fromOpusTable[16] = {
0x80, 0x88, 0x90, 0x98,
0x40, 0x48, 0x50, 0x58,
0x20, 0x28, 0x30, 0x38,
0x00, 0x08, 0x10, 0x18
};
static OPUS_INLINE int toOpus(unsigned char c)
{
int ret=0;
if (c<0xA0)
ret = toOpusTable[c>>3];
if (ret == 0)
return -1;
else
return ret|(c&0x7);
}
static OPUS_INLINE int fromOpus(unsigned char c)
{
if (c<0x80)
return -1;
else
return fromOpusTable[(c>>3)-16] | (c&0x7);
}
#endif /* CUSTOM_MODES */
#define COMBFILTER_MAXPERIOD 1024
#define COMBFILTER_MINPERIOD 15
extern const signed char tf_select_table[4][8];
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
void validate_celt_decoder(CELTDecoder *st);
#define VALIDATE_CELT_DECODER(st) validate_celt_decoder(st)
#else
#define VALIDATE_CELT_DECODER(st)
#endif
int resampling_factor(opus_int32 rate);
void celt_preemphasis(const opus_val16 * OPUS_RESTRICT pcmp, celt_sig * OPUS_RESTRICT inp,
int N, int CC, int upsample, const opus_val16 *coef, celt_sig *mem, int clip);
void comb_filter(opus_val32 *y, opus_val32 *x, int T0, int T1, int N,
opus_val16 g0, opus_val16 g1, int tapset0, int tapset1,
const opus_val16 *window, int overlap, int arch);
#ifdef NON_STATIC_COMB_FILTER_CONST_C
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12);
#endif
#ifndef OVERRIDE_COMB_FILTER_CONST
# define comb_filter_const(y, x, T, N, g10, g11, g12, arch) \
((void)(arch),comb_filter_const_c(y, x, T, N, g10, g11, g12))
#endif
void init_caps(const CELTMode *m,int *cap,int LM,int C);
#ifdef RESYNTH
void deemphasis(celt_sig *in[], opus_val16 *pcm, int N, int C, int downsample, const opus_val16 *coef, celt_sig *mem);
void celt_synthesis(const CELTMode *mode, celt_norm *X, celt_sig * out_syn[],
opus_val16 *oldBandE, int start, int effEnd, int C, int CC, int isTransient,
int LM, int downsample, int silence);
#endif
#ifdef __cplusplus
}
#endif
#endif /* CELT_H */

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,296 @@
/* Copyright (c) 2009-2010 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "celt_lpc.h"
#include "stack_alloc.h"
#include "mathops.h"
#include "pitch.h"
void _celt_lpc(
opus_val16 *_lpc, /* out: [0...p-1] LPC coefficients */
const opus_val32 *ac, /* in: [0...p] autocorrelation values */
int p
)
{
int i, j;
opus_val32 r;
opus_val32 error = ac[0];
#ifdef FIXED_POINT
opus_val32 lpc[LPC_ORDER];
#else
float *lpc = _lpc;
#endif
OPUS_CLEAR(lpc, p);
if (ac[0] != 0)
{
for (i = 0; i < p; i++) {
/* Sum up this iteration's reflection coefficient */
opus_val32 rr = 0;
for (j = 0; j < i; j++)
rr += MULT32_32_Q31(lpc[j],ac[i - j]);
rr += SHR32(ac[i + 1],3);
r = -frac_div32(SHL32(rr,3), error);
/* Update LPC coefficients and total error */
lpc[i] = SHR32(r,3);
for (j = 0; j < (i+1)>>1; j++)
{
opus_val32 tmp1, tmp2;
tmp1 = lpc[j];
tmp2 = lpc[i-1-j];
lpc[j] = tmp1 + MULT32_32_Q31(r,tmp2);
lpc[i-1-j] = tmp2 + MULT32_32_Q31(r,tmp1);
}
error = error - MULT32_32_Q31(MULT32_32_Q31(r,r),error);
/* Bail out once we get 30 dB gain */
#ifdef FIXED_POINT
if (error<SHR32(ac[0],10))
break;
#else
if (error<.001f*ac[0])
break;
#endif
}
}
#ifdef FIXED_POINT
for (i=0;i<p;i++)
_lpc[i] = ROUND16(lpc[i],16);
#endif
}
void celt_fir_c(
const opus_val16 *x,
const opus_val16 *num,
opus_val16 *y,
int N,
int ord,
int arch)
{
int i,j;
VARDECL(opus_val16, rnum);
SAVE_STACK;
celt_assert(x != y);
ALLOC(rnum, ord, opus_val16);
for(i=0;i<ord;i++)
rnum[i] = num[ord-i-1];
for (i=0;i<N-3;i+=4)
{
opus_val32 sum[4];
sum[0] = SHL32(EXTEND32(x[i ]), SIG_SHIFT);
sum[1] = SHL32(EXTEND32(x[i+1]), SIG_SHIFT);
sum[2] = SHL32(EXTEND32(x[i+2]), SIG_SHIFT);
sum[3] = SHL32(EXTEND32(x[i+3]), SIG_SHIFT);
xcorr_kernel(rnum, x+i-ord, sum, ord, arch);
y[i ] = ROUND16(sum[0], SIG_SHIFT);
y[i+1] = ROUND16(sum[1], SIG_SHIFT);
y[i+2] = ROUND16(sum[2], SIG_SHIFT);
y[i+3] = ROUND16(sum[3], SIG_SHIFT);
}
for (;i<N;i++)
{
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
for (j=0;j<ord;j++)
sum = MAC16_16(sum,rnum[j],x[i+j-ord]);
y[i] = ROUND16(sum, SIG_SHIFT);
}
RESTORE_STACK;
}
void celt_iir(const opus_val32 *_x,
const opus_val16 *den,
opus_val32 *_y,
int N,
int ord,
opus_val16 *mem,
int arch)
{
#ifdef SMALL_FOOTPRINT
int i,j;
(void)arch;
for (i=0;i<N;i++)
{
opus_val32 sum = _x[i];
for (j=0;j<ord;j++)
{
sum -= MULT16_16(den[j],mem[j]);
}
for (j=ord-1;j>=1;j--)
{
mem[j]=mem[j-1];
}
mem[0] = SROUND16(sum, SIG_SHIFT);
_y[i] = sum;
}
#else
int i,j;
VARDECL(opus_val16, rden);
VARDECL(opus_val16, y);
SAVE_STACK;
celt_assert((ord&3)==0);
ALLOC(rden, ord, opus_val16);
ALLOC(y, N+ord, opus_val16);
for(i=0;i<ord;i++)
rden[i] = den[ord-i-1];
for(i=0;i<ord;i++)
y[i] = -mem[ord-i-1];
for(;i<N+ord;i++)
y[i]=0;
for (i=0;i<N-3;i+=4)
{
/* Unroll by 4 as if it were an FIR filter */
opus_val32 sum[4];
sum[0]=_x[i];
sum[1]=_x[i+1];
sum[2]=_x[i+2];
sum[3]=_x[i+3];
xcorr_kernel(rden, y+i, sum, ord, arch);
/* Patch up the result to compensate for the fact that this is an IIR */
y[i+ord ] = -SROUND16(sum[0],SIG_SHIFT);
_y[i ] = sum[0];
sum[1] = MAC16_16(sum[1], y[i+ord ], den[0]);
y[i+ord+1] = -SROUND16(sum[1],SIG_SHIFT);
_y[i+1] = sum[1];
sum[2] = MAC16_16(sum[2], y[i+ord+1], den[0]);
sum[2] = MAC16_16(sum[2], y[i+ord ], den[1]);
y[i+ord+2] = -SROUND16(sum[2],SIG_SHIFT);
_y[i+2] = sum[2];
sum[3] = MAC16_16(sum[3], y[i+ord+2], den[0]);
sum[3] = MAC16_16(sum[3], y[i+ord+1], den[1]);
sum[3] = MAC16_16(sum[3], y[i+ord ], den[2]);
y[i+ord+3] = -SROUND16(sum[3],SIG_SHIFT);
_y[i+3] = sum[3];
}
for (;i<N;i++)
{
opus_val32 sum = _x[i];
for (j=0;j<ord;j++)
sum -= MULT16_16(rden[j],y[i+j]);
y[i+ord] = SROUND16(sum,SIG_SHIFT);
_y[i] = sum;
}
for(i=0;i<ord;i++)
mem[i] = _y[N-i-1];
RESTORE_STACK;
#endif
}
int _celt_autocorr(
const opus_val16 *x, /* in: [0...n-1] samples x */
opus_val32 *ac, /* out: [0...lag-1] ac values */
const opus_val16 *window,
int overlap,
int lag,
int n,
int arch
)
{
opus_val32 d;
int i, k;
int fastN=n-lag;
int shift;
const opus_val16 *xptr;
VARDECL(opus_val16, xx);
SAVE_STACK;
ALLOC(xx, n, opus_val16);
celt_assert(n>0);
celt_assert(overlap>=0);
if (overlap == 0)
{
xptr = x;
} else {
for (i=0;i<n;i++)
xx[i] = x[i];
for (i=0;i<overlap;i++)
{
xx[i] = MULT16_16_Q15(x[i],window[i]);
xx[n-i-1] = MULT16_16_Q15(x[n-i-1],window[i]);
}
xptr = xx;
}
shift=0;
#ifdef FIXED_POINT
{
opus_val32 ac0;
ac0 = 1+(n<<7);
if (n&1) ac0 += SHR32(MULT16_16(xptr[0],xptr[0]),9);
for(i=(n&1);i<n;i+=2)
{
ac0 += SHR32(MULT16_16(xptr[i],xptr[i]),9);
ac0 += SHR32(MULT16_16(xptr[i+1],xptr[i+1]),9);
}
shift = celt_ilog2(ac0)-30+10;
shift = (shift)/2;
if (shift>0)
{
for(i=0;i<n;i++)
xx[i] = PSHR32(xptr[i], shift);
xptr = xx;
} else
shift = 0;
}
#endif
celt_pitch_xcorr(xptr, xptr, ac, fastN, lag+1, arch);
for (k=0;k<=lag;k++)
{
for (i = k+fastN, d = 0; i < n; i++)
d = MAC16_16(d, xptr[i], xptr[i-k]);
ac[k] += d;
}
#ifdef FIXED_POINT
shift = 2*shift;
if (shift<=0)
ac[0] += SHL32((opus_int32)1, -shift);
if (ac[0] < 268435456)
{
int shift2 = 29 - EC_ILOG(ac[0]);
for (i=0;i<=lag;i++)
ac[i] = SHL32(ac[i], shift2);
shift -= shift2;
} else if (ac[0] >= 536870912)
{
int shift2=1;
if (ac[0] >= 1073741824)
shift2++;
for (i=0;i<=lag;i++)
ac[i] = SHR32(ac[i], shift2);
shift += shift2;
}
#endif
RESTORE_STACK;
return shift;
}

View File

@@ -0,0 +1,66 @@
/* Copyright (c) 2009-2010 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef PLC_H
#define PLC_H
#include "arch.h"
#include "cpu_support.h"
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
#include "x86/celt_lpc_sse.h"
#endif
#define LPC_ORDER 24
void _celt_lpc(opus_val16 *_lpc, const opus_val32 *ac, int p);
void celt_fir_c(
const opus_val16 *x,
const opus_val16 *num,
opus_val16 *y,
int N,
int ord,
int arch);
#if !defined(OVERRIDE_CELT_FIR)
#define celt_fir(x, num, y, N, ord, arch) \
(celt_fir_c(x, num, y, N, ord, arch))
#endif
void celt_iir(const opus_val32 *x,
const opus_val16 *den,
opus_val32 *y,
int N,
int ord,
opus_val16 *mem,
int arch);
int _celt_autocorr(const opus_val16 *x, opus_val32 *ac,
const opus_val16 *window, int overlap, int lag, int n, int arch);
#endif /* PLC_H */

View File

@@ -0,0 +1,70 @@
/* Copyright (c) 2010 Xiph.Org Foundation
* Copyright (c) 2013 Parrot */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef CPU_SUPPORT_H
#define CPU_SUPPORT_H
#include "../opus_types.h"
#include "../opus_defines.h"
#if defined(OPUS_HAVE_RTCD) && \
(defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
#include "arm/armcpu.h"
/* We currently support 4 ARM variants:
* arch[0] -> ARMv4
* arch[1] -> ARMv5E
* arch[2] -> ARMv6
* arch[3] -> NEON
*/
#define OPUS_ARCHMASK 3
#elif (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(OPUS_X86_PRESUME_SSE)) || \
(defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(OPUS_X86_PRESUME_SSE2)) || \
(defined(OPUS_X86_MAY_HAVE_SSE4_1) && !defined(OPUS_X86_PRESUME_SSE4_1)) || \
(defined(OPUS_X86_MAY_HAVE_AVX) && !defined(OPUS_X86_PRESUME_AVX))
#include "x86/x86cpu.h"
/* We currently support 5 x86 variants:
* arch[0] -> non-sse
* arch[1] -> sse
* arch[2] -> sse2
* arch[3] -> sse4.1
* arch[4] -> avx
*/
#define OPUS_ARCHMASK 7
int opus_select_arch(void);
#else
#define OPUS_ARCHMASK 0
static OPUS_INLINE int opus_select_arch(void)
{
return 0;
}
#endif
#endif

View File

@@ -0,0 +1,716 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2007-2009 Timothy B. Terriberry
Written by Timothy B. Terriberry and Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "os_support.h"
#include "cwrs.h"
#include "mathops.h"
#include "arch.h"
#include <pgmspace.h>
#ifdef CUSTOM_MODES
/*Guaranteed to return a conservatively large estimate of the binary logarithm
with frac bits of fractional precision.
Tested for all possible 32-bit inputs with frac=4, where the maximum
overestimation is 0.06254243 bits.*/
int log2_frac(opus_uint32 val, int frac)
{
int l;
l=EC_ILOG(val);
if(val&(val-1)){
/*This is (val>>l-16), but guaranteed to round up, even if adding a bias
before the shift would cause overflow (e.g., for 0xFFFFxxxx).
Doesn't work for val=0, but that case fails the test above.*/
if(l>16)val=((val-1)>>(l-16))+1;
else val<<=16-l;
l=(l-1)<<frac;
/*Note that we always need one iteration, since the rounding up above means
that we might need to adjust the integer part of the logarithm.*/
do{
int b;
b=(int)(val>>16);
l+=b<<frac;
val=(val+b)>>b;
val=(val*val+0x7FFF)>>15;
}
while(frac-->0);
/*If val is not exactly 0x8000, then we have to round up the remainder.*/
return l+(val>0x8000);
}
/*Exact powers of two require no rounding.*/
else return (l-1)<<frac;
}
#endif
/*Although derived separately, the pulse vector coding scheme is equivalent to
a Pyramid Vector Quantizer \cite{Fis86}.
Some additional notes about an early version appear at
https://people.xiph.org/~tterribe/notes/cwrs.html, but the codebook ordering
and the definitions of some terms have evolved since that was written.
The conversion from a pulse vector to an integer index (encoding) and back
(decoding) is governed by two related functions, V(N,K) and U(N,K).
V(N,K) = the number of combinations, with replacement, of N items, taken K
at a time, when a sign bit is added to each item taken at least once (i.e.,
the number of N-dimensional unit pulse vectors with K pulses).
One way to compute this is via
V(N,K) = K>0 ? sum(k=1...K,2**k*choose(N,k)*choose(K-1,k-1)) : 1,
where choose() is the binomial function.
A table of values for N<10 and K<10 looks like:
V[10][10] = {
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{1, 2, 2, 2, 2, 2, 2, 2, 2, 2},
{1, 4, 8, 12, 16, 20, 24, 28, 32, 36},
{1, 6, 18, 38, 66, 102, 146, 198, 258, 326},
{1, 8, 32, 88, 192, 360, 608, 952, 1408, 1992},
{1, 10, 50, 170, 450, 1002, 1970, 3530, 5890, 9290},
{1, 12, 72, 292, 912, 2364, 5336, 10836, 20256, 35436},
{1, 14, 98, 462, 1666, 4942, 12642, 28814, 59906, 115598},
{1, 16, 128, 688, 2816, 9424, 27008, 68464, 157184, 332688},
{1, 18, 162, 978, 4482, 16722, 53154, 148626, 374274, 864146}
};
U(N,K) = the number of such combinations wherein N-1 objects are taken at
most K-1 at a time.
This is given by
U(N,K) = sum(k=0...K-1,V(N-1,k))
= K>0 ? (V(N-1,K-1) + V(N,K-1))/2 : 0.
The latter expression also makes clear that U(N,K) is half the number of such
combinations wherein the first object is taken at least once.
Although it may not be clear from either of these definitions, U(N,K) is the
natural function to work with when enumerating the pulse vector codebooks,
not V(N,K).
U(N,K) is not well-defined for N=0, but with the extension
U(0,K) = K>0 ? 0 : 1,
the function becomes symmetric: U(N,K) = U(K,N), with a similar table:
U[10][10] = {
{1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
{0, 1, 1, 1, 1, 1, 1, 1, 1, 1},
{0, 1, 3, 5, 7, 9, 11, 13, 15, 17},
{0, 1, 5, 13, 25, 41, 61, 85, 113, 145},
{0, 1, 7, 25, 63, 129, 231, 377, 575, 833},
{0, 1, 9, 41, 129, 321, 681, 1289, 2241, 3649},
{0, 1, 11, 61, 231, 681, 1683, 3653, 7183, 13073},
{0, 1, 13, 85, 377, 1289, 3653, 8989, 19825, 40081},
{0, 1, 15, 113, 575, 2241, 7183, 19825, 48639, 108545},
{0, 1, 17, 145, 833, 3649, 13073, 40081, 108545, 265729}
};
With this extension, V(N,K) may be written in terms of U(N,K):
V(N,K) = U(N,K) + U(N,K+1)
for all N>=0, K>=0.
Thus U(N,K+1) represents the number of combinations where the first element
is positive or zero, and U(N,K) represents the number of combinations where
it is negative.
With a large enough table of U(N,K) values, we could write O(N) encoding
and O(min(N*log(K),N+K)) decoding routines, but such a table would be
prohibitively large for small embedded devices (K may be as large as 32767
for small N, and N may be as large as 200).
Both functions obey the same recurrence relation:
V(N,K) = V(N-1,K) + V(N,K-1) + V(N-1,K-1),
U(N,K) = U(N-1,K) + U(N,K-1) + U(N-1,K-1),
for all N>0, K>0, with different initial conditions at N=0 or K=0.
This allows us to construct a row of one of the tables above given the
previous row or the next row.
Thus we can derive O(NK) encoding and decoding routines with O(K) memory
using only addition and subtraction.
When encoding, we build up from the U(2,K) row and work our way forwards.
When decoding, we need to start at the U(N,K) row and work our way backwards,
which requires a means of computing U(N,K).
U(N,K) may be computed from two previous values with the same N:
U(N,K) = ((2*N-1)*U(N,K-1) - U(N,K-2))/(K-1) + U(N,K-2)
for all N>1, and since U(N,K) is symmetric, a similar relation holds for two
previous values with the same K:
U(N,K>1) = ((2*K-1)*U(N-1,K) - U(N-2,K))/(N-1) + U(N-2,K)
for all K>1.
This allows us to construct an arbitrary row of the U(N,K) table by starting
with the first two values, which are constants.
This saves roughly 2/3 the work in our O(NK) decoding routine, but costs O(K)
multiplications.
Similar relations can be derived for V(N,K), but are not used here.
For N>0 and K>0, U(N,K) and V(N,K) take on the form of an (N-1)-degree
polynomial for fixed N.
The first few are
U(1,K) = 1,
U(2,K) = 2*K-1,
U(3,K) = (2*K-2)*K+1,
U(4,K) = (((4*K-6)*K+8)*K-3)/3,
U(5,K) = ((((2*K-4)*K+10)*K-8)*K+3)/3,
and
V(1,K) = 2,
V(2,K) = 4*K,
V(3,K) = 4*K*K+2,
V(4,K) = 8*(K*K+2)*K/3,
V(5,K) = ((4*K*K+20)*K*K+6)/3,
for all K>0.
This allows us to derive O(N) encoding and O(N*log(K)) decoding routines for
small N (and indeed decoding is also O(N) for N<3).
@ARTICLE{Fis86,
author="Thomas R. Fischer",
title="A Pyramid Vector Quantizer",
journal="IEEE Transactions on Information Theory",
volume="IT-32",
number=4,
pages="568--583",
month=Jul,
year=1986
}*/
#if !defined(SMALL_FOOTPRINT)
/*U(N,K) = U(K,N) := N>0?K>0?U(N-1,K)+U(N,K-1)+U(N-1,K-1):0:K>0?1:0*/
# define CELT_PVQ_U(_n,_k) (CELT_PVQ_U_ROW[IMIN(_n,_k)][IMAX(_n,_k)])
/*V(N,K) := U(N,K)+U(N,K+1) = the number of PVQ codewords for a band of size N
with K pulses allocated to it.*/
# define CELT_PVQ_V(_n,_k) (CELT_PVQ_U(_n,_k)+CELT_PVQ_U(_n,(_k)+1))
/*For each V(N,K) supported, we will access element U(min(N,K+1),max(N,K+1)).
Thus, the number of entries in row I is the larger of the maximum number of
pulses we will ever allocate for a given N=I (K=128, or however many fit in
32 bits, whichever is smaller), plus one, and the maximum N for which
K=I-1 pulses fit in 32 bits.
The largest band size in an Opus Custom mode is 208.
Otherwise, we can limit things to the set of N which can be achieved by
splitting a band from a standard Opus mode: 176, 144, 96, 88, 72, 64, 48,
44, 36, 32, 24, 22, 18, 16, 8, 4, 2).*/
#if defined(CUSTOM_MODES)
static const opus_uint32 CELT_PVQ_U_DATA[1488] PROGMEM ={
#else
static const opus_uint32 CELT_PVQ_U_DATA[1272] PROGMEM ={
#endif
/*N=0, K=0...176:*/
1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
#if defined(CUSTOM_MODES)
/*...208:*/
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0,
#endif
/*N=1, K=1...176:*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
#if defined(CUSTOM_MODES)
/*...208:*/
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
1, 1, 1, 1, 1, 1,
#endif
/*N=2, K=2...176:*/
3, 5, 7, 9, 11, 13, 15, 17, 19, 21, 23, 25, 27, 29, 31, 33, 35, 37, 39, 41,
43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 63, 65, 67, 69, 71, 73, 75, 77, 79,
81, 83, 85, 87, 89, 91, 93, 95, 97, 99, 101, 103, 105, 107, 109, 111, 113,
115, 117, 119, 121, 123, 125, 127, 129, 131, 133, 135, 137, 139, 141, 143,
145, 147, 149, 151, 153, 155, 157, 159, 161, 163, 165, 167, 169, 171, 173,
175, 177, 179, 181, 183, 185, 187, 189, 191, 193, 195, 197, 199, 201, 203,
205, 207, 209, 211, 213, 215, 217, 219, 221, 223, 225, 227, 229, 231, 233,
235, 237, 239, 241, 243, 245, 247, 249, 251, 253, 255, 257, 259, 261, 263,
265, 267, 269, 271, 273, 275, 277, 279, 281, 283, 285, 287, 289, 291, 293,
295, 297, 299, 301, 303, 305, 307, 309, 311, 313, 315, 317, 319, 321, 323,
325, 327, 329, 331, 333, 335, 337, 339, 341, 343, 345, 347, 349, 351,
#if defined(CUSTOM_MODES)
/*...208:*/
353, 355, 357, 359, 361, 363, 365, 367, 369, 371, 373, 375, 377, 379, 381,
383, 385, 387, 389, 391, 393, 395, 397, 399, 401, 403, 405, 407, 409, 411,
413, 415,
#endif
/*N=3, K=3...176:*/
13, 25, 41, 61, 85, 113, 145, 181, 221, 265, 313, 365, 421, 481, 545, 613,
685, 761, 841, 925, 1013, 1105, 1201, 1301, 1405, 1513, 1625, 1741, 1861,
1985, 2113, 2245, 2381, 2521, 2665, 2813, 2965, 3121, 3281, 3445, 3613, 3785,
3961, 4141, 4325, 4513, 4705, 4901, 5101, 5305, 5513, 5725, 5941, 6161, 6385,
6613, 6845, 7081, 7321, 7565, 7813, 8065, 8321, 8581, 8845, 9113, 9385, 9661,
9941, 10225, 10513, 10805, 11101, 11401, 11705, 12013, 12325, 12641, 12961,
13285, 13613, 13945, 14281, 14621, 14965, 15313, 15665, 16021, 16381, 16745,
17113, 17485, 17861, 18241, 18625, 19013, 19405, 19801, 20201, 20605, 21013,
21425, 21841, 22261, 22685, 23113, 23545, 23981, 24421, 24865, 25313, 25765,
26221, 26681, 27145, 27613, 28085, 28561, 29041, 29525, 30013, 30505, 31001,
31501, 32005, 32513, 33025, 33541, 34061, 34585, 35113, 35645, 36181, 36721,
37265, 37813, 38365, 38921, 39481, 40045, 40613, 41185, 41761, 42341, 42925,
43513, 44105, 44701, 45301, 45905, 46513, 47125, 47741, 48361, 48985, 49613,
50245, 50881, 51521, 52165, 52813, 53465, 54121, 54781, 55445, 56113, 56785,
57461, 58141, 58825, 59513, 60205, 60901, 61601,
#if defined(CUSTOM_MODES)
/*...208:*/
62305, 63013, 63725, 64441, 65161, 65885, 66613, 67345, 68081, 68821, 69565,
70313, 71065, 71821, 72581, 73345, 74113, 74885, 75661, 76441, 77225, 78013,
78805, 79601, 80401, 81205, 82013, 82825, 83641, 84461, 85285, 86113,
#endif
/*N=4, K=4...176:*/
63, 129, 231, 377, 575, 833, 1159, 1561, 2047, 2625, 3303, 4089, 4991, 6017,
7175, 8473, 9919, 11521, 13287, 15225, 17343, 19649, 22151, 24857, 27775,
30913, 34279, 37881, 41727, 45825, 50183, 54809, 59711, 64897, 70375, 76153,
82239, 88641, 95367, 102425, 109823, 117569, 125671, 134137, 142975, 152193,
161799, 171801, 182207, 193025, 204263, 215929, 228031, 240577, 253575,
267033, 280959, 295361, 310247, 325625, 341503, 357889, 374791, 392217,
410175, 428673, 447719, 467321, 487487, 508225, 529543, 551449, 573951,
597057, 620775, 645113, 670079, 695681, 721927, 748825, 776383, 804609,
833511, 863097, 893375, 924353, 956039, 988441, 1021567, 1055425, 1090023,
1125369, 1161471, 1198337, 1235975, 1274393, 1313599, 1353601, 1394407,
1436025, 1478463, 1521729, 1565831, 1610777, 1656575, 1703233, 1750759,
1799161, 1848447, 1898625, 1949703, 2001689, 2054591, 2108417, 2163175,
2218873, 2275519, 2333121, 2391687, 2451225, 2511743, 2573249, 2635751,
2699257, 2763775, 2829313, 2895879, 2963481, 3032127, 3101825, 3172583,
3244409, 3317311, 3391297, 3466375, 3542553, 3619839, 3698241, 3777767,
3858425, 3940223, 4023169, 4107271, 4192537, 4278975, 4366593, 4455399,
4545401, 4636607, 4729025, 4822663, 4917529, 5013631, 5110977, 5209575,
5309433, 5410559, 5512961, 5616647, 5721625, 5827903, 5935489, 6044391,
6154617, 6266175, 6379073, 6493319, 6608921, 6725887, 6844225, 6963943,
7085049, 7207551,
#if defined(CUSTOM_MODES)
/*...208:*/
7331457, 7456775, 7583513, 7711679, 7841281, 7972327, 8104825, 8238783,
8374209, 8511111, 8649497, 8789375, 8930753, 9073639, 9218041, 9363967,
9511425, 9660423, 9810969, 9963071, 10116737, 10271975, 10428793, 10587199,
10747201, 10908807, 11072025, 11236863, 11403329, 11571431, 11741177,
11912575,
#endif
/*N=5, K=5...176:*/
321, 681, 1289, 2241, 3649, 5641, 8361, 11969, 16641, 22569, 29961, 39041,
50049, 63241, 78889, 97281, 118721, 143529, 172041, 204609, 241601, 283401,
330409, 383041, 441729, 506921, 579081, 658689, 746241, 842249, 947241,
1061761, 1186369, 1321641, 1468169, 1626561, 1797441, 1981449, 2179241,
2391489, 2618881, 2862121, 3121929, 3399041, 3694209, 4008201, 4341801,
4695809, 5071041, 5468329, 5888521, 6332481, 6801089, 7295241, 7815849,
8363841, 8940161, 9545769, 10181641, 10848769, 11548161, 12280841, 13047849,
13850241, 14689089, 15565481, 16480521, 17435329, 18431041, 19468809,
20549801, 21675201, 22846209, 24064041, 25329929, 26645121, 28010881,
29428489, 30899241, 32424449, 34005441, 35643561, 37340169, 39096641,
40914369, 42794761, 44739241, 46749249, 48826241, 50971689, 53187081,
55473921, 57833729, 60268041, 62778409, 65366401, 68033601, 70781609,
73612041, 76526529, 79526721, 82614281, 85790889, 89058241, 92418049,
95872041, 99421961, 103069569, 106816641, 110664969, 114616361, 118672641,
122835649, 127107241, 131489289, 135983681, 140592321, 145317129, 150160041,
155123009, 160208001, 165417001, 170752009, 176215041, 181808129, 187533321,
193392681, 199388289, 205522241, 211796649, 218213641, 224775361, 231483969,
238341641, 245350569, 252512961, 259831041, 267307049, 274943241, 282741889,
290705281, 298835721, 307135529, 315607041, 324252609, 333074601, 342075401,
351257409, 360623041, 370174729, 379914921, 389846081, 399970689, 410291241,
420810249, 431530241, 442453761, 453583369, 464921641, 476471169, 488234561,
500214441, 512413449, 524834241, 537479489, 550351881, 563454121, 576788929,
590359041, 604167209, 618216201, 632508801,
#if defined(CUSTOM_MODES)
/*...208:*/
647047809, 661836041, 676876329, 692171521, 707724481, 723538089, 739615241,
755958849, 772571841, 789457161, 806617769, 824056641, 841776769, 859781161,
878072841, 896654849, 915530241, 934702089, 954173481, 973947521, 994027329,
1014416041, 1035116809, 1056132801, 1077467201, 1099123209, 1121104041,
1143412929, 1166053121, 1189027881, 1212340489, 1235994241,
#endif
/*N=6, K=6...96:*/
1683, 3653, 7183, 13073, 22363, 36365, 56695, 85305, 124515, 177045, 246047,
335137, 448427, 590557, 766727, 982729, 1244979, 1560549, 1937199, 2383409,
2908411, 3522221, 4235671, 5060441, 6009091, 7095093, 8332863, 9737793,
11326283, 13115773, 15124775, 17372905, 19880915, 22670725, 25765455,
29189457, 32968347, 37129037, 41699767, 46710137, 52191139, 58175189,
64696159, 71789409, 79491819, 87841821, 96879431, 106646281, 117185651,
128542501, 140763503, 153897073, 167993403, 183104493, 199284183, 216588185,
235074115, 254801525, 275831935, 298228865, 322057867, 347386557, 374284647,
402823977, 433078547, 465124549, 499040399, 534906769, 572806619, 612825229,
655050231, 699571641, 746481891, 795875861, 847850911, 902506913, 959946283,
1020274013, 1083597703, 1150027593, 1219676595, 1292660325, 1369097135,
1449108145, 1532817275, 1620351277, 1711839767, 1807415257, 1907213187,
2011371957, 2120032959,
#if defined(CUSTOM_MODES)
/*...109:*/
2233340609U, 2351442379U, 2474488829U, 2602633639U, 2736033641U, 2874848851U,
3019242501U, 3169381071U, 3325434321U, 3487575323U, 3655980493U, 3830829623U,
4012305913U,
#endif
/*N=7, K=7...54*/
8989, 19825, 40081, 75517, 134245, 227305, 369305, 579125, 880685, 1303777,
1884961, 2668525, 3707509, 5064793, 6814249, 9041957, 11847485, 15345233,
19665841, 24957661, 31388293, 39146185, 48442297, 59511829, 72616013,
88043969, 106114625, 127178701, 151620757, 179861305, 212358985, 249612805,
292164445, 340600625, 395555537, 457713341, 527810725, 606639529, 695049433,
793950709, 904317037, 1027188385, 1163673953, 1314955181, 1482288821,
1667010073, 1870535785, 2094367717,
#if defined(CUSTOM_MODES)
/*...60:*/
2340095869U, 2609401873U, 2904062449U, 3225952925U, 3577050821U, 3959439497U,
#endif
/*N=8, K=8...37*/
48639, 108545, 224143, 433905, 795455, 1392065, 2340495, 3800305, 5984767,
9173505, 13726991, 20103025, 28875327, 40754369, 56610575, 77500017,
104692735, 139703809, 184327311, 240673265, 311207743, 398796225, 506750351,
638878193, 799538175, 993696769, 1226990095, 1505789553, 1837271615,
2229491905U,
#if defined(CUSTOM_MODES)
/*...40:*/
2691463695U, 3233240945U, 3866006015U,
#endif
/*N=9, K=9...28:*/
265729, 598417, 1256465, 2485825, 4673345, 8405905, 14546705, 24331777,
39490049, 62390545, 96220561, 145198913, 214828609, 312193553, 446304145,
628496897, 872893441, 1196924561, 1621925137, 2173806145U,
#if defined(CUSTOM_MODES)
/*...29:*/
2883810113U,
#endif
/*N=10, K=10...24:*/
1462563, 3317445, 7059735, 14218905, 27298155, 50250765, 89129247, 152951073,
254831667, 413442773, 654862247, 1014889769, 1541911931, 2300409629U,
3375210671U,
/*N=11, K=11...19:*/
8097453, 18474633, 39753273, 81270333, 158819253, 298199265, 540279585,
948062325, 1616336765,
#if defined(CUSTOM_MODES)
/*...20:*/
2684641785U,
#endif
/*N=12, K=12...18:*/
45046719, 103274625, 224298231, 464387817, 921406335, 1759885185,
3248227095U,
/*N=13, K=13...16:*/
251595969, 579168825, 1267854873, 2653649025U,
/*N=14, K=14:*/
1409933619
};
#if defined(CUSTOM_MODES)
static const opus_uint32 *const CELT_PVQ_U_ROW[15] PROGMEM={
CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 208,CELT_PVQ_U_DATA+ 415,
CELT_PVQ_U_DATA+ 621,CELT_PVQ_U_DATA+ 826,CELT_PVQ_U_DATA+1030,
CELT_PVQ_U_DATA+1233,CELT_PVQ_U_DATA+1336,CELT_PVQ_U_DATA+1389,
CELT_PVQ_U_DATA+1421,CELT_PVQ_U_DATA+1441,CELT_PVQ_U_DATA+1455,
CELT_PVQ_U_DATA+1464,CELT_PVQ_U_DATA+1470,CELT_PVQ_U_DATA+1473
};
#else
static const opus_uint32 *const CELT_PVQ_U_ROW[15] PROGMEM={
CELT_PVQ_U_DATA+ 0,CELT_PVQ_U_DATA+ 176,CELT_PVQ_U_DATA+ 351,
CELT_PVQ_U_DATA+ 525,CELT_PVQ_U_DATA+ 698,CELT_PVQ_U_DATA+ 870,
CELT_PVQ_U_DATA+1041,CELT_PVQ_U_DATA+1131,CELT_PVQ_U_DATA+1178,
CELT_PVQ_U_DATA+1207,CELT_PVQ_U_DATA+1226,CELT_PVQ_U_DATA+1240,
CELT_PVQ_U_DATA+1248,CELT_PVQ_U_DATA+1254,CELT_PVQ_U_DATA+1257
};
#endif
#if defined(CUSTOM_MODES)
void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
int k;
/*_maxk==0 => there's nothing to do.*/
celt_assert(_maxk>0);
_bits[0]=0;
for(k=1;k<=_maxk;k++)_bits[k]=log2_frac(CELT_PVQ_V(_n,k),_frac);
}
#endif
static opus_uint32 icwrs(int _n,const int *_y){
opus_uint32 i;
int j;
int k;
celt_assert(_n>=2);
j=_n-1;
i=_y[j]<0;
k=abs(_y[j]);
do{
j--;
i+=CELT_PVQ_U(_n-j,k);
k+=abs(_y[j]);
if(_y[j]<0)i+=CELT_PVQ_U(_n-j,k+1);
}
while(j>0);
return i;
}
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
celt_assert(_k>0);
ec_enc_uint(_enc,icwrs(_n,_y),CELT_PVQ_V(_n,_k));
}
static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y){
opus_uint32 p;
int s;
int k0;
opus_int16 val;
opus_val32 yy=0;
celt_assert(_k>0);
celt_assert(_n>1);
while(_n>2){
opus_uint32 q;
/*Lots of pulses case:*/
if(_k>=_n){
const opus_uint32 *row;
row=CELT_PVQ_U_ROW[_n];
/*Are the pulses in this dimension negative?*/
p=row[_k+1];
s=-(_i>=p);
_i-=p&s;
/*Count how many pulses were placed in this dimension.*/
k0=_k;
q=row[_n];
if(q>_i){
celt_sig_assert(p>q);
_k=_n;
do p=CELT_PVQ_U_ROW[--_k][_n];
while(p>_i);
}
else for(p=row[_k];p>_i;p=row[_k])_k--;
_i-=p;
val=(k0-_k+s)^s;
*_y++=val;
yy=MAC16_16(yy,val,val);
}
/*Lots of dimensions case:*/
else{
/*Are there any pulses in this dimension at all?*/
p=CELT_PVQ_U_ROW[_k][_n];
q=CELT_PVQ_U_ROW[_k+1][_n];
if(p<=_i&&_i<q){
_i-=p;
*_y++=0;
}
else{
/*Are the pulses in this dimension negative?*/
s=-(_i>=q);
_i-=q&s;
/*Count how many pulses were placed in this dimension.*/
k0=_k;
do p=CELT_PVQ_U_ROW[--_k][_n];
while(p>_i);
_i-=p;
val=(k0-_k+s)^s;
*_y++=val;
yy=MAC16_16(yy,val,val);
}
}
_n--;
}
/*_n==2*/
p=2*_k+1;
s=-(_i>=p);
_i-=p&s;
k0=_k;
_k=(_i+1)>>1;
if(_k)_i-=2*_k-1;
val=(k0-_k+s)^s;
*_y++=val;
yy=MAC16_16(yy,val,val);
/*_n==1*/
s=-(int)_i;
val=(_k+s)^s;
*_y=val;
yy=MAC16_16(yy,val,val);
return yy;
}
opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
return cwrsi(_n,_k,ec_dec_uint(_dec,CELT_PVQ_V(_n,_k)),_y);
}
#else /* SMALL_FOOTPRINT */
/*Computes the next row/column of any recurrence that obeys the relation
u[i][j]=u[i-1][j]+u[i][j-1]+u[i-1][j-1].
_ui0 is the base case for the new row/column.*/
static OPUS_INLINE void unext(opus_uint32 *_ui,unsigned _len,opus_uint32 _ui0){
opus_uint32 ui1;
unsigned j;
/*This do-while will overrun the array if we don't have storage for at least
2 values.*/
j=1; do {
ui1=UADD32(UADD32(_ui[j],_ui[j-1]),_ui0);
_ui[j-1]=_ui0;
_ui0=ui1;
} while (++j<_len);
_ui[j-1]=_ui0;
}
/*Computes the previous row/column of any recurrence that obeys the relation
u[i-1][j]=u[i][j]-u[i][j-1]-u[i-1][j-1].
_ui0 is the base case for the new row/column.*/
static OPUS_INLINE void uprev(opus_uint32 *_ui,unsigned _n,opus_uint32 _ui0){
opus_uint32 ui1;
unsigned j;
/*This do-while will overrun the array if we don't have storage for at least
2 values.*/
j=1; do {
ui1=USUB32(USUB32(_ui[j],_ui[j-1]),_ui0);
_ui[j-1]=_ui0;
_ui0=ui1;
} while (++j<_n);
_ui[j-1]=_ui0;
}
/*Compute V(_n,_k), as well as U(_n,0..._k+1).
_u: On exit, _u[i] contains U(_n,i) for i in [0..._k+1].*/
static opus_uint32 ncwrs_urow(unsigned _n,unsigned _k,opus_uint32 *_u){
opus_uint32 um2;
unsigned len;
unsigned k;
len=_k+2;
/*We require storage at least 3 values (e.g., _k>0).*/
celt_assert(len>=3);
_u[0]=0;
_u[1]=um2=1;
/*If _n==0, _u[0] should be 1 and the rest should be 0.*/
/*If _n==1, _u[i] should be 1 for i>1.*/
celt_assert(_n>=2);
/*If _k==0, the following do-while loop will overflow the buffer.*/
celt_assert(_k>0);
k=2;
do _u[k]=(k<<1)-1;
while(++k<len);
for(k=2;k<_n;k++)unext(_u+1,_k+1,1);
return _u[_k]+_u[_k+1];
}
/*Returns the _i'th combination of _k elements chosen from a set of size _n
with associated sign bits.
_y: Returns the vector of pulses.
_u: Must contain entries [0..._k+1] of row _n of U() on input.
Its contents will be destructively modified.*/
static opus_val32 cwrsi(int _n,int _k,opus_uint32 _i,int *_y,opus_uint32 *_u){
int j;
opus_int16 val;
opus_val32 yy=0;
celt_assert(_n>0);
j=0;
do{
opus_uint32 p;
int s;
int yj;
p=_u[_k+1];
s=-(_i>=p);
_i-=p&s;
yj=_k;
p=_u[_k];
while(p>_i)p=_u[--_k];
_i-=p;
yj-=_k;
val=(yj+s)^s;
_y[j]=val;
yy=MAC16_16(yy,val,val);
uprev(_u,_k+2,0);
}
while(++j<_n);
return yy;
}
/*Returns the index of the given combination of K elements chosen from a set
of size 1 with associated sign bits.
_y: The vector of pulses, whose sum of absolute values is K.
_k: Returns K.*/
static OPUS_INLINE opus_uint32 icwrs1(const int *_y,int *_k){
*_k=abs(_y[0]);
return _y[0]<0;
}
/*Returns the index of the given combination of K elements chosen from a set
of size _n with associated sign bits.
_y: The vector of pulses, whose sum of absolute values must be _k.
_nc: Returns V(_n,_k).*/
static OPUS_INLINE opus_uint32 icwrs(int _n,int _k,opus_uint32 *_nc,const int *_y,
opus_uint32 *_u){
opus_uint32 i;
int j;
int k;
/*We can't unroll the first two iterations of the loop unless _n>=2.*/
celt_assert(_n>=2);
_u[0]=0;
for(k=1;k<=_k+1;k++)_u[k]=(k<<1)-1;
i=icwrs1(_y+_n-1,&k);
j=_n-2;
i+=_u[k];
k+=abs(_y[j]);
if(_y[j]<0)i+=_u[k+1];
while(j-->0){
unext(_u,_k+2,0);
i+=_u[k];
k+=abs(_y[j]);
if(_y[j]<0)i+=_u[k+1];
}
*_nc=_u[k]+_u[k+1];
return i;
}
#ifdef CUSTOM_MODES
void get_required_bits(opus_int16 *_bits,int _n,int _maxk,int _frac){
int k;
/*_maxk==0 => there's nothing to do.*/
celt_assert(_maxk>0);
_bits[0]=0;
if (_n==1)
{
for (k=1;k<=_maxk;k++)
_bits[k] = 1<<_frac;
}
else {
VARDECL(opus_uint32,u);
SAVE_STACK;
ALLOC(u,_maxk+2U,opus_uint32);
ncwrs_urow(_n,_maxk,u);
for(k=1;k<=_maxk;k++)
_bits[k]=log2_frac(u[k]+u[k+1],_frac);
RESTORE_STACK;
}
}
#endif /* CUSTOM_MODES */
void encode_pulses(const int *_y,int _n,int _k,ec_enc *_enc){
opus_uint32 i;
VARDECL(opus_uint32,u);
opus_uint32 nc;
SAVE_STACK;
celt_assert(_k>0);
ALLOC(u,_k+2U,opus_uint32);
i=icwrs(_n,_k,&nc,_y,u);
ec_enc_uint(_enc,i,nc);
RESTORE_STACK;
}
opus_val32 decode_pulses(int *_y,int _n,int _k,ec_dec *_dec){
VARDECL(opus_uint32,u);
int ret;
SAVE_STACK;
celt_assert(_k>0);
ALLOC(u,_k+2U,opus_uint32);
ret = cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u);
RESTORE_STACK;
return ret;
}
#endif /* SMALL_FOOTPRINT */

View File

@@ -0,0 +1,48 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2007-2009 Timothy B. Terriberry
Written by Timothy B. Terriberry and Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef CWRS_H
#define CWRS_H
#include "arch.h"
#include "stack_alloc.h"
#include "entenc.h"
#include "entdec.h"
#ifdef CUSTOM_MODES
int log2_frac(opus_uint32 val, int frac);
#endif
void get_required_bits(opus_int16 *bits, int N, int K, int frac);
void encode_pulses(const int *_y, int N, int K, ec_enc *enc);
opus_val32 decode_pulses(int *_y, int N, int K, ec_dec *dec);
#endif /* CWRS_H */

View File

@@ -0,0 +1,87 @@
/* Copyright (c) 2003-2008 Timothy B. Terriberry
Copyright (c) 2008 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.
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 COPYRIGHT OWNER
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.
*/
/*Some common macros for potential platform-specific optimization.*/
#include "../opus_types.h"
#include <math.h>
#include <limits.h>
#include "arch.h"
#if !defined(_ecintrin_H)
# define _ecintrin_H (1)
/*Some specific platforms may have optimized intrinsic or OPUS_INLINE assembly
versions of these functions which can substantially improve performance.
We define macros for them to allow easy incorporation of these non-ANSI
features.*/
/*Modern gcc (4.x) can compile the naive versions of min and max with cmov if
given an appropriate architecture, but the branchless bit-twiddling versions
are just as fast, and do not require any special target architecture.
Earlier gcc versions (3.x) compiled both code to the same assembly
instructions, because of the way they represented ((_b)>(_a)) internally.*/
# define EC_MINI(_a,_b) ((_a)+(((_b)-(_a))&-((_b)<(_a))))
/*Count leading zeros.
This macro should only be used for implementing ec_ilog(), if it is defined.
All other code should use EC_ILOG() instead.*/
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
# include <intrin.h>
/*In _DEBUG mode this is not an intrinsic by default.*/
# pragma intrinsic(_BitScanReverse)
static __inline int ec_bsr(unsigned long _x){
unsigned long ret;
_BitScanReverse(&ret,_x);
return (int)ret;
}
# define EC_CLZ0 (1)
# define EC_CLZ(_x) (-ec_bsr(_x))
#elif defined(ENABLE_TI_DSPLIB)
# include "dsplib.h"
# define EC_CLZ0 (31)
# define EC_CLZ(_x) (_lnorm(_x))
#elif __GNUC_PREREQ(3,4)
# if INT_MAX>=2147483647
# define EC_CLZ0 ((int)sizeof(unsigned)*CHAR_BIT)
# define EC_CLZ(_x) (__builtin_clz(_x))
# elif LONG_MAX>=2147483647L
# define EC_CLZ0 ((int)sizeof(unsigned long)*CHAR_BIT)
# define EC_CLZ(_x) (__builtin_clzl(_x))
# endif
#endif
#if defined(EC_CLZ)
/*Note that __builtin_clz is not defined when _x==0, according to the gcc
documentation (and that of the BSR instruction that implements it on x86).
The majority of the time we can never pass it zero.
When we need to, it can be special cased.*/
# define EC_ILOG(_x) (EC_CLZ0-EC_CLZ(_x))
#else
int ec_ilog(opus_uint32 _v);
# define EC_ILOG(_x) (ec_ilog(_x))
#endif
#endif

View File

@@ -0,0 +1,153 @@
/* Copyright (c) 2001-2011 Timothy B. Terriberry
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "entcode.h"
#include "arch.h"
#if !defined(EC_CLZ)
/*This is a fallback for systems where we don't know how to access
a BSR or CLZ instruction (see ecintrin.h).
If you are optimizing Opus on a new platform and it has a native CLZ or
BZR (e.g. cell, MIPS, x86, etc) then making it available to Opus will be
an easy performance win.*/
int ec_ilog(opus_uint32 _v){
/*On a Pentium M, this branchless version tested as the fastest on
1,000,000,000 random 32-bit integers, edging out a similar version with
branches, and a 256-entry LUT version.*/
int ret;
int m;
ret=!!_v;
m=!!(_v&0xFFFF0000)<<4;
_v>>=m;
ret|=m;
m=!!(_v&0xFF00)<<3;
_v>>=m;
ret|=m;
m=!!(_v&0xF0)<<2;
_v>>=m;
ret|=m;
m=!!(_v&0xC)<<1;
_v>>=m;
ret|=m;
ret+=!!(_v&0x2);
return ret;
}
#endif
#if 1
/* This is a faster version of ec_tell_frac() that takes advantage
of the low (1/8 bit) resolution to use just a linear function
followed by a lookup to determine the exact transition thresholds. */
opus_uint32 ec_tell_frac(ec_ctx *_this){
static const unsigned correction[8] =
{35733, 38967, 42495, 46340,
50535, 55109, 60097, 65535};
opus_uint32 nbits;
opus_uint32 r;
int l;
unsigned b;
nbits=_this->nbits_total<<BITRES;
l=EC_ILOG(_this->rng);
r=_this->rng>>(l-16);
b = (r>>12)-8;
b += r>correction[b];
l = (l<<3)+b;
return nbits-l;
}
#else
opus_uint32 ec_tell_frac(ec_ctx *_this){
opus_uint32 nbits;
opus_uint32 r;
int l;
int i;
/*To handle the non-integral number of bits still left in the encoder/decoder
state, we compute the worst-case number of bits of val that must be
encoded to ensure that the value is inside the range for any possible
subsequent bits.
The computation here is independent of val itself (the decoder does not
even track that value), even though the real number of bits used after
ec_enc_done() may be 1 smaller if rng is a power of two and the
corresponding trailing bits of val are all zeros.
If we did try to track that special case, then coding a value with a
probability of 1/(1<<n) might sometimes appear to use more than n bits.
This may help explain the surprising result that a newly initialized
encoder or decoder claims to have used 1 bit.*/
nbits=_this->nbits_total<<BITRES;
l=EC_ILOG(_this->rng);
r=_this->rng>>(l-16);
for(i=BITRES;i-->0;){
int b;
r=r*r>>15;
b=(int)(r>>16);
l=l<<1|b;
r>>=b;
}
return nbits-l;
}
#endif
#ifdef USE_SMALL_DIV_TABLE
/* Result of 2^32/(2*i+1), except for i=0. */
const opus_uint32 SMALL_DIV_TABLE[129] = {
0xFFFFFFFF, 0x55555555, 0x33333333, 0x24924924,
0x1C71C71C, 0x1745D174, 0x13B13B13, 0x11111111,
0x0F0F0F0F, 0x0D79435E, 0x0C30C30C, 0x0B21642C,
0x0A3D70A3, 0x097B425E, 0x08D3DCB0, 0x08421084,
0x07C1F07C, 0x07507507, 0x06EB3E45, 0x06906906,
0x063E7063, 0x05F417D0, 0x05B05B05, 0x0572620A,
0x05397829, 0x05050505, 0x04D4873E, 0x04A7904A,
0x047DC11F, 0x0456C797, 0x04325C53, 0x04104104,
0x03F03F03, 0x03D22635, 0x03B5CC0E, 0x039B0AD1,
0x0381C0E0, 0x0369D036, 0x03531DEC, 0x033D91D2,
0x0329161F, 0x03159721, 0x03030303, 0x02F14990,
0x02E05C0B, 0x02D02D02, 0x02C0B02C, 0x02B1DA46,
0x02A3A0FD, 0x0295FAD4, 0x0288DF0C, 0x027C4597,
0x02702702, 0x02647C69, 0x02593F69, 0x024E6A17,
0x0243F6F0, 0x0239E0D5, 0x02302302, 0x0226B902,
0x021D9EAD, 0x0214D021, 0x020C49BA, 0x02040810,
0x01FC07F0, 0x01F44659, 0x01ECC07B, 0x01E573AC,
0x01DE5D6E, 0x01D77B65, 0x01D0CB58, 0x01CA4B30,
0x01C3F8F0, 0x01BDD2B8, 0x01B7D6C3, 0x01B20364,
0x01AC5701, 0x01A6D01A, 0x01A16D3F, 0x019C2D14,
0x01970E4F, 0x01920FB4, 0x018D3018, 0x01886E5F,
0x0183C977, 0x017F405F, 0x017AD220, 0x01767DCE,
0x01724287, 0x016E1F76, 0x016A13CD, 0x01661EC6,
0x01623FA7, 0x015E75BB, 0x015AC056, 0x01571ED3,
0x01539094, 0x01501501, 0x014CAB88, 0x0149539E,
0x01460CBC, 0x0142D662, 0x013FB013, 0x013C995A,
0x013991C2, 0x013698DF, 0x0133AE45, 0x0130D190,
0x012E025C, 0x012B404A, 0x01288B01, 0x0125E227,
0x01234567, 0x0120B470, 0x011E2EF3, 0x011BB4A4,
0x01194538, 0x0116E068, 0x011485F0, 0x0112358E,
0x010FEF01, 0x010DB20A, 0x010B7E6E, 0x010953F3,
0x01073260, 0x0105197F, 0x0103091B, 0x01010101
};
#endif

View File

@@ -0,0 +1,152 @@
/* Copyright (c) 2001-2011 Timothy B. Terriberry
Copyright (c) 2008-2009 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.
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 COPYRIGHT OWNER
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.
*/
#include "../opus_types.h"
#include "../opus_defines.h"
#if !defined(_entcode_H)
# define _entcode_H (1)
# include <limits.h>
# include <stddef.h>
# include "ecintrin.h"
extern const opus_uint32 SMALL_DIV_TABLE[129];
#ifdef OPUS_ARM_ASM
#define USE_SMALL_DIV_TABLE
#endif
/*OPT: ec_window must be at least 32 bits, but if you have fast arithmetic on a
larger type, you can speed up the decoder by using it here.*/
typedef opus_uint32 ec_window;
typedef struct ec_ctx ec_ctx;
typedef struct ec_ctx ec_enc;
typedef struct ec_ctx ec_dec;
# define EC_WINDOW_SIZE ((int)sizeof(ec_window)*CHAR_BIT)
/*The number of bits to use for the range-coded part of unsigned integers.*/
# define EC_UINT_BITS (8)
/*The resolution of fractional-precision bit usage measurements, i.e.,
3 => 1/8th bits.*/
# define BITRES 3
/*The entropy encoder/decoder context.
We use the same structure for both, so that common functions like ec_tell()
can be used on either one.*/
struct ec_ctx{
/*Buffered input/output.*/
unsigned char *buf;
/*The size of the buffer.*/
opus_uint32 storage;
/*The offset at which the last byte containing raw bits was read/written.*/
opus_uint32 end_offs;
/*Bits that will be read from/written at the end.*/
ec_window end_window;
/*Number of valid bits in end_window.*/
int nend_bits;
/*The total number of whole bits read/written.
This does not include partial bits currently in the range coder.*/
int nbits_total;
/*The offset at which the next range coder byte will be read/written.*/
opus_uint32 offs;
/*The number of values in the current range.*/
opus_uint32 rng;
/*In the decoder: the difference between the top of the current range and
the input value, minus one.
In the encoder: the low end of the current range.*/
opus_uint32 val;
/*In the decoder: the saved normalization factor from ec_decode().
In the encoder: the number of oustanding carry propagating symbols.*/
opus_uint32 ext;
/*A buffered input/output symbol, awaiting carry propagation.*/
int rem;
/*Nonzero if an error occurred.*/
int error;
};
static OPUS_INLINE opus_uint32 ec_range_bytes(ec_ctx *_this){
return _this->offs;
}
static OPUS_INLINE unsigned char *ec_get_buffer(ec_ctx *_this){
return _this->buf;
}
static OPUS_INLINE int ec_get_error(ec_ctx *_this){
return _this->error;
}
/*Returns the number of bits "used" by the encoded or decoded symbols so far.
This same number can be computed in either the encoder or the decoder, and is
suitable for making coding decisions.
Return: The number of bits.
This will always be slightly larger than the exact value (e.g., all
rounding error is in the positive direction).*/
static OPUS_INLINE int ec_tell(ec_ctx *_this){
return _this->nbits_total-EC_ILOG(_this->rng);
}
/*Returns the number of bits "used" by the encoded or decoded symbols so far.
This same number can be computed in either the encoder or the decoder, and is
suitable for making coding decisions.
Return: The number of bits scaled by 2**BITRES.
This will always be slightly larger than the exact value (e.g., all
rounding error is in the positive direction).*/
opus_uint32 ec_tell_frac(ec_ctx *_this);
/* Tested exhaustively for all n and for 1<=d<=256 */
static OPUS_INLINE opus_uint32 celt_udiv(opus_uint32 n, opus_uint32 d) {
celt_sig_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE
if (d>256)
return n/d;
else {
opus_uint32 t, q;
t = EC_ILOG(d&-d);
q = (opus_uint64)SMALL_DIV_TABLE[d>>t]*(n>>(t-1))>>32;
return q+(n-q*d >= d);
}
#else
return n/d;
#endif
}
static OPUS_INLINE opus_int32 celt_sudiv(opus_int32 n, opus_int32 d) {
celt_sig_assert(d>0);
#ifdef USE_SMALL_DIV_TABLE
if (n<0)
return -(opus_int32)celt_udiv(-n, d);
else
return celt_udiv(n, d);
#else
return n/d;
#endif
}
#endif

View File

@@ -0,0 +1,245 @@
/* Copyright (c) 2001-2011 Timothy B. Terriberry
Copyright (c) 2008-2009 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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include <stddef.h>
#include "os_support.h"
#include "arch.h"
#include "entdec.h"
#include "mfrngcod.h"
/*A range decoder.
This is an entropy decoder based upon \cite{Mar79}, which is itself a
rediscovery of the FIFO arithmetic code introduced by \cite{Pas76}.
It is very similar to arithmetic encoding, except that encoding is done with
digits in any base, instead of with bits, and so it is faster when using
larger bases (i.e.: a byte).
The author claims an average waste of $\frac{1}{2}\log_b(2b)$ bits, where $b$
is the base, longer than the theoretical optimum, but to my knowledge there
is no published justification for this claim.
This only seems true when using near-infinite precision arithmetic so that
the process is carried out with no rounding errors.
An excellent description of implementation details is available at
http://www.arturocampos.com/ac_range.html
A recent work \cite{MNW98} which proposes several changes to arithmetic
encoding for efficiency actually re-discovers many of the principles
behind range encoding, and presents a good theoretical analysis of them.
End of stream is handled by writing out the smallest number of bits that
ensures that the stream will be correctly decoded regardless of the value of
any subsequent bits.
ec_tell() can be used to determine how many bits were needed to decode
all the symbols thus far; other data can be packed in the remaining bits of
the input buffer.
@PHDTHESIS{Pas76,
author="Richard Clark Pasco",
title="Source coding algorithms for fast data compression",
school="Dept. of Electrical Engineering, Stanford University",
address="Stanford, CA",
month=May,
year=1976
}
@INPROCEEDINGS{Mar79,
author="Martin, G.N.N.",
title="Range encoding: an algorithm for removing redundancy from a digitised
message",
booktitle="Video & Data Recording Conference",
year=1979,
address="Southampton",
month=Jul
}
@ARTICLE{MNW98,
author="Alistair Moffat and Radford Neal and Ian H. Witten",
title="Arithmetic Coding Revisited",
journal="{ACM} Transactions on Information Systems",
year=1998,
volume=16,
number=3,
pages="256--294",
month=Jul,
URL="http://www.stanford.edu/class/ee398a/handouts/papers/Moffat98ArithmCoding.pdf"
}*/
static int ec_read_byte(ec_dec *_this){
return _this->offs<_this->storage?_this->buf[_this->offs++]:0;
}
static int ec_read_byte_from_end(ec_dec *_this){
return _this->end_offs<_this->storage?
_this->buf[_this->storage-++(_this->end_offs)]:0;
}
/*Normalizes the contents of val and rng so that rng lies entirely in the
high-order symbol.*/
static void ec_dec_normalize(ec_dec *_this){
/*If the range is too small, rescale it and input some bits.*/
while(_this->rng<=EC_CODE_BOT){
int sym;
_this->nbits_total+=EC_SYM_BITS;
_this->rng<<=EC_SYM_BITS;
/*Use up the remaining bits from our last symbol.*/
sym=_this->rem;
/*Read the next value from the input.*/
_this->rem=ec_read_byte(_this);
/*Take the rest of the bits we need from this new symbol.*/
sym=(sym<<EC_SYM_BITS|_this->rem)>>(EC_SYM_BITS-EC_CODE_EXTRA);
/*And subtract them from val, capped to be less than EC_CODE_TOP.*/
_this->val=((_this->val<<EC_SYM_BITS)+(EC_SYM_MAX&~sym))&(EC_CODE_TOP-1);
}
}
void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage){
_this->buf=_buf;
_this->storage=_storage;
_this->end_offs=0;
_this->end_window=0;
_this->nend_bits=0;
/*This is the offset from which ec_tell() will subtract partial bits.
The final value after the ec_dec_normalize() call will be the same as in
the encoder, but we have to compensate for the bits that are added there.*/
_this->nbits_total=EC_CODE_BITS+1
-((EC_CODE_BITS-EC_CODE_EXTRA)/EC_SYM_BITS)*EC_SYM_BITS;
_this->offs=0;
_this->rng=1U<<EC_CODE_EXTRA;
_this->rem=ec_read_byte(_this);
_this->val=_this->rng-1-(_this->rem>>(EC_SYM_BITS-EC_CODE_EXTRA));
_this->error=0;
/*Normalize the interval.*/
ec_dec_normalize(_this);
}
unsigned ec_decode(ec_dec *_this,unsigned _ft){
unsigned s;
_this->ext=celt_udiv(_this->rng,_ft);
s=(unsigned)(_this->val/_this->ext);
return _ft-EC_MINI(s+1,_ft);
}
unsigned ec_decode_bin(ec_dec *_this,unsigned _bits){
unsigned s;
_this->ext=_this->rng>>_bits;
s=(unsigned)(_this->val/_this->ext);
return (1U<<_bits)-EC_MINI(s+1U,1U<<_bits);
}
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
opus_uint32 s;
s=IMUL32(_this->ext,_ft-_fh);
_this->val-=s;
_this->rng=_fl>0?IMUL32(_this->ext,_fh-_fl):_this->rng-s;
ec_dec_normalize(_this);
}
/*The probability of having a "one" is 1/(1<<_logp).*/
int ec_dec_bit_logp(ec_dec *_this,unsigned _logp){
opus_uint32 r;
opus_uint32 d;
opus_uint32 s;
int ret;
r=_this->rng;
d=_this->val;
s=r>>_logp;
ret=d<s;
if(!ret)_this->val=d-s;
_this->rng=ret?s:r-s;
ec_dec_normalize(_this);
return ret;
}
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb){
opus_uint32 r;
opus_uint32 d;
opus_uint32 s;
opus_uint32 t;
int ret;
s=_this->rng;
d=_this->val;
r=s>>_ftb;
ret=-1;
do{
t=s;
s=IMUL32(r,_icdf[++ret]);
}
while(d<s);
_this->val=d-s;
_this->rng=t-s;
ec_dec_normalize(_this);
return ret;
}
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft){
unsigned ft;
unsigned s;
int ftb;
/*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
celt_assert(_ft>1);
_ft--;
ftb=EC_ILOG(_ft);
if(ftb>EC_UINT_BITS){
opus_uint32 t;
ftb-=EC_UINT_BITS;
ft=(unsigned)(_ft>>ftb)+1;
s=ec_decode(_this,ft);
ec_dec_update(_this,s,s+1,ft);
t=(opus_uint32)s<<ftb|ec_dec_bits(_this,ftb);
if(t<=_ft)return t;
_this->error=1;
return _ft;
}
else{
_ft++;
s=ec_decode(_this,(unsigned)_ft);
ec_dec_update(_this,s,s+1,(unsigned)_ft);
return s;
}
}
opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){
ec_window window;
int available;
opus_uint32 ret;
window=_this->end_window;
available=_this->nend_bits;
if((unsigned)available<_bits){
do{
window|=(ec_window)ec_read_byte_from_end(_this)<<available;
available+=EC_SYM_BITS;
}
while(available<=EC_WINDOW_SIZE-EC_SYM_BITS);
}
ret=(opus_uint32)window&(((opus_uint32)1<<_bits)-1U);
window>>=_bits;
available-=_bits;
_this->end_window=window;
_this->nend_bits=available;
_this->nbits_total+=_bits;
return ret;
}

View File

@@ -0,0 +1,100 @@
/* Copyright (c) 2001-2011 Timothy B. Terriberry
Copyright (c) 2008-2009 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.
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 COPYRIGHT OWNER
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.
*/
#if !defined(_entdec_H)
# define _entdec_H (1)
# include <limits.h>
# include "entcode.h"
/*Initializes the decoder.
_buf: The input buffer to use.
Return: 0 on success, or a negative value on error.*/
void ec_dec_init(ec_dec *_this,unsigned char *_buf,opus_uint32 _storage);
/*Calculates the cumulative frequency for the next symbol.
This can then be fed into the probability model to determine what that
symbol is, and the additional frequency information required to advance to
the next symbol.
This function cannot be called more than once without a corresponding call to
ec_dec_update(), or decoding will not proceed correctly.
_ft: The total frequency of the symbols in the alphabet the next symbol was
encoded with.
Return: A cumulative frequency representing the encoded symbol.
If the cumulative frequency of all the symbols before the one that
was encoded was fl, and the cumulative frequency of all the symbols
up to and including the one encoded is fh, then the returned value
will fall in the range [fl,fh).*/
unsigned ec_decode(ec_dec *_this,unsigned _ft);
/*Equivalent to ec_decode() with _ft==1<<_bits.*/
unsigned ec_decode_bin(ec_dec *_this,unsigned _bits);
/*Advance the decoder past the next symbol using the frequency information the
symbol was encoded with.
Exactly one call to ec_decode() must have been made so that all necessary
intermediate calculations are performed.
_fl: The cumulative frequency of all symbols that come before the symbol
decoded.
_fh: The cumulative frequency of all symbols up to and including the symbol
decoded.
Together with _fl, this defines the range [_fl,_fh) in which the value
returned above must fall.
_ft: The total frequency of the symbols in the alphabet the symbol decoded
was encoded in.
This must be the same as passed to the preceding call to ec_decode().*/
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft);
/* Decode a bit that has a 1/(1<<_logp) probability of being a one */
int ec_dec_bit_logp(ec_dec *_this,unsigned _logp);
/*Decodes a symbol given an "inverse" CDF table.
No call to ec_dec_update() is necessary after this call.
_icdf: The "inverse" CDF, such that symbol s falls in the range
[s>0?ft-_icdf[s-1]:0,ft-_icdf[s]), where ft=1<<_ftb.
The values must be monotonically non-increasing, and the last value
must be 0.
_ftb: The number of bits of precision in the cumulative distribution.
Return: The decoded symbol s.*/
int ec_dec_icdf(ec_dec *_this,const unsigned char *_icdf,unsigned _ftb);
/*Extracts a raw unsigned integer with a non-power-of-2 range from the stream.
The bits must have been encoded with ec_enc_uint().
No call to ec_dec_update() is necessary after this call.
_ft: The number of integers that can be decoded (one more than the max).
This must be at least 2, and no more than 2**32-1.
Return: The decoded bits.*/
opus_uint32 ec_dec_uint(ec_dec *_this,opus_uint32 _ft);
/*Extracts a sequence of raw bits from the stream.
The bits must have been encoded with ec_enc_bits().
No call to ec_dec_update() is necessary after this call.
_ftb: The number of bits to extract.
This must be between 0 and 25, inclusive.
Return: The decoded bits.*/
opus_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
#endif

View File

@@ -0,0 +1,294 @@
/* Copyright (c) 2001-2011 Timothy B. Terriberry
Copyright (c) 2008-2009 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.
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 COPYRIGHT OWNER
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.
*/
//#if defined(HAVE_CONFIG_H)
# include "../config.h"
//#endif
#include "os_support.h"
#include "arch.h"
#include "entenc.h"
#include "mfrngcod.h"
/*A range encoder.
See entdec.c and the references for implementation details \cite{Mar79,MNW98}.
@INPROCEEDINGS{Mar79,
author="Martin, G.N.N.",
title="Range encoding: an algorithm for removing redundancy from a digitised
message",
booktitle="Video \& Data Recording Conference",
year=1979,
address="Southampton",
month=Jul
}
@ARTICLE{MNW98,
author="Alistair Moffat and Radford Neal and Ian H. Witten",
title="Arithmetic Coding Revisited",
journal="{ACM} Transactions on Information Systems",
year=1998,
volume=16,
number=3,
pages="256--294",
month=Jul,
URL="http://www.stanford.edu/class/ee398/handouts/papers/Moffat98ArithmCoding.pdf"
}*/
static int ec_write_byte(ec_enc *_this,unsigned _value){
if(_this->offs+_this->end_offs>=_this->storage)return -1;
_this->buf[_this->offs++]=(unsigned char)_value;
return 0;
}
static int ec_write_byte_at_end(ec_enc *_this,unsigned _value){
if(_this->offs+_this->end_offs>=_this->storage)return -1;
_this->buf[_this->storage-++(_this->end_offs)]=(unsigned char)_value;
return 0;
}
/*Outputs a symbol, with a carry bit.
If there is a potential to propagate a carry over several symbols, they are
buffered until it can be determined whether or not an actual carry will
occur.
If the counter for the buffered symbols overflows, then the stream becomes
undecodable.
This gives a theoretical limit of a few billion symbols in a single packet on
32-bit systems.
The alternative is to truncate the range in order to force a carry, but
requires similar carry tracking in the decoder, needlessly slowing it down.*/
static void ec_enc_carry_out(ec_enc *_this,int _c){
if(_c!=EC_SYM_MAX){
/*No further carry propagation possible, flush buffer.*/
int carry;
carry=_c>>EC_SYM_BITS;
/*Don't output a byte on the first write.
This compare should be taken care of by branch-prediction thereafter.*/
if(_this->rem>=0)_this->error|=ec_write_byte(_this,_this->rem+carry);
if(_this->ext>0){
unsigned sym;
sym=(EC_SYM_MAX+carry)&EC_SYM_MAX;
do _this->error|=ec_write_byte(_this,sym);
while(--(_this->ext)>0);
}
_this->rem=_c&EC_SYM_MAX;
}
else _this->ext++;
}
static OPUS_INLINE void ec_enc_normalize(ec_enc *_this){
/*If the range is too small, output some bits and rescale it.*/
while(_this->rng<=EC_CODE_BOT){
ec_enc_carry_out(_this,(int)(_this->val>>EC_CODE_SHIFT));
/*Move the next-to-high-order symbol into the high-order position.*/
_this->val=(_this->val<<EC_SYM_BITS)&(EC_CODE_TOP-1);
_this->rng<<=EC_SYM_BITS;
_this->nbits_total+=EC_SYM_BITS;
}
}
void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size){
_this->buf=_buf;
_this->end_offs=0;
_this->end_window=0;
_this->nend_bits=0;
/*This is the offset from which ec_tell() will subtract partial bits.*/
_this->nbits_total=EC_CODE_BITS+1;
_this->offs=0;
_this->rng=EC_CODE_TOP;
_this->rem=-1;
_this->val=0;
_this->ext=0;
_this->storage=_size;
_this->error=0;
}
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft){
opus_uint32 r;
r=celt_udiv(_this->rng,_ft);
if(_fl>0){
_this->val+=_this->rng-IMUL32(r,(_ft-_fl));
_this->rng=IMUL32(r,(_fh-_fl));
}
else _this->rng-=IMUL32(r,(_ft-_fh));
ec_enc_normalize(_this);
}
void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits){
opus_uint32 r;
r=_this->rng>>_bits;
if(_fl>0){
_this->val+=_this->rng-IMUL32(r,((1U<<_bits)-_fl));
_this->rng=IMUL32(r,(_fh-_fl));
}
else _this->rng-=IMUL32(r,((1U<<_bits)-_fh));
ec_enc_normalize(_this);
}
/*The probability of having a "one" is 1/(1<<_logp).*/
void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp){
opus_uint32 r;
opus_uint32 s;
opus_uint32 l;
r=_this->rng;
l=_this->val;
s=r>>_logp;
r-=s;
if(_val)_this->val=l+r;
_this->rng=_val?s:r;
ec_enc_normalize(_this);
}
void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb){
opus_uint32 r;
r=_this->rng>>_ftb;
if(_s>0){
_this->val+=_this->rng-IMUL32(r,_icdf[_s-1]);
_this->rng=IMUL32(r,_icdf[_s-1]-_icdf[_s]);
}
else _this->rng-=IMUL32(r,_icdf[_s]);
ec_enc_normalize(_this);
}
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft){
unsigned ft;
unsigned fl;
int ftb;
/*In order to optimize EC_ILOG(), it is undefined for the value 0.*/
celt_assert(_ft>1);
_ft--;
ftb=EC_ILOG(_ft);
if(ftb>EC_UINT_BITS){
ftb-=EC_UINT_BITS;
ft=(_ft>>ftb)+1;
fl=(unsigned)(_fl>>ftb);
ec_encode(_this,fl,fl+1,ft);
ec_enc_bits(_this,_fl&(((opus_uint32)1<<ftb)-1U),ftb);
}
else ec_encode(_this,_fl,_fl+1,_ft+1);
}
void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _bits){
ec_window window;
int used;
window=_this->end_window;
used=_this->nend_bits;
celt_assert(_bits>0);
if(used+_bits>EC_WINDOW_SIZE){
do{
_this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
window>>=EC_SYM_BITS;
used-=EC_SYM_BITS;
}
while(used>=EC_SYM_BITS);
}
window|=(ec_window)_fl<<used;
used+=_bits;
_this->end_window=window;
_this->nend_bits=used;
_this->nbits_total+=_bits;
}
void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits){
int shift;
unsigned mask;
celt_assert(_nbits<=EC_SYM_BITS);
shift=EC_SYM_BITS-_nbits;
mask=((1<<_nbits)-1)<<shift;
if(_this->offs>0){
/*The first byte has been finalized.*/
_this->buf[0]=(unsigned char)((_this->buf[0]&~mask)|_val<<shift);
}
else if(_this->rem>=0){
/*The first byte is still awaiting carry propagation.*/
_this->rem=(_this->rem&~mask)|_val<<shift;
}
else if(_this->rng<=(EC_CODE_TOP>>_nbits)){
/*The renormalization loop has never been run.*/
_this->val=(_this->val&~((opus_uint32)mask<<EC_CODE_SHIFT))|
(opus_uint32)_val<<(EC_CODE_SHIFT+shift);
}
/*The encoder hasn't even encoded _nbits of data yet.*/
else _this->error=-1;
}
void ec_enc_shrink(ec_enc *_this,opus_uint32 _size){
celt_assert(_this->offs+_this->end_offs<=_size);
OPUS_MOVE(_this->buf+_size-_this->end_offs,
_this->buf+_this->storage-_this->end_offs,_this->end_offs);
_this->storage=_size;
}
void ec_enc_done(ec_enc *_this){
ec_window window;
int used;
opus_uint32 msk;
opus_uint32 end;
int l;
/*We output the minimum number of bits that ensures that the symbols encoded
thus far will be decoded correctly regardless of the bits that follow.*/
l=EC_CODE_BITS-EC_ILOG(_this->rng);
msk=(EC_CODE_TOP-1)>>l;
end=(_this->val+msk)&~msk;
if((end|msk)>=_this->val+_this->rng){
l++;
msk>>=1;
end=(_this->val+msk)&~msk;
}
while(l>0){
ec_enc_carry_out(_this,(int)(end>>EC_CODE_SHIFT));
end=(end<<EC_SYM_BITS)&(EC_CODE_TOP-1);
l-=EC_SYM_BITS;
}
/*If we have a buffered byte flush it into the output buffer.*/
if(_this->rem>=0||_this->ext>0)ec_enc_carry_out(_this,0);
/*If we have buffered extra bits, flush them as well.*/
window=_this->end_window;
used=_this->nend_bits;
while(used>=EC_SYM_BITS){
_this->error|=ec_write_byte_at_end(_this,(unsigned)window&EC_SYM_MAX);
window>>=EC_SYM_BITS;
used-=EC_SYM_BITS;
}
/*Clear any excess space and add any remaining extra bits to the last byte.*/
if(!_this->error){
OPUS_CLEAR(_this->buf+_this->offs,
_this->storage-_this->offs-_this->end_offs);
if(used>0){
/*If there's no range coder data at all, give up.*/
if(_this->end_offs>=_this->storage)_this->error=-1;
else{
l=-l;
/*If we've busted, don't add too many extra bits to the last byte; it
would corrupt the range coder data, and that's more important.*/
if(_this->offs+_this->end_offs>=_this->storage&&l<used){
window&=(1<<l)-1;
_this->error=-1;
}
_this->buf[_this->storage-_this->end_offs-1]|=(unsigned char)window;
}
}
}
}

View File

@@ -0,0 +1,110 @@
/* Copyright (c) 2001-2011 Timothy B. Terriberry
Copyright (c) 2008-2009 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.
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 COPYRIGHT OWNER
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.
*/
#if !defined(_entenc_H)
# define _entenc_H (1)
# include <stddef.h>
# include "entcode.h"
/*Initializes the encoder.
_buf: The buffer to store output bytes in.
_size: The size of the buffer, in chars.*/
void ec_enc_init(ec_enc *_this,unsigned char *_buf,opus_uint32 _size);
/*Encodes a symbol given its frequency information.
The frequency information must be discernable by the decoder, assuming it
has read only the previous symbols from the stream.
It is allowable to change the frequency information, or even the entire
source alphabet, so long as the decoder can tell from the context of the
previously encoded information that it is supposed to do so as well.
_fl: The cumulative frequency of all symbols that come before the one to be
encoded.
_fh: The cumulative frequency of all symbols up to and including the one to
be encoded.
Together with _fl, this defines the range [_fl,_fh) in which the
decoded value will fall.
_ft: The sum of the frequencies of all the symbols*/
void ec_encode(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _ft);
/*Equivalent to ec_encode() with _ft==1<<_bits.*/
void ec_encode_bin(ec_enc *_this,unsigned _fl,unsigned _fh,unsigned _bits);
/* Encode a bit that has a 1/(1<<_logp) probability of being a one */
void ec_enc_bit_logp(ec_enc *_this,int _val,unsigned _logp);
/*Encodes a symbol given an "inverse" CDF table.
_s: The index of the symbol to encode.
_icdf: The "inverse" CDF, such that symbol _s falls in the range
[_s>0?ft-_icdf[_s-1]:0,ft-_icdf[_s]), where ft=1<<_ftb.
The values must be monotonically non-increasing, and the last value
must be 0.
_ftb: The number of bits of precision in the cumulative distribution.*/
void ec_enc_icdf(ec_enc *_this,int _s,const unsigned char *_icdf,unsigned _ftb);
/*Encodes a raw unsigned integer in the stream.
_fl: The integer to encode.
_ft: The number of integers that can be encoded (one more than the max).
This must be at least 2, and no more than 2**32-1.*/
void ec_enc_uint(ec_enc *_this,opus_uint32 _fl,opus_uint32 _ft);
/*Encodes a sequence of raw bits in the stream.
_fl: The bits to encode.
_ftb: The number of bits to encode.
This must be between 1 and 25, inclusive.*/
void ec_enc_bits(ec_enc *_this,opus_uint32 _fl,unsigned _ftb);
/*Overwrites a few bits at the very start of an existing stream, after they
have already been encoded.
This makes it possible to have a few flags up front, where it is easy for
decoders to access them without parsing the whole stream, even if their
values are not determined until late in the encoding process, without having
to buffer all the intermediate symbols in the encoder.
In order for this to work, at least _nbits bits must have already been
encoded using probabilities that are an exact power of two.
The encoder can verify the number of encoded bits is sufficient, but cannot
check this latter condition.
_val: The bits to encode (in the least _nbits significant bits).
They will be decoded in order from most-significant to least.
_nbits: The number of bits to overwrite.
This must be no more than 8.*/
void ec_enc_patch_initial_bits(ec_enc *_this,unsigned _val,unsigned _nbits);
/*Compacts the data to fit in the target size.
This moves up the raw bits at the end of the current buffer so they are at
the end of the new buffer size.
The caller must ensure that the amount of data that's already been written
will fit in the new size.
_size: The number of bytes in the new buffer.
This must be large enough to contain the bits already written, and
must be no larger than the existing size.*/
void ec_enc_shrink(ec_enc *_this,opus_uint32 _size);
/*Indicates that there are no more symbols to encode.
All reamining output bytes are flushed to the output buffer.
ec_enc_init() must be called before the encoder can be used again.*/
void ec_enc_done(ec_enc *_this);
#endif

View File

@@ -0,0 +1,791 @@
/* Copyright (C) 2003-2008 Jean-Marc Valin
Copyright (C) 2007-2012 Xiph.Org Foundation */
/**
@file fixed_debug.h
@brief Fixed-point operations with debugging
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef FIXED_DEBUG_H
#define FIXED_DEBUG_H
#include <stdio.h>
#include "../opus_defines.h"
#ifdef CELT_C
OPUS_EXPORT opus_int64 celt_mips=0;
#else
extern opus_int64 celt_mips;
#endif
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL32(MULT16_16(SHR32((a),16),SHR((b),16)),1), SHR32(MULT16_16SU(SHR32((a),16),((b)&0x0000ffff)),15)), SHR32(MULT16_16SU(SHR32((b),16),((a)&0x0000ffff)),15))
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR32((b),16)), SHR32(MULT16_16SU((a),((b)&0x0000ffff)),16))
#define MULT16_32_P16(a,b) MULT16_32_PX(a,b,16)
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits))))
#define VERIFY_SHORT(x) ((x)<=32767&&(x)>=-32768)
#define VERIFY_INT(x) ((x)<=2147483647LL&&(x)>=-2147483648LL)
#define VERIFY_UINT(x) ((x)<=(2147483647LLU<<1))
#define SHR(a,b) SHR32(a,b)
#define PSHR(a,b) PSHR32(a,b)
/** Add two 32-bit values, ignore any overflows */
#define ADD32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
/** Subtract two 32-bit values, ignore any overflows */
#define SUB32_ovflw(a,b) (celt_mips+=2,(opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
/** Negate 32-bit value, ignore any overflows */
#define NEG32_ovflw(a) (celt_mips+=2,(opus_val32)(0-(opus_uint32)(a)))
static OPUS_INLINE short NEG16(int x)
{
int res;
if (!VERIFY_SHORT(x))
{
fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = -x;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
static OPUS_INLINE int NEG32(opus_int64 x)
{
opus_int64 res;
if (!VERIFY_INT(x))
{
fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = -x;
if (!VERIFY_INT(res))
{
fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#define EXTRACT16(x) EXTRACT16_(x, __FILE__, __LINE__)
static OPUS_INLINE short EXTRACT16_(int x, char *file, int line)
{
int res;
if (!VERIFY_SHORT(x))
{
fprintf (stderr, "EXTRACT16: input is not short: %d in %s: line %d\n", x, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = x;
celt_mips++;
return res;
}
#define EXTEND32(x) EXTEND32_(x, __FILE__, __LINE__)
static OPUS_INLINE int EXTEND32_(int x, char *file, int line)
{
int res;
if (!VERIFY_SHORT(x))
{
fprintf (stderr, "EXTEND32: input is not short: %d in %s: line %d\n", x, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = x;
celt_mips++;
return res;
}
#define SHR16(a, shift) SHR16_(a, shift, __FILE__, __LINE__)
static OPUS_INLINE short SHR16_(int a, int shift, char *file, int line)
{
int res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHR16: inputs are not short: %d >> %d in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a>>shift;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
#define SHL16(a, shift) SHL16_(a, shift, __FILE__, __LINE__)
static OPUS_INLINE short SHL16_(int a, int shift, char *file, int line)
{
int res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHL16: inputs are not short: %d %d in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a<<shift;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
static OPUS_INLINE int SHR32(opus_int64 a, int shift)
{
opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a>>shift;
if (!VERIFY_INT(res))
{
fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#define SHL32(a, shift) SHL32_(a, shift, __FILE__, __LINE__)
static OPUS_INLINE int SHL32_(opus_int64 a, int shift, char *file, int line)
{
opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
{
fprintf (stderr, "SHL32: inputs are not int: %lld %d in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a<<shift;
if (!VERIFY_INT(res))
{
fprintf (stderr, "SHL32: output is not int: %lld<<%d = %lld in %s: line %d\n", a, shift, res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((opus_val32)(1)<<((shift))>>1))),shift))
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
#define SROUND16(x,a) (celt_mips--,EXTRACT16(SATURATE(PSHR32(x,a), 32767)));
#define HALF16(x) (SHR16(x,1))
#define HALF32(x) (SHR32(x,1))
#define ADD16(a, b) ADD16_(a, b, __FILE__, __LINE__)
static OPUS_INLINE short ADD16_(int a, int b, char *file, int line)
{
int res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "ADD16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a+b;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "ADD16: output is not short: %d+%d=%d in %s: line %d\n", a,b,res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
#define SUB16(a, b) SUB16_(a, b, __FILE__, __LINE__)
static OPUS_INLINE short SUB16_(int a, int b, char *file, int line)
{
int res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "SUB16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a-b;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
#define ADD32(a, b) ADD32_(a, b, __FILE__, __LINE__)
static OPUS_INLINE int ADD32_(opus_int64 a, opus_int64 b, char *file, int line)
{
opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "ADD32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a+b;
if (!VERIFY_INT(res))
{
fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#define SUB32(a, b) SUB32_(a, b, __FILE__, __LINE__)
static OPUS_INLINE int SUB32_(opus_int64 a, opus_int64 b, char *file, int line)
{
opus_int64 res;
if (!VERIFY_INT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "SUB32: inputs are not int: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a-b;
if (!VERIFY_INT(res))
{
fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#undef UADD32
#define UADD32(a, b) UADD32_(a, b, __FILE__, __LINE__)
static OPUS_INLINE unsigned int UADD32_(opus_uint64 a, opus_uint64 b, char *file, int line)
{
opus_uint64 res;
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
{
fprintf (stderr, "UADD32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a+b;
if (!VERIFY_UINT(res))
{
fprintf (stderr, "UADD32: output is not uint32: %llu in %s: line %d\n", res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#undef USUB32
#define USUB32(a, b) USUB32_(a, b, __FILE__, __LINE__)
static OPUS_INLINE unsigned int USUB32_(opus_uint64 a, opus_uint64 b, char *file, int line)
{
opus_uint64 res;
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
{
fprintf (stderr, "USUB32: inputs are not uint32: %llu %llu in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (a<b)
{
fprintf (stderr, "USUB32: inputs underflow: %llu < %llu in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a-b;
if (!VERIFY_UINT(res))
{
fprintf (stderr, "USUB32: output is not uint32: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
/* result fits in 16 bits */
static OPUS_INLINE short MULT16_16_16(int a, int b)
{
int res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_16: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a*b;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
#define MULT16_16(a, b) MULT16_16_(a, b, __FILE__, __LINE__)
static OPUS_INLINE int MULT16_16_(int a, int b, char *file, int line)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips++;
return res;
}
#define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
#define MULT16_32_QX(a, b, Q) MULT16_32_QX_(a, b, Q, __FILE__, __LINE__)
static OPUS_INLINE int MULT16_32_QX_(int a, opus_int64 b, int Q, char *file, int line)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "MULT16_32_Q%d: inputs are not short+int: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (ABS32(b)>=((opus_val32)(1)<<(15+Q)))
{
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n", Q, (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = (((opus_int64)a)*(opus_int64)b) >> Q;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_32_Q%d: output is not int: %d*%d=%d in %s: line %d\n", Q, (int)a, (int)b,(int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (Q==15)
celt_mips+=3;
else
celt_mips+=4;
return res;
}
#define MULT16_32_PX(a, b, Q) MULT16_32_PX_(a, b, Q, __FILE__, __LINE__)
static OPUS_INLINE int MULT16_32_PX_(int a, opus_int64 b, int Q, char *file, int line)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d in %s: line %d\n\n", Q, (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (ABS32(b)>=((opus_int64)(1)<<(15+Q)))
{
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d in %s: line %d\n\n", Q, (int)a, (int)b,file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((((opus_int64)a)*(opus_int64)b) + (((opus_val32)(1)<<Q)>>1))>> Q;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d in %s: line %d\n\n", Q, (int)a, (int)b,(int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
if (Q==15)
celt_mips+=4;
else
celt_mips+=5;
return res;
}
#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
#define MAC16_32_Q16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q16((a),(b))))
static OPUS_INLINE int SATURATE(int a, int b)
{
if (a>b)
a=b;
if (a<-b)
a = -b;
celt_mips+=3;
return a;
}
static OPUS_INLINE opus_int16 SATURATE16(opus_int32 a)
{
celt_mips+=3;
if (a>32767)
return 32767;
else if (a<-32768)
return -32768;
else return a;
}
static OPUS_INLINE int MULT16_16_Q11_32(int a, int b)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res >>= 11;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_16_Q11: output is not short: %d*%d=%d\n", (int)a, (int)b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=3;
return res;
}
static OPUS_INLINE short MULT16_16_Q13(int a, int b)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res >>= 13;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_Q13: output is not short: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=3;
return res;
}
static OPUS_INLINE short MULT16_16_Q14(int a, int b)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res >>= 14;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=3;
return res;
}
#define MULT16_16_Q15(a, b) MULT16_16_Q15_(a, b, __FILE__, __LINE__)
static OPUS_INLINE short MULT16_16_Q15_(int a, int b, char *file, int line)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_Q15: inputs are not short: %d %d in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res >>= 15;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_Q15: output is not short: %d in %s: line %d\n", (int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=1;
return res;
}
static OPUS_INLINE short MULT16_16_P13(int a, int b)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res += 4096;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res >>= 13;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=4;
return res;
}
static OPUS_INLINE short MULT16_16_P14(int a, int b)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res += 8192;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res >>= 14;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=4;
return res;
}
static OPUS_INLINE short MULT16_16_P15(int a, int b)
{
opus_int64 res;
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = ((opus_int64)a)*b;
res += 16384;
if (!VERIFY_INT(res))
{
fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res >>= 15;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=2;
return res;
}
#define DIV32_16(a, b) DIV32_16_(a, b, __FILE__, __LINE__)
static OPUS_INLINE int DIV32_16_(opus_int64 a, opus_int64 b, char *file, int line)
{
opus_int64 res;
if (b==0)
{
fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
return 0;
}
if (!VERIFY_INT(a) || !VERIFY_SHORT(b))
{
fprintf (stderr, "DIV32_16: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a/b;
if (!VERIFY_SHORT(res))
{
fprintf (stderr, "DIV32_16: output is not short: %d / %d = %d in %s: line %d\n", (int)a,(int)b,(int)res, file, line);
if (res>32767)
res = 32767;
if (res<-32768)
res = -32768;
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=35;
return res;
}
#define DIV32(a, b) DIV32_(a, b, __FILE__, __LINE__)
static OPUS_INLINE int DIV32_(opus_int64 a, opus_int64 b, char *file, int line)
{
opus_int64 res;
if (b==0)
{
fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
return 0;
}
if (!VERIFY_INT(a) || !VERIFY_INT(b))
{
fprintf (stderr, "DIV32: inputs are not int/short: %d %d in %s: line %d\n", (int)a, (int)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
res = a/b;
if (!VERIFY_INT(res))
{
fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
#ifdef FIXED_DEBUG_ASSERT
celt_assert(0);
#endif
}
celt_mips+=70;
return res;
}
static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
{
x = PSHR32(x, SIG_SHIFT);
x = MAX32(x, -32768);
x = MIN32(x, 32767);
return EXTRACT16(x);
}
#define SIG2WORD16(x) (SIG2WORD16_generic(x))
#undef PRINT_MIPS
#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
#endif

View File

@@ -0,0 +1,178 @@
/* Copyright (C) 2007-2009 Xiph.Org Foundation
Copyright (C) 2003-2008 Jean-Marc Valin
Copyright (C) 2007-2008 CSIRO */
/**
@file fixed_generic.h
@brief Generic fixed-point operations
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef FIXED_GENERIC_H
#define FIXED_GENERIC_H
/** Multiply a 16-bit signed value by a 16-bit unsigned value. The result is a 32-bit signed value */
#define MULT16_16SU(a,b) ((opus_val32)(opus_val16)(a)*(opus_val32)(opus_uint16)(b))
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
#if OPUS_FAST_INT64
#define MULT16_32_Q16(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),16))
#else
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
#endif
/** 16x32 multiplication, followed by a 16-bit shift right (round-to-nearest). Results fits in 32 bits */
#if OPUS_FAST_INT64
#define MULT16_32_P16(a,b) ((opus_val32)PSHR((opus_int64)((opus_val16)(a))*(b),16))
#else
#define MULT16_32_P16(a,b) ADD32(MULT16_16((a),SHR((b),16)), PSHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
#endif
/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
#if OPUS_FAST_INT64
#define MULT16_32_Q15(a,b) ((opus_val32)SHR((opus_int64)((opus_val16)(a))*(b),15))
#else
#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15))
#endif
/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */
#if OPUS_FAST_INT64
#define MULT32_32_Q31(a,b) ((opus_val32)SHR((opus_int64)(a)*(opus_int64)(b),31))
#else
#define MULT32_32_Q31(a,b) ADD32(ADD32(SHL(MULT16_16(SHR((a),16),SHR((b),16)),1), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),15)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),15))
#endif
/** Compile-time conversion of float constant to 16-bit value */
#define QCONST16(x,bits) ((opus_val16)(.5+(x)*(((opus_val32)1)<<(bits))))
/** Compile-time conversion of float constant to 32-bit value */
#define QCONST32(x,bits) ((opus_val32)(.5+(x)*(((opus_val32)1)<<(bits))))
/** Negate a 16-bit value */
#define NEG16(x) (-(x))
/** Negate a 32-bit value */
#define NEG32(x) (-(x))
/** Change a 32-bit value into a 16-bit value. The value is assumed to fit in 16-bit, otherwise the result is undefined */
#define EXTRACT16(x) ((opus_val16)(x))
/** Change a 16-bit value into a 32-bit value */
#define EXTEND32(x) ((opus_val32)(x))
/** Arithmetic shift-right of a 16-bit value */
#define SHR16(a,shift) ((a) >> (shift))
/** Arithmetic shift-left of a 16-bit value */
#define SHL16(a,shift) ((opus_int16)((opus_uint16)(a)<<(shift)))
/** Arithmetic shift-right of a 32-bit value */
#define SHR32(a,shift) ((a) >> (shift))
/** Arithmetic shift-left of a 32-bit value */
#define SHL32(a,shift) ((opus_int32)((opus_uint32)(a)<<(shift)))
/** 32-bit arithmetic shift right with rounding-to-nearest instead of rounding down */
#define PSHR32(a,shift) (SHR32((a)+((EXTEND32(1)<<((shift))>>1)),shift))
/** 32-bit arithmetic shift right where the argument can be negative */
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
/** "RAW" macros, should not be used outside of this header file */
#define SHR(a,shift) ((a) >> (shift))
#define SHL(a,shift) SHL32(a,shift)
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
#define SATURATE16(x) (EXTRACT16((x)>32767 ? 32767 : (x)<-32768 ? -32768 : (x)))
/** Shift by a and round-to-neareast 32-bit value. Result is a 16-bit value */
#define ROUND16(x,a) (EXTRACT16(PSHR32((x),(a))))
/** Shift by a and round-to-neareast 32-bit value. Result is a saturated 16-bit value */
#define SROUND16(x,a) EXTRACT16(SATURATE(PSHR32(x,a), 32767));
/** Divide by two */
#define HALF16(x) (SHR16(x,1))
#define HALF32(x) (SHR32(x,1))
/** Add two 16-bit values */
#define ADD16(a,b) ((opus_val16)((opus_val16)(a)+(opus_val16)(b)))
/** Subtract two 16-bit values */
#define SUB16(a,b) ((opus_val16)(a)-(opus_val16)(b))
/** Add two 32-bit values */
#define ADD32(a,b) ((opus_val32)(a)+(opus_val32)(b))
/** Subtract two 32-bit values */
#define SUB32(a,b) ((opus_val32)(a)-(opus_val32)(b))
/** Add two 32-bit values, ignore any overflows */
#define ADD32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)+(opus_uint32)(b)))
/** Subtract two 32-bit values, ignore any overflows */
#define SUB32_ovflw(a,b) ((opus_val32)((opus_uint32)(a)-(opus_uint32)(b)))
/* Avoid MSVC warning C4146: unary minus operator applied to unsigned type */
/** Negate 32-bit value, ignore any overflows */
#define NEG32_ovflw(a) ((opus_val32)(0-(opus_uint32)(a)))
/** 16x16 multiplication where the result fits in 16 bits */
#define MULT16_16_16(a,b) ((((opus_val16)(a))*((opus_val16)(b))))
/* (opus_val32)(opus_val16) gives TI compiler a hint that it's 16x16->32 multiply */
/** 16x16 multiplication where the result fits in 32 bits */
#define MULT16_16(a,b) (((opus_val32)(opus_val16)(a))*((opus_val32)(opus_val16)(b)))
/** 16x16 multiply-add where the result fits in 32 bits */
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
/** 16x32 multiply, followed by a 15-bit shift right and 32-bit add.
b must fit in 31 bits.
Result fits in 32 bits. */
#define MAC16_32_Q15(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),15)), SHR(MULT16_16((a),((b)&0x00007fff)),15)))
/** 16x32 multiplication, followed by a 16-bit shift right and 32-bit add.
Results fits in 32 bits */
#define MAC16_32_Q16(c,a,b) ADD32((c),ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16)))
#define MULT16_16_Q11_32(a,b) (SHR(MULT16_16((a),(b)),11))
#define MULT16_16_Q11(a,b) (SHR(MULT16_16((a),(b)),11))
#define MULT16_16_Q13(a,b) (SHR(MULT16_16((a),(b)),13))
#define MULT16_16_Q14(a,b) (SHR(MULT16_16((a),(b)),14))
#define MULT16_16_Q15(a,b) (SHR(MULT16_16((a),(b)),15))
#define MULT16_16_P13(a,b) (SHR(ADD32(4096,MULT16_16((a),(b))),13))
#define MULT16_16_P14(a,b) (SHR(ADD32(8192,MULT16_16((a),(b))),14))
#define MULT16_16_P15(a,b) (SHR(ADD32(16384,MULT16_16((a),(b))),15))
/** Divide a 32-bit value by a 16-bit value. Result fits in 16 bits */
#define DIV32_16(a,b) ((opus_val16)(((opus_val32)(a))/((opus_val16)(b))))
/** Divide a 32-bit value by a 32-bit value. Result fits in 32 bits */
#define DIV32(a,b) (((opus_val32)(a))/((opus_val32)(b)))
#if defined(MIPSr1_ASM)
#include "mips/fixed_generic_mipsr1.h"
#endif
static OPUS_INLINE opus_val16 SIG2WORD16_generic(celt_sig x)
{
x = PSHR32(x, SIG_SHIFT);
x = MAX32(x, -32768);
x = MIN32(x, 32767);
return EXTRACT16(x);
}
#define SIG2WORD16(x) (SIG2WORD16_generic(x))
#endif

View File

@@ -0,0 +1,146 @@
/* Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com> */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/* Version 1.1 */
#ifndef FLOAT_CAST_H
#define FLOAT_CAST_H
#include "arch.h"
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
** from float to int is very slow. To meet the C specs, the code produced by
** most C compilers targeting Pentium needs to change the FPU rounding mode
** before the float to int conversion is performed.
**
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
** is this flushing of the pipeline which is so slow.
**
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
** llrint and llrintf which fix this problem as a side effect.
**
** On Unix-like systems, the configure process should have detected the
** presence of these functions. If they weren't found we have to replace them
** here with a standard C cast.
*/
/*
** The C99 prototypes for lrint and lrintf are as follows:
**
** long int lrintf (float x) ;
** long int lrint (double x) ;
*/
/* The presence of the required functions are detected during the configure
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
** the ../config.h file.
*/
/* With GCC, when SSE is available, the fastest conversion is cvtss2si. */
#if defined(__GNUC__) && defined(__SSE__)
#include <xmmintrin.h>
static OPUS_INLINE opus_int32 float2int(float x) {return _mm_cvt_ss2si(_mm_set_ss(x));}
#elif defined(HAVE_LRINTF)
/* These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
** engage them. If optimisation is enabled, these functions will be
** inlined. With optimisation switched off, you have to link in the
** maths library using -lm.
*/
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#define float2int(x) lrintf(x)
#elif (defined(HAVE_LRINT))
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#define float2int(x) lrint(x)
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && (defined(_M_X64) || (defined(_M_IX86_FP) && _M_IX86_FP >= 1))
#include <xmmintrin.h>
static __inline long int float2int(float value)
{
return _mm_cvtss_si32(_mm_load_ss(&value));
}
#elif (defined(_MSC_VER) && _MSC_VER >= 1400) && defined (_M_IX86)
#include <math.h>
/* Win32 doesn't seem to have these functions.
** Therefore implement OPUS_INLINE versions of these functions here.
*/
static __inline long int
float2int (float flt)
{ int intgr;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
#else
#if (defined(__GNUC__) && defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L)
/* supported by gcc in C99 mode, but not by all other compilers */
#warning "Don't have the functions lrint() and lrintf ()."
#warning "Replacing these functions with a standard C cast."
#endif /* __STDC_VERSION__ >= 199901L */
#include <math.h>
#define float2int(flt) ((int)(floor(.5+flt)))
#endif
#ifndef DISABLE_FLOAT_API
static OPUS_INLINE opus_int16 FLOAT2INT16(float x)
{
x = x*CELT_SIG_SCALE;
x = MAX32(x, -32768);
x = MIN32(x, 32767);
return (opus_int16)float2int(x);
}
#endif /* DISABLE_FLOAT_API */
#endif /* FLOAT_CAST_H */

View File

@@ -0,0 +1,604 @@
/*Copyright (c) 2003-2004, Mark Borgerding
Lots of modifications by Jean-Marc Valin
Copyright (c) 2005-2007, Xiph.Org Foundation
Copyright (c) 2008, Xiph.Org Foundation, CSIRO
All rights reserved.
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.
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 COPYRIGHT OWNER 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.*/
/* This code is originally from Mark Borgerding's KISS-FFT but has been
heavily modified to better suit Opus */
#ifndef SKIP_CONFIG_H
//# ifdef HAVE_CONFIG_H
# include "../config.h"
//# endif
#endif
#include "_kiss_fft_guts.h"
#include "arch.h"
#include "os_support.h"
#include "mathops.h"
#include "stack_alloc.h"
/* The guts header contains all the multiplication and addition macros that are defined for
complex numbers. It also delares the kf_ internal functions.
*/
static void kf_bfly2(
kiss_fft_cpx * Fout,
int m,
int N
)
{
kiss_fft_cpx * Fout2;
int i;
(void)m;
#ifdef CUSTOM_MODES
if (m==1)
{
celt_assert(m==1);
for (i=0;i<N;i++)
{
kiss_fft_cpx t;
Fout2 = Fout + 1;
t = *Fout2;
C_SUB( *Fout2 , *Fout , t );
C_ADDTO( *Fout , t );
Fout += 2;
}
} else
#endif
{
opus_val16 tw;
tw = QCONST16(0.7071067812f, 15);
/* We know that m==4 here because the radix-2 is just after a radix-4 */
celt_assert(m==4);
for (i=0;i<N;i++)
{
kiss_fft_cpx t;
Fout2 = Fout + 4;
t = Fout2[0];
C_SUB( Fout2[0] , Fout[0] , t );
C_ADDTO( Fout[0] , t );
t.r = S_MUL(ADD32_ovflw(Fout2[1].r, Fout2[1].i), tw);
t.i = S_MUL(SUB32_ovflw(Fout2[1].i, Fout2[1].r), tw);
C_SUB( Fout2[1] , Fout[1] , t );
C_ADDTO( Fout[1] , t );
t.r = Fout2[2].i;
t.i = -Fout2[2].r;
C_SUB( Fout2[2] , Fout[2] , t );
C_ADDTO( Fout[2] , t );
t.r = S_MUL(SUB32_ovflw(Fout2[3].i, Fout2[3].r), tw);
t.i = S_MUL(NEG32_ovflw(ADD32_ovflw(Fout2[3].i, Fout2[3].r)), tw);
C_SUB( Fout2[3] , Fout[3] , t );
C_ADDTO( Fout[3] , t );
Fout += 8;
}
}
}
static void kf_bfly4(
kiss_fft_cpx * Fout,
const size_t fstride,
const kiss_fft_state *st,
int m,
int N,
int mm
)
{
int i;
if (m==1)
{
/* Degenerate case where all the twiddles are 1. */
for (i=0;i<N;i++)
{
kiss_fft_cpx scratch0, scratch1;
C_SUB( scratch0 , *Fout, Fout[2] );
C_ADDTO(*Fout, Fout[2]);
C_ADD( scratch1 , Fout[1] , Fout[3] );
C_SUB( Fout[2], *Fout, scratch1 );
C_ADDTO( *Fout , scratch1 );
C_SUB( scratch1 , Fout[1] , Fout[3] );
Fout[1].r = ADD32_ovflw(scratch0.r, scratch1.i);
Fout[1].i = SUB32_ovflw(scratch0.i, scratch1.r);
Fout[3].r = SUB32_ovflw(scratch0.r, scratch1.i);
Fout[3].i = ADD32_ovflw(scratch0.i, scratch1.r);
Fout+=4;
}
} else {
int j;
kiss_fft_cpx scratch[6];
const kiss_twiddle_cpx *tw1,*tw2,*tw3;
const int m2=2*m;
const int m3=3*m;
kiss_fft_cpx * Fout_beg = Fout;
for (i=0;i<N;i++)
{
Fout = Fout_beg + i*mm;
tw3 = tw2 = tw1 = st->twiddles;
/* m is guaranteed to be a multiple of 4. */
for (j=0;j<m;j++)
{
C_MUL(scratch[0],Fout[m] , *tw1 );
C_MUL(scratch[1],Fout[m2] , *tw2 );
C_MUL(scratch[2],Fout[m3] , *tw3 );
C_SUB( scratch[5] , *Fout, scratch[1] );
C_ADDTO(*Fout, scratch[1]);
C_ADD( scratch[3] , scratch[0] , scratch[2] );
C_SUB( scratch[4] , scratch[0] , scratch[2] );
C_SUB( Fout[m2], *Fout, scratch[3] );
tw1 += fstride;
tw2 += fstride*2;
tw3 += fstride*3;
C_ADDTO( *Fout , scratch[3] );
Fout[m].r = ADD32_ovflw(scratch[5].r, scratch[4].i);
Fout[m].i = SUB32_ovflw(scratch[5].i, scratch[4].r);
Fout[m3].r = SUB32_ovflw(scratch[5].r, scratch[4].i);
Fout[m3].i = ADD32_ovflw(scratch[5].i, scratch[4].r);
++Fout;
}
}
}
}
#ifndef RADIX_TWO_ONLY
static void kf_bfly3(
kiss_fft_cpx * Fout,
const size_t fstride,
const kiss_fft_state *st,
int m,
int N,
int mm
)
{
int i;
size_t k;
const size_t m2 = 2*m;
const kiss_twiddle_cpx *tw1,*tw2;
kiss_fft_cpx scratch[5];
kiss_twiddle_cpx epi3;
kiss_fft_cpx * Fout_beg = Fout;
#ifdef FIXED_POINT
/*epi3.r = -16384;*/ /* Unused */
epi3.i = -28378;
#else
epi3 = st->twiddles[fstride*m];
#endif
for (i=0;i<N;i++)
{
Fout = Fout_beg + i*mm;
tw1=tw2=st->twiddles;
/* For non-custom modes, m is guaranteed to be a multiple of 4. */
k=m;
do {
C_MUL(scratch[1],Fout[m] , *tw1);
C_MUL(scratch[2],Fout[m2] , *tw2);
C_ADD(scratch[3],scratch[1],scratch[2]);
C_SUB(scratch[0],scratch[1],scratch[2]);
tw1 += fstride;
tw2 += fstride*2;
Fout[m].r = SUB32_ovflw(Fout->r, HALF_OF(scratch[3].r));
Fout[m].i = SUB32_ovflw(Fout->i, HALF_OF(scratch[3].i));
C_MULBYSCALAR( scratch[0] , epi3.i );
C_ADDTO(*Fout,scratch[3]);
Fout[m2].r = ADD32_ovflw(Fout[m].r, scratch[0].i);
Fout[m2].i = SUB32_ovflw(Fout[m].i, scratch[0].r);
Fout[m].r = SUB32_ovflw(Fout[m].r, scratch[0].i);
Fout[m].i = ADD32_ovflw(Fout[m].i, scratch[0].r);
++Fout;
} while(--k);
}
}
#ifndef OVERRIDE_kf_bfly5
static void kf_bfly5(
kiss_fft_cpx * Fout,
const size_t fstride,
const kiss_fft_state *st,
int m,
int N,
int mm
)
{
kiss_fft_cpx *Fout0,*Fout1,*Fout2,*Fout3,*Fout4;
int i, u;
kiss_fft_cpx scratch[13];
const kiss_twiddle_cpx *tw;
kiss_twiddle_cpx ya,yb;
kiss_fft_cpx * Fout_beg = Fout;
#ifdef FIXED_POINT
ya.r = 10126;
ya.i = -31164;
yb.r = -26510;
yb.i = -19261;
#else
ya = st->twiddles[fstride*m];
yb = st->twiddles[fstride*2*m];
#endif
tw=st->twiddles;
for (i=0;i<N;i++)
{
Fout = Fout_beg + i*mm;
Fout0=Fout;
Fout1=Fout0+m;
Fout2=Fout0+2*m;
Fout3=Fout0+3*m;
Fout4=Fout0+4*m;
/* For non-custom modes, m is guaranteed to be a multiple of 4. */
for ( u=0; u<m; ++u ) {
scratch[0] = *Fout0;
C_MUL(scratch[1] ,*Fout1, tw[u*fstride]);
C_MUL(scratch[2] ,*Fout2, tw[2*u*fstride]);
C_MUL(scratch[3] ,*Fout3, tw[3*u*fstride]);
C_MUL(scratch[4] ,*Fout4, tw[4*u*fstride]);
C_ADD( scratch[7],scratch[1],scratch[4]);
C_SUB( scratch[10],scratch[1],scratch[4]);
C_ADD( scratch[8],scratch[2],scratch[3]);
C_SUB( scratch[9],scratch[2],scratch[3]);
Fout0->r = ADD32_ovflw(Fout0->r, ADD32_ovflw(scratch[7].r, scratch[8].r));
Fout0->i = ADD32_ovflw(Fout0->i, ADD32_ovflw(scratch[7].i, scratch[8].i));
scratch[5].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,ya.r), S_MUL(scratch[8].r,yb.r)));
scratch[5].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,ya.r), S_MUL(scratch[8].i,yb.r)));
scratch[6].r = ADD32_ovflw(S_MUL(scratch[10].i,ya.i), S_MUL(scratch[9].i,yb.i));
scratch[6].i = NEG32_ovflw(ADD32_ovflw(S_MUL(scratch[10].r,ya.i), S_MUL(scratch[9].r,yb.i)));
C_SUB(*Fout1,scratch[5],scratch[6]);
C_ADD(*Fout4,scratch[5],scratch[6]);
scratch[11].r = ADD32_ovflw(scratch[0].r, ADD32_ovflw(S_MUL(scratch[7].r,yb.r), S_MUL(scratch[8].r,ya.r)));
scratch[11].i = ADD32_ovflw(scratch[0].i, ADD32_ovflw(S_MUL(scratch[7].i,yb.r), S_MUL(scratch[8].i,ya.r)));
scratch[12].r = SUB32_ovflw(S_MUL(scratch[9].i,ya.i), S_MUL(scratch[10].i,yb.i));
scratch[12].i = SUB32_ovflw(S_MUL(scratch[10].r,yb.i), S_MUL(scratch[9].r,ya.i));
C_ADD(*Fout2,scratch[11],scratch[12]);
C_SUB(*Fout3,scratch[11],scratch[12]);
++Fout0;++Fout1;++Fout2;++Fout3;++Fout4;
}
}
}
#endif /* OVERRIDE_kf_bfly5 */
#endif
#ifdef CUSTOM_MODES
static
void compute_bitrev_table(
int Fout,
opus_int16 *f,
const size_t fstride,
int in_stride,
opus_int16 * factors,
const kiss_fft_state *st
)
{
const int p=*factors++; /* the radix */
const int m=*factors++; /* stage's fft length/p */
/*printf ("fft %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N);*/
if (m==1)
{
int j;
for (j=0;j<p;j++)
{
*f = Fout+j;
f += fstride*in_stride;
}
} else {
int j;
for (j=0;j<p;j++)
{
compute_bitrev_table( Fout , f, fstride*p, in_stride, factors,st);
f += fstride*in_stride;
Fout += m;
}
}
}
/* facbuf is populated by p1,m1,p2,m2, ...
where
p[i] * m[i] = m[i-1]
m0 = n */
static
int kf_factor(int n,opus_int16 * facbuf)
{
int p=4;
int i;
int stages=0;
int nbak = n;
/*factor out powers of 4, powers of 2, then any remaining primes */
do {
while (n % p) {
switch (p) {
case 4: p = 2; break;
case 2: p = 3; break;
default: p += 2; break;
}
if (p>32000 || (opus_int32)p*(opus_int32)p > n)
p = n; /* no more factors, skip to end */
}
n /= p;
#ifdef RADIX_TWO_ONLY
if (p!=2 && p != 4)
#else
if (p>5)
#endif
{
return 0;
}
facbuf[2*stages] = p;
if (p==2 && stages > 1)
{
facbuf[2*stages] = 4;
facbuf[2] = 2;
}
stages++;
} while (n > 1);
n = nbak;
/* Reverse the order to get the radix 4 at the end, so we can use the
fast degenerate case. It turns out that reversing the order also
improves the noise behaviour. */
for (i=0;i<stages/2;i++)
{
int tmp;
tmp = facbuf[2*i];
facbuf[2*i] = facbuf[2*(stages-i-1)];
facbuf[2*(stages-i-1)] = tmp;
}
for (i=0;i<stages;i++)
{
n /= facbuf[2*i];
facbuf[2*i+1] = n;
}
return 1;
}
static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
{
int i;
#ifdef FIXED_POINT
for (i=0;i<nfft;++i) {
opus_val32 phase = -i;
kf_cexp2(twiddles+i, DIV32(SHL32(phase,17),nfft));
}
#else
for (i=0;i<nfft;++i) {
const double pi=3.14159265358979323846264338327;
double phase = ( -2*pi /nfft ) * i;
kf_cexp(twiddles+i, phase );
}
#endif
}
int opus_fft_alloc_arch_c(kiss_fft_state *st) {
(void)st;
return 0;
}
/*
*
* Allocates all necessary storage space for the fft and ifft.
* The return value is a contiguous block of memory. As such,
* It can be freed with free().
* */
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem,
const kiss_fft_state *base, int arch)
{
kiss_fft_state *st=NULL;
size_t memneeded = sizeof(struct kiss_fft_state); /* twiddle factors*/
if ( lenmem==NULL ) {
st = ( kiss_fft_state*)KISS_FFT_MALLOC( memneeded );
}else{
if (mem != NULL && *lenmem >= memneeded)
st = (kiss_fft_state*)mem;
*lenmem = memneeded;
}
if (st) {
opus_int16 *bitrev;
kiss_twiddle_cpx *twiddles;
st->nfft=nfft;
#ifdef FIXED_POINT
st->scale_shift = celt_ilog2(st->nfft);
if (st->nfft == 1<<st->scale_shift)
st->scale = Q15ONE;
else
st->scale = (1073741824+st->nfft/2)/st->nfft>>(15-st->scale_shift);
#else
st->scale = 1.f/nfft;
#endif
if (base != NULL)
{
st->twiddles = base->twiddles;
st->shift = 0;
while (st->shift < 32 && nfft<<st->shift != base->nfft)
st->shift++;
if (st->shift>=32)
goto fail;
} else {
st->twiddles = twiddles = (kiss_twiddle_cpx*)KISS_FFT_MALLOC(sizeof(kiss_twiddle_cpx)*nfft);
compute_twiddles(twiddles, nfft);
st->shift = -1;
}
if (!kf_factor(nfft,st->factors))
{
goto fail;
}
/* bitrev */
st->bitrev = bitrev = (opus_int16*)KISS_FFT_MALLOC(sizeof(opus_int16)*nfft);
if (st->bitrev==NULL)
goto fail;
compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
/* Initialize architecture specific fft parameters */
if (opus_fft_alloc_arch(st, arch))
goto fail;
}
return st;
fail:
opus_fft_free(st, arch);
return NULL;
}
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch)
{
return opus_fft_alloc_twiddles(nfft, mem, lenmem, NULL, arch);
}
void opus_fft_free_arch_c(kiss_fft_state *st) {
(void)st;
}
void opus_fft_free(const kiss_fft_state *cfg, int arch)
{
if (cfg)
{
opus_fft_free_arch((kiss_fft_state *)cfg, arch);
opus_free((opus_int16*)cfg->bitrev);
if (cfg->shift < 0)
opus_free((kiss_twiddle_cpx*)cfg->twiddles);
opus_free((kiss_fft_state*)cfg);
}
}
#endif /* CUSTOM_MODES */
void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout)
{
int m2, m;
int p;
int L;
int fstride[MAXFACTORS];
int i;
int shift;
/* st->shift can be -1 */
shift = st->shift>0 ? st->shift : 0;
fstride[0] = 1;
L=0;
do {
p = st->factors[2*L];
m = st->factors[2*L+1];
fstride[L+1] = fstride[L]*p;
L++;
} while(m!=1);
m = st->factors[2*L-1];
for (i=L-1;i>=0;i--)
{
if (i!=0)
m2 = st->factors[2*i-1];
else
m2 = 1;
switch (st->factors[2*i])
{
case 2:
kf_bfly2(fout, m, fstride[i]);
break;
case 4:
kf_bfly4(fout,fstride[i]<<shift,st,m, fstride[i], m2);
break;
#ifndef RADIX_TWO_ONLY
case 3:
kf_bfly3(fout,fstride[i]<<shift,st,m, fstride[i], m2);
break;
case 5:
kf_bfly5(fout,fstride[i]<<shift,st,m, fstride[i], m2);
break;
#endif
}
m = m2;
}
}
void opus_fft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
{
int i;
opus_val16 scale;
#ifdef FIXED_POINT
/* Allows us to scale with MULT16_32_Q16(), which is faster than
MULT16_32_Q15() on ARM. */
int scale_shift = st->scale_shift-1;
#endif
scale = st->scale;
celt_assert2 (fin != fout, "In-place FFT not supported");
/* Bit-reverse the input */
for (i=0;i<st->nfft;i++)
{
kiss_fft_cpx x = fin[i];
fout[st->bitrev[i]].r = SHR32(MULT16_32_Q16(scale, x.r), scale_shift);
fout[st->bitrev[i]].i = SHR32(MULT16_32_Q16(scale, x.i), scale_shift);
}
opus_fft_impl(st, fout);
}
void opus_ifft_c(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
{
int i;
celt_assert2 (fin != fout, "In-place FFT not supported");
/* Bit-reverse the input */
for (i=0;i<st->nfft;i++)
fout[st->bitrev[i]] = fin[i];
for (i=0;i<st->nfft;i++)
fout[i].i = -fout[i].i;
opus_fft_impl(st, fout);
for (i=0;i<st->nfft;i++)
fout[i].i = -fout[i].i;
}

View File

@@ -0,0 +1,200 @@
/*Copyright (c) 2003-2004, Mark Borgerding
Lots of modifications by Jean-Marc Valin
Copyright (c) 2005-2007, Xiph.Org Foundation
Copyright (c) 2008, Xiph.Org Foundation, CSIRO
All rights reserved.
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.
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 COPYRIGHT OWNER 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.*/
#ifndef KISS_FFT_H
#define KISS_FFT_H
#include <stdlib.h>
#include <math.h>
#include "arch.h"
#include "cpu_support.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef USE_SIMD
# include <xmmintrin.h>
# define kiss_fft_scalar __m128
#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
#else
#define KISS_FFT_MALLOC opus_alloc
#endif
#ifdef FIXED_POINT
#include "arch.h"
# define kiss_fft_scalar opus_int32
# define kiss_twiddle_scalar opus_int16
#else
# ifndef kiss_fft_scalar
/* default is float */
# define kiss_fft_scalar float
# define kiss_twiddle_scalar float
# define KF_SUFFIX _celt_single
# endif
#endif
typedef struct {
kiss_fft_scalar r;
kiss_fft_scalar i;
}kiss_fft_cpx;
typedef struct {
kiss_twiddle_scalar r;
kiss_twiddle_scalar i;
}kiss_twiddle_cpx;
#define MAXFACTORS 8
/* e.g. an fft of length 128 has 4 factors
as far as kissfft is concerned
4*4*4*2
*/
typedef struct arch_fft_state{
int is_supported;
void *priv;
} arch_fft_state;
typedef struct kiss_fft_state{
int nfft;
opus_val16 scale;
#ifdef FIXED_POINT
int scale_shift;
#endif
int shift;
opus_int16 factors[2*MAXFACTORS];
const opus_int16 *bitrev;
const kiss_twiddle_cpx *twiddles;
arch_fft_state *arch_fft;
} kiss_fft_state;
#if defined(HAVE_ARM_NE10)
#include "arm/fft_arm.h"
#endif
/*typedef struct kiss_fft_state* kiss_fft_cfg;*/
/**
* opus_fft_alloc
*
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
*
* typical usage: kiss_fft_cfg mycfg=opus_fft_alloc(1024,0,NULL,NULL);
*
* The return value from fft_alloc is a cfg buffer used internally
* by the fft routine or NULL.
*
* If lenmem is NULL, then opus_fft_alloc will allocate a cfg buffer using malloc.
* The returned value should be free()d when done to avoid memory leaks.
*
* The state can be placed in a user supplied buffer 'mem':
* If lenmem is not NULL and mem is not NULL and *lenmem is large enough,
* then the function places the cfg in mem and the size used in *lenmem
* and returns mem.
*
* If lenmem is not NULL and ( mem is NULL or *lenmem is not large enough),
* then the function returns NULL and places the minimum cfg
* buffer size in *lenmem.
* */
kiss_fft_state *opus_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base, int arch);
kiss_fft_state *opus_fft_alloc(int nfft,void * mem,size_t * lenmem, int arch);
/**
* opus_fft(cfg,in_out_buf)
*
* Perform an FFT on a complex input buffer.
* for a forward FFT,
* fin should be f[0] , f[1] , ... ,f[nfft-1]
* fout will be F[0] , F[1] , ... ,F[nfft-1]
* Note that each element is complex and can be accessed like
f[k].r and f[k].i
* */
void opus_fft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
void opus_ifft_c(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
void opus_fft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout);
void opus_ifft_impl(const kiss_fft_state *st,kiss_fft_cpx *fout);
void opus_fft_free(const kiss_fft_state *cfg, int arch);
void opus_fft_free_arch_c(kiss_fft_state *st);
int opus_fft_alloc_arch_c(kiss_fft_state *st);
#if !defined(OVERRIDE_OPUS_FFT)
/* Is run-time CPU detection enabled on this platform? */
#if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10))
extern int (*const OPUS_FFT_ALLOC_ARCH_IMPL[OPUS_ARCHMASK+1])(
kiss_fft_state *st);
#define opus_fft_alloc_arch(_st, arch) \
((*OPUS_FFT_ALLOC_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st))
extern void (*const OPUS_FFT_FREE_ARCH_IMPL[OPUS_ARCHMASK+1])(
kiss_fft_state *st);
#define opus_fft_free_arch(_st, arch) \
((*OPUS_FFT_FREE_ARCH_IMPL[(arch)&OPUS_ARCHMASK])(_st))
extern void (*const OPUS_FFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
const kiss_fft_cpx *fin, kiss_fft_cpx *fout);
#define opus_fft(_cfg, _fin, _fout, arch) \
((*OPUS_FFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout))
extern void (*const OPUS_IFFT[OPUS_ARCHMASK+1])(const kiss_fft_state *cfg,
const kiss_fft_cpx *fin, kiss_fft_cpx *fout);
#define opus_ifft(_cfg, _fin, _fout, arch) \
((*OPUS_IFFT[(arch)&OPUS_ARCHMASK])(_cfg, _fin, _fout))
#else /* else for if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */
#define opus_fft_alloc_arch(_st, arch) \
((void)(arch), opus_fft_alloc_arch_c(_st))
#define opus_fft_free_arch(_st, arch) \
((void)(arch), opus_fft_free_arch_c(_st))
#define opus_fft(_cfg, _fin, _fout, arch) \
((void)(arch), opus_fft_c(_cfg, _fin, _fout))
#define opus_ifft(_cfg, _fin, _fout, arch) \
((void)(arch), opus_ifft_c(_cfg, _fin, _fout))
#endif /* end if defined(OPUS_HAVE_RTCD) && (defined(HAVE_ARM_NE10)) */
#endif /* end if !defined(OVERRIDE_OPUS_FFT) */
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,134 @@
/* Copyright (c) 2007 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "laplace.h"
#include "mathops.h"
/* The minimum probability of an energy delta (out of 32768). */
#define LAPLACE_LOG_MINP (0)
#define LAPLACE_MINP (1<<LAPLACE_LOG_MINP)
/* The minimum number of guaranteed representable energy deltas (in one
direction). */
#define LAPLACE_NMIN (16)
/* When called, decay is positive and at most 11456. */
static unsigned ec_laplace_get_freq1(unsigned fs0, int decay)
{
unsigned ft;
ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN) - fs0;
return ft*(opus_int32)(16384-decay)>>15;
}
void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay)
{
unsigned fl;
int val = *value;
fl = 0;
if (val)
{
int s;
int i;
s = -(val<0);
val = (val+s)^s;
fl = fs;
fs = ec_laplace_get_freq1(fs, decay);
/* Search the decaying part of the PDF.*/
for (i=1; fs > 0 && i < val; i++)
{
fs *= 2;
fl += fs+2*LAPLACE_MINP;
fs = (fs*(opus_int32)decay)>>15;
}
/* Everything beyond that has probability LAPLACE_MINP. */
if (!fs)
{
int di;
int ndi_max;
ndi_max = (32768-fl+LAPLACE_MINP-1)>>LAPLACE_LOG_MINP;
ndi_max = (ndi_max-s)>>1;
di = IMIN(val - i, ndi_max - 1);
fl += (2*di+1+s)*LAPLACE_MINP;
fs = IMIN(LAPLACE_MINP, 32768-fl);
*value = (i+di+s)^s;
}
else
{
fs += LAPLACE_MINP;
fl += fs&~s;
}
celt_assert(fl+fs<=32768);
celt_assert(fs>0);
}
ec_encode_bin(enc, fl, fl+fs, 15);
}
int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay)
{
int val=0;
unsigned fl;
unsigned fm;
fm = ec_decode_bin(dec, 15);
fl = 0;
if (fm >= fs)
{
val++;
fl = fs;
fs = ec_laplace_get_freq1(fs, decay)+LAPLACE_MINP;
/* Search the decaying part of the PDF.*/
while(fs > LAPLACE_MINP && fm >= fl+2*fs)
{
fs *= 2;
fl += fs;
fs = ((fs-2*LAPLACE_MINP)*(opus_int32)decay)>>15;
fs += LAPLACE_MINP;
val++;
}
/* Everything beyond that has probability LAPLACE_MINP. */
if (fs <= LAPLACE_MINP)
{
int di;
di = (fm-fl)>>(LAPLACE_LOG_MINP+1);
val += di;
fl += 2*di*LAPLACE_MINP;
}
if (fm < fl+fs)
val = -val;
else
fl += fs;
}
celt_assert(fl<32768);
celt_assert(fs>0);
celt_assert(fl<=fm);
celt_assert(fm<IMIN(fl+fs,32768));
ec_dec_update(dec, fl, IMIN(fl+fs,32768), 32768);
return val;
}

View File

@@ -0,0 +1,48 @@
/* Copyright (c) 2007 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#include "entenc.h"
#include "entdec.h"
/** Encode a value that is assumed to be the realisation of a
Laplace-distributed random process
@param enc Entropy encoder state
@param value Value to encode
@param fs Probability of 0, multiplied by 32768
@param decay Probability of the value +/- 1, multiplied by 16384
*/
void ec_laplace_encode(ec_enc *enc, int *value, unsigned fs, int decay);
/** Decode a value that is assumed to be the realisation of a
Laplace-distributed random process
@param dec Entropy decoder state
@param fs Probability of 0, multiplied by 32768
@param decay Probability of the value +/- 1, multiplied by 16384
@return Value decoded
*/
int ec_laplace_decode(ec_dec *dec, unsigned fs, int decay);

View File

@@ -0,0 +1,209 @@
/* Copyright (c) 2002-2008 Jean-Marc Valin
Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/**
@file mathops.h
@brief Various math functions
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "mathops.h"
/*Compute floor(sqrt(_val)) with exact arithmetic.
_val must be greater than 0.
This has been tested on all possible 32-bit inputs greater than 0.*/
unsigned isqrt32(opus_uint32 _val){
unsigned b;
unsigned g;
int bshift;
/*Uses the second method from
http://www.azillionmonkeys.com/qed/sqroot.html
The main idea is to search for the largest binary digit b such that
(g+b)*(g+b) <= _val, and add it to the solution g.*/
g=0;
bshift=(EC_ILOG(_val)-1)>>1;
b=1U<<bshift;
do{
opus_uint32 t;
t=(((opus_uint32)g<<1)+b)<<bshift;
if(t<=_val){
g+=b;
_val-=t;
}
b>>=1;
bshift--;
}
while(bshift>=0);
return g;
}
#ifdef FIXED_POINT
opus_val32 frac_div32(opus_val32 a, opus_val32 b)
{
opus_val16 rcp;
opus_val32 result, rem;
int shift = celt_ilog2(b)-29;
a = VSHR32(a,shift);
b = VSHR32(b,shift);
/* 16-bit reciprocal */
rcp = ROUND16(celt_rcp(ROUND16(b,16)),3);
result = MULT16_32_Q15(rcp, a);
rem = PSHR32(a,2)-MULT32_32_Q31(result, b);
result = ADD32(result, SHL32(MULT16_32_Q15(rcp, rem),2));
if (result >= 536870912) /* 2^29 */
return 2147483647; /* 2^31 - 1 */
else if (result <= -536870912) /* -2^29 */
return -2147483647; /* -2^31 */
else
return SHL32(result, 2);
}
/** Reciprocal sqrt approximation in the range [0.25,1) (Q16 in, Q14 out) */
opus_val16 celt_rsqrt_norm(opus_val32 x)
{
opus_val16 n;
opus_val16 r;
opus_val16 r2;
opus_val16 y;
/* Range of n is [-16384,32767] ([-0.5,1) in Q15). */
n = x-32768;
/* Get a rough initial guess for the root.
The optimal minimax quadratic approximation (using relative error) is
r = 1.437799046117536+n*(-0.823394375837328+n*0.4096419668459485).
Coefficients here, and the final result r, are Q14.*/
r = ADD16(23557, MULT16_16_Q15(n, ADD16(-13490, MULT16_16_Q15(n, 6713))));
/* We want y = x*r*r-1 in Q15, but x is 32-bit Q16 and r is Q14.
We can compute the result from n and r using Q15 multiplies with some
adjustment, carefully done to avoid overflow.
Range of y is [-1564,1594]. */
r2 = MULT16_16_Q15(r, r);
y = SHL16(SUB16(ADD16(MULT16_16_Q15(r2, n), r2), 16384), 1);
/* Apply a 2nd-order Householder iteration: r += r*y*(y*0.375-0.5).
This yields the Q14 reciprocal square root of the Q16 x, with a maximum
relative error of 1.04956E-4, a (relative) RMSE of 2.80979E-5, and a
peak absolute error of 2.26591/16384. */
return ADD16(r, MULT16_16_Q15(r, MULT16_16_Q15(y,
SUB16(MULT16_16_Q15(y, 12288), 16384))));
}
/** Sqrt approximation (QX input, QX/2 output) */
opus_val32 celt_sqrt(opus_val32 x)
{
int k;
opus_val16 n;
opus_val32 rt;
static const opus_val16 C[5] = {23175, 11561, -3011, 1699, -664};
if (x==0)
return 0;
else if (x>=1073741824)
return 32767;
k = (celt_ilog2(x)>>1)-7;
x = VSHR32(x, 2*k);
n = x-32768;
rt = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2],
MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, (C[4])))))))));
rt = VSHR32(rt,7-k);
return rt;
}
#define L1 32767
#define L2 -7651
#define L3 8277
#define L4 -626
static OPUS_INLINE opus_val16 _celt_cos_pi_2(opus_val16 x)
{
opus_val16 x2;
x2 = MULT16_16_P15(x,x);
return ADD16(1,MIN16(32766,ADD32(SUB16(L1,x2), MULT16_16_P15(x2, ADD32(L2, MULT16_16_P15(x2, ADD32(L3, MULT16_16_P15(L4, x2
))))))));
}
#undef L1
#undef L2
#undef L3
#undef L4
opus_val16 celt_cos_norm(opus_val32 x)
{
x = x&0x0001ffff;
if (x>SHL32(EXTEND32(1), 16))
x = SUB32(SHL32(EXTEND32(1), 17),x);
if (x&0x00007fff)
{
if (x<SHL32(EXTEND32(1), 15))
{
return _celt_cos_pi_2(EXTRACT16(x));
} else {
return NEG16(_celt_cos_pi_2(EXTRACT16(65536-x)));
}
} else {
if (x&0x0000ffff)
return 0;
else if (x&0x0001ffff)
return -32767;
else
return 32767;
}
}
/** Reciprocal approximation (Q15 input, Q16 output) */
opus_val32 celt_rcp(opus_val32 x)
{
int i;
opus_val16 n;
opus_val16 r;
celt_sig_assert(x>0);
i = celt_ilog2(x);
/* n is Q15 with range [0,1). */
n = VSHR32(x,i-15)-32768;
/* Start with a linear approximation:
r = 1.8823529411764706-0.9411764705882353*n.
The coefficients and the result are Q14 in the range [15420,30840].*/
r = ADD16(30840, MULT16_16_Q15(-15420, n));
/* Perform two Newton iterations:
r -= r*((r*n)-1.Q15)
= r*((r*n)+(r-1.Q15)). */
r = SUB16(r, MULT16_16_Q15(r,
ADD16(MULT16_16_Q15(r, n), ADD16(r, -32768))));
/* We subtract an extra 1 in the second iteration to avoid overflow; it also
neatly compensates for truncation error in the rest of the process. */
r = SUB16(r, ADD16(1, MULT16_16_Q15(r,
ADD16(MULT16_16_Q15(r, n), ADD16(r, -32768)))));
/* r is now the Q15 solution to 2/(n+1), with a maximum relative error
of 7.05346E-5, a (relative) RMSE of 2.14418E-5, and a peak absolute
error of 1.24665/32768. */
return VSHR32(EXTEND32(r),i-16);
}
#endif

View File

@@ -0,0 +1,290 @@
/* Copyright (c) 2002-2008 Jean-Marc Valin
Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/**
@file mathops.h
@brief Various math functions
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef MATHOPS_H
#define MATHOPS_H
#include "arch.h"
#include "entcode.h"
#include "os_support.h"
#define PI 3.141592653f
/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
#define FRAC_MUL16(a,b) ((16384+((opus_int32)(opus_int16)(a)*(opus_int16)(b)))>>15)
unsigned isqrt32(opus_uint32 _val);
/* CELT doesn't need it for fixed-point, by analysis.c does. */
#if !defined(FIXED_POINT) || defined(ANALYSIS_C)
#define cA 0.43157974f
#define cB 0.67848403f
#define cC 0.08595542f
#define cE ((float)PI/2)
static OPUS_INLINE float fast_atan2f(float y, float x) {
float x2, y2;
x2 = x*x;
y2 = y*y;
/* For very small values, we don't care about the answer, so
we can just return 0. */
if (x2 + y2 < 1e-18f)
{
return 0;
}
if(x2<y2){
float den = (y2 + cB*x2) * (y2 + cC*x2);
return -x*y*(y2 + cA*x2) / den + (y<0 ? -cE : cE);
}else{
float den = (x2 + cB*y2) * (x2 + cC*y2);
return x*y*(x2 + cA*y2) / den + (y<0 ? -cE : cE) - (x*y<0 ? -cE : cE);
}
}
#undef cA
#undef cB
#undef cC
#undef cE
#endif
#ifndef OVERRIDE_CELT_MAXABS16
static OPUS_INLINE opus_val32 celt_maxabs16(const opus_val16 *x, int len)
{
int i;
opus_val16 maxval = 0;
opus_val16 minval = 0;
for (i=0;i<len;i++)
{
maxval = MAX16(maxval, x[i]);
minval = MIN16(minval, x[i]);
}
return MAX32(EXTEND32(maxval),-EXTEND32(minval));
}
#endif
#ifndef OVERRIDE_CELT_MAXABS32
#ifdef FIXED_POINT
static OPUS_INLINE opus_val32 celt_maxabs32(const opus_val32 *x, int len)
{
int i;
opus_val32 maxval = 0;
opus_val32 minval = 0;
for (i=0;i<len;i++)
{
maxval = MAX32(maxval, x[i]);
minval = MIN32(minval, x[i]);
}
return MAX32(maxval, -minval);
}
#else
#define celt_maxabs32(x,len) celt_maxabs16(x,len)
#endif
#endif
#ifndef FIXED_POINT
#define celt_sqrt(x) ((float)sqrt(x))
#define celt_rsqrt(x) (1.f/celt_sqrt(x))
#define celt_rsqrt_norm(x) (celt_rsqrt(x))
#define celt_cos_norm(x) ((float)cos((.5f*PI)*(x)))
#define celt_rcp(x) (1.f/(x))
#define celt_div(a,b) ((a)/(b))
#define frac_div32(a,b) ((float)(a)/(b))
#ifdef FLOAT_APPROX
/* Note: This assumes radix-2 floating point with the exponent at bits 23..30 and an offset of 127
denorm, +/- inf and NaN are *not* handled */
/** Base-2 log approximation (log2(x)). */
static OPUS_INLINE float celt_log2(float x)
{
int integer;
float frac;
union {
float f;
opus_uint32 i;
} in;
in.f = x;
integer = (in.i>>23)-127;
in.i -= integer<<23;
frac = in.f - 1.5f;
frac = -0.41445418f + frac*(0.95909232f
+ frac*(-0.33951290f + frac*0.16541097f));
return 1+integer+frac;
}
/** Base-2 exponential approximation (2^x). */
static OPUS_INLINE float celt_exp2(float x)
{
int integer;
float frac;
union {
float f;
opus_uint32 i;
} res;
integer = floor(x);
if (integer < -50)
return 0;
frac = x-integer;
/* K0 = 1, K1 = log(2), K2 = 3-4*log(2), K3 = 3*log(2) - 2 */
res.f = 0.99992522f + frac * (0.69583354f
+ frac * (0.22606716f + 0.078024523f*frac));
res.i = (res.i + (integer<<23)) & 0x7fffffff;
return res.f;
}
#else
#define celt_log2(x) ((float)(1.442695040888963387*log(x)))
#define celt_exp2(x) ((float)exp(0.6931471805599453094*(x)))
#endif
#endif
#ifdef FIXED_POINT
#include "os_support.h"
#ifndef OVERRIDE_CELT_ILOG2
/** Integer log in base2. Undefined for zero and negative numbers */
static OPUS_INLINE opus_int16 celt_ilog2(opus_int32 x)
{
celt_sig_assert(x>0);
return EC_ILOG(x)-1;
}
#endif
/** Integer log in base2. Defined for zero, but not for negative numbers */
static OPUS_INLINE opus_int16 celt_zlog2(opus_val32 x)
{
return x <= 0 ? 0 : celt_ilog2(x);
}
opus_val16 celt_rsqrt_norm(opus_val32 x);
opus_val32 celt_sqrt(opus_val32 x);
opus_val16 celt_cos_norm(opus_val32 x);
/** Base-2 logarithm approximation (log2(x)). (Q14 input, Q10 output) */
static OPUS_INLINE opus_val16 celt_log2(opus_val32 x)
{
int i;
opus_val16 n, frac;
/* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
0.15530808010959576, -0.08556153059057618 */
static const opus_val16 C[5] = {-6801+(1<<(13-DB_SHIFT)), 15746, -5217, 2545, -1401};
if (x==0)
return -32767;
i = celt_ilog2(x);
n = VSHR32(x,i-15)-32768-16384;
frac = ADD16(C[0], MULT16_16_Q15(n, ADD16(C[1], MULT16_16_Q15(n, ADD16(C[2], MULT16_16_Q15(n, ADD16(C[3], MULT16_16_Q15(n, C[4]))))))));
return SHL16(i-13,DB_SHIFT)+SHR16(frac,14-DB_SHIFT);
}
/*
K0 = 1
K1 = log(2)
K2 = 3-4*log(2)
K3 = 3*log(2) - 2
*/
#define D0 16383
#define D1 22804
#define D2 14819
#define D3 10204
static OPUS_INLINE opus_val32 celt_exp2_frac(opus_val16 x)
{
opus_val16 frac;
frac = SHL16(x, 4);
return ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
}
/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
static OPUS_INLINE opus_val32 celt_exp2(opus_val16 x)
{
int integer;
opus_val16 frac;
integer = SHR16(x,10);
if (integer>14)
return 0x7f000000;
else if (integer < -15)
return 0;
frac = celt_exp2_frac(x-SHL16(integer,10));
return VSHR32(EXTEND32(frac), -integer-2);
}
opus_val32 celt_rcp(opus_val32 x);
#define celt_div(a,b) MULT32_32_Q31((opus_val32)(a),celt_rcp(b))
opus_val32 frac_div32(opus_val32 a, opus_val32 b);
#define M1 32767
#define M2 -21
#define M3 -11943
#define M4 4936
/* Atan approximation using a 4th order polynomial. Input is in Q15 format
and normalized by pi/4. Output is in Q15 format */
static OPUS_INLINE opus_val16 celt_atan01(opus_val16 x)
{
return MULT16_16_P15(x, ADD32(M1, MULT16_16_P15(x, ADD32(M2, MULT16_16_P15(x, ADD32(M3, MULT16_16_P15(M4, x)))))));
}
#undef M1
#undef M2
#undef M3
#undef M4
/* atan2() approximation valid for positive input values */
static OPUS_INLINE opus_val16 celt_atan2p(opus_val16 y, opus_val16 x)
{
if (y < x)
{
opus_val32 arg;
arg = celt_div(SHL32(EXTEND32(y),15),x);
if (arg >= 32767)
arg = 32767;
return SHR16(celt_atan01(EXTRACT16(arg)),1);
} else {
opus_val32 arg;
arg = celt_div(SHL32(EXTEND32(x),15),y);
if (arg >= 32767)
arg = 32767;
return 25736-SHR16(celt_atan01(EXTRACT16(arg)),1);
}
}
#endif /* FIXED_POINT */
#endif /* MATHOPS_H */

View File

@@ -0,0 +1,343 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2008 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/* This is a simple MDCT implementation that uses a N/4 complex FFT
to do most of the work. It should be relatively straightforward to
plug in pretty much and FFT here.
This replaces the Vorbis FFT (and uses the exact same API), which
was a bit too messy and that was ending up duplicating code
(might as well use the same FFT everywhere).
The algorithm is similar to (and inspired from) Fabrice Bellard's
MDCT implementation in FFMPEG, but has differences in signs, ordering
and scaling in many places.
*/
#ifndef SKIP_CONFIG_H
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#endif
#include "mdct.h"
#include "kiss_fft.h"
#include "_kiss_fft_guts.h"
#include <math.h>
#include "os_support.h"
#include "mathops.h"
#include "stack_alloc.h"
#if defined(MIPSr1_ASM)
#include "mips/mdct_mipsr1.h"
#endif
#ifdef CUSTOM_MODES
int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch)
{
int i;
kiss_twiddle_scalar *trig;
int shift;
int N2=N>>1;
l->n = N;
l->maxshift = maxshift;
for (i=0;i<=maxshift;i++)
{
if (i==0)
l->kfft[i] = opus_fft_alloc(N>>2>>i, 0, 0, arch);
else
l->kfft[i] = opus_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0], arch);
#ifndef ENABLE_TI_DSPLIB55
if (l->kfft[i]==NULL)
return 0;
#endif
}
l->trig = trig = (kiss_twiddle_scalar*)opus_alloc((N-(N2>>maxshift))*sizeof(kiss_twiddle_scalar));
if (l->trig==NULL)
return 0;
for (shift=0;shift<=maxshift;shift++)
{
/* We have enough points that sine isn't necessary */
#if defined(FIXED_POINT)
#if 1
for (i=0;i<N2;i++)
trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2+16384),N));
#else
for (i=0;i<N2;i++)
trig[i] = (kiss_twiddle_scalar)MAX32(-32767,MIN32(32767,floor(.5+32768*cos(2*M_PI*(i+.125)/N))));
#endif
#else
for (i=0;i<N2;i++)
trig[i] = (kiss_twiddle_scalar)cos(2*PI*(i+.125)/N);
#endif
trig += N2;
N2 >>= 1;
N >>= 1;
}
return 1;
}
void clt_mdct_clear(mdct_lookup *l, int arch)
{
int i;
for (i=0;i<=l->maxshift;i++)
opus_fft_free(l->kfft[i], arch);
opus_free((kiss_twiddle_scalar*)l->trig);
}
#endif /* CUSTOM_MODES */
/* Forward MDCT trashes the input array */
#ifndef OVERRIDE_clt_mdct_forward
void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap, int shift, int stride, int arch)
{
int i;
int N, N2, N4;
VARDECL(kiss_fft_scalar, f);
VARDECL(kiss_fft_cpx, f2);
const kiss_fft_state *st = l->kfft[shift];
const kiss_twiddle_scalar *trig;
opus_val16 scale;
#ifdef FIXED_POINT
/* Allows us to scale with MULT16_32_Q16(), which is faster than
MULT16_32_Q15() on ARM. */
int scale_shift = st->scale_shift-1;
#endif
SAVE_STACK;
(void)arch;
scale = st->scale;
N = l->n;
trig = l->trig;
for (i=0;i<shift;i++)
{
N >>= 1;
trig += N;
}
N2 = N>>1;
N4 = N>>2;
ALLOC(f, N2, kiss_fft_scalar);
ALLOC(f2, N4, kiss_fft_cpx);
/* Consider the input to be composed of four blocks: [a, b, c, d] */
/* Window, shuffle, fold */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in+(overlap>>1);
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+N2-1+(overlap>>1);
kiss_fft_scalar * OPUS_RESTRICT yp = f;
const opus_val16 * OPUS_RESTRICT wp1 = window+(overlap>>1);
const opus_val16 * OPUS_RESTRICT wp2 = window+(overlap>>1)-1;
for(i=0;i<((overlap+3)>>2);i++)
{
/* Real part arranged as -d-cR, Imag part arranged as -b+aR*/
*yp++ = MULT16_32_Q15(*wp2, xp1[N2]) + MULT16_32_Q15(*wp1,*xp2);
*yp++ = MULT16_32_Q15(*wp1, *xp1) - MULT16_32_Q15(*wp2, xp2[-N2]);
xp1+=2;
xp2-=2;
wp1+=2;
wp2-=2;
}
wp1 = window;
wp2 = window+overlap-1;
for(;i<N4-((overlap+3)>>2);i++)
{
/* Real part arranged as a-bR, Imag part arranged as -c-dR */
*yp++ = *xp2;
*yp++ = *xp1;
xp1+=2;
xp2-=2;
}
for(;i<N4;i++)
{
/* Real part arranged as a-bR, Imag part arranged as -c-dR */
*yp++ = -MULT16_32_Q15(*wp1, xp1[-N2]) + MULT16_32_Q15(*wp2, *xp2);
*yp++ = MULT16_32_Q15(*wp2, *xp1) + MULT16_32_Q15(*wp1, xp2[N2]);
xp1+=2;
xp2-=2;
wp1+=2;
wp2-=2;
}
}
/* Pre-rotation */
{
kiss_fft_scalar * OPUS_RESTRICT yp = f;
const kiss_twiddle_scalar *t = &trig[0];
for(i=0;i<N4;i++)
{
kiss_fft_cpx yc;
kiss_twiddle_scalar t0, t1;
kiss_fft_scalar re, im, yr, yi;
t0 = t[i];
t1 = t[N4+i];
re = *yp++;
im = *yp++;
yr = S_MUL(re,t0) - S_MUL(im,t1);
yi = S_MUL(im,t0) + S_MUL(re,t1);
yc.r = yr;
yc.i = yi;
yc.r = PSHR32(MULT16_32_Q16(scale, yc.r), scale_shift);
yc.i = PSHR32(MULT16_32_Q16(scale, yc.i), scale_shift);
f2[st->bitrev[i]] = yc;
}
}
/* N/4 complex FFT, does not downscale anymore */
opus_fft_impl(st, f2);
/* Post-rotate */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
const kiss_fft_cpx * OPUS_RESTRICT fp = f2;
kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
kiss_fft_scalar * OPUS_RESTRICT yp2 = out+stride*(N2-1);
const kiss_twiddle_scalar *t = &trig[0];
/* Temp pointers to make it really clear to the compiler what we're doing */
for(i=0;i<N4;i++)
{
kiss_fft_scalar yr, yi;
yr = S_MUL(fp->i,t[N4+i]) - S_MUL(fp->r,t[i]);
yi = S_MUL(fp->r,t[N4+i]) + S_MUL(fp->i,t[i]);
*yp1 = yr;
*yp2 = yi;
fp++;
yp1 += 2*stride;
yp2 -= 2*stride;
}
}
RESTORE_STACK;
}
#endif /* OVERRIDE_clt_mdct_forward */
#ifndef OVERRIDE_clt_mdct_backward
void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window, int overlap, int shift, int stride, int arch)
{
int i;
int N, N2, N4;
const kiss_twiddle_scalar *trig;
(void) arch;
N = l->n;
trig = l->trig;
for (i=0;i<shift;i++)
{
N >>= 1;
trig += N;
}
N2 = N>>1;
N4 = N>>2;
/* Pre-rotate */
{
/* Temp pointers to make it really clear to the compiler what we're doing */
const kiss_fft_scalar * OPUS_RESTRICT xp1 = in;
const kiss_fft_scalar * OPUS_RESTRICT xp2 = in+stride*(N2-1);
kiss_fft_scalar * OPUS_RESTRICT yp = out+(overlap>>1);
const kiss_twiddle_scalar * OPUS_RESTRICT t = &trig[0];
const opus_int16 * OPUS_RESTRICT bitrev = l->kfft[shift]->bitrev;
for(i=0;i<N4;i++)
{
int rev;
kiss_fft_scalar yr, yi;
rev = *bitrev++;
yr = ADD32_ovflw(S_MUL(*xp2, t[i]), S_MUL(*xp1, t[N4+i]));
yi = SUB32_ovflw(S_MUL(*xp1, t[i]), S_MUL(*xp2, t[N4+i]));
/* We swap real and imag because we use an FFT instead of an IFFT. */
yp[2*rev+1] = yr;
yp[2*rev] = yi;
/* Storing the pre-rotation directly in the bitrev order. */
xp1+=2*stride;
xp2-=2*stride;
}
}
opus_fft_impl(l->kfft[shift], (kiss_fft_cpx*)(out+(overlap>>1)));
/* Post-rotate and de-shuffle from both ends of the buffer at once to make
it in-place. */
{
kiss_fft_scalar * yp0 = out+(overlap>>1);
kiss_fft_scalar * yp1 = out+(overlap>>1)+N2-2;
const kiss_twiddle_scalar *t = &trig[0];
/* Loop to (N4+1)>>1 to handle odd N4. When N4 is odd, the
middle pair will be computed twice. */
for(i=0;i<(N4+1)>>1;i++)
{
kiss_fft_scalar re, im, yr, yi;
kiss_twiddle_scalar t0, t1;
/* We swap real and imag because we're using an FFT instead of an IFFT. */
re = yp0[1];
im = yp0[0];
t0 = t[i];
t1 = t[N4+i];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
/* We swap real and imag because we're using an FFT instead of an IFFT. */
re = yp1[1];
im = yp1[0];
yp0[0] = yr;
yp1[1] = yi;
t0 = t[(N4-i-1)];
t1 = t[(N2-i-1)];
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
yr = ADD32_ovflw(S_MUL(re,t0), S_MUL(im,t1));
yi = SUB32_ovflw(S_MUL(re,t1), S_MUL(im,t0));
yp1[0] = yr;
yp0[1] = yi;
yp0 += 2;
yp1 -= 2;
}
}
/* Mirror on both sides for TDAC */
{
kiss_fft_scalar * OPUS_RESTRICT xp1 = out+overlap-1;
kiss_fft_scalar * OPUS_RESTRICT yp1 = out;
const opus_val16 * OPUS_RESTRICT wp1 = window;
const opus_val16 * OPUS_RESTRICT wp2 = window+overlap-1;
for(i = 0; i < overlap/2; i++)
{
kiss_fft_scalar x1, x2;
x1 = *xp1;
x2 = *yp1;
*yp1++ = SUB32_ovflw(MULT16_32_Q15(*wp2, x2), MULT16_32_Q15(*wp1, x1));
*xp1-- = ADD32_ovflw(MULT16_32_Q15(*wp1, x2), MULT16_32_Q15(*wp2, x1));
wp1++;
wp2--;
}
}
}
#endif /* OVERRIDE_clt_mdct_backward */

View File

@@ -0,0 +1,112 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2008 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/* This is a simple MDCT implementation that uses a N/4 complex FFT
to do most of the work. It should be relatively straightforward to
plug in pretty much and FFT here.
This replaces the Vorbis FFT (and uses the exact same API), which
was a bit too messy and that was ending up duplicating code
(might as well use the same FFT everywhere).
The algorithm is similar to (and inspired from) Fabrice Bellard's
MDCT implementation in FFMPEG, but has differences in signs, ordering
and scaling in many places.
*/
#ifndef MDCT_H
#define MDCT_H
#include "../opus_defines.h"
#include "kiss_fft.h"
#include "arch.h"
typedef struct {
int n;
int maxshift;
const kiss_fft_state *kfft[4];
const kiss_twiddle_scalar * OPUS_RESTRICT trig;
} mdct_lookup;
#if defined(HAVE_ARM_NE10)
#include "arm/mdct_arm.h"
#endif
int clt_mdct_init(mdct_lookup *l,int N, int maxshift, int arch);
void clt_mdct_clear(mdct_lookup *l, int arch);
/** Compute a forward MDCT and scale by 4/N, trashes the input array */
void clt_mdct_forward_c(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 *window, int overlap,
int shift, int stride, int arch);
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
(scales implicitly by 1/2) */
void clt_mdct_backward_c(const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out,
const opus_val16 * OPUS_RESTRICT window,
int overlap, int shift, int stride, int arch);
#if !defined(OVERRIDE_OPUS_MDCT)
/* Is run-time CPU detection enabled on this platform? */
#if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10)
extern void (*const CLT_MDCT_FORWARD_IMPL[OPUS_ARCHMASK+1])(
const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, const opus_val16 *window,
int overlap, int shift, int stride, int arch);
#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
((*CLT_MDCT_FORWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
_window, _overlap, _shift, \
_stride, _arch))
extern void (*const CLT_MDCT_BACKWARD_IMPL[OPUS_ARCHMASK+1])(
const mdct_lookup *l, kiss_fft_scalar *in,
kiss_fft_scalar * OPUS_RESTRICT out, const opus_val16 *window,
int overlap, int shift, int stride, int arch);
#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
(*CLT_MDCT_BACKWARD_IMPL[(arch)&OPUS_ARCHMASK])(_l, _in, _out, \
_window, _overlap, _shift, \
_stride, _arch)
#else /* if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) */
#define clt_mdct_forward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
clt_mdct_forward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch)
#define clt_mdct_backward(_l, _in, _out, _window, _overlap, _shift, _stride, _arch) \
clt_mdct_backward_c(_l, _in, _out, _window, _overlap, _shift, _stride, _arch)
#endif /* end if defined(OPUS_HAVE_RTCD) && defined(HAVE_ARM_NE10) && !defined(FIXED_POINT) */
#endif /* end if !defined(OVERRIDE_OPUS_MDCT) */
#endif

View File

@@ -0,0 +1,48 @@
/* Copyright (c) 2001-2008 Timothy B. Terriberry
Copyright (c) 2008-2009 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.
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 COPYRIGHT OWNER
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.
*/
#if !defined(_mfrngcode_H)
# define _mfrngcode_H (1)
# include "entcode.h"
/*Constants used by the entropy encoder/decoder.*/
/*The number of bits to output at a time.*/
# define EC_SYM_BITS (8)
/*The total number of bits in each of the state registers.*/
# define EC_CODE_BITS (32)
/*The maximum symbol value.*/
# define EC_SYM_MAX ((1U<<EC_SYM_BITS)-1)
/*Bits to shift by to move a symbol into the high-order position.*/
# define EC_CODE_SHIFT (EC_CODE_BITS-EC_SYM_BITS-1)
/*Carry bit of the high-order range symbol.*/
# define EC_CODE_TOP (((opus_uint32)1U)<<(EC_CODE_BITS-1))
/*Low-order bit of the high-order range symbol.*/
# define EC_CODE_BOT (EC_CODE_TOP>>EC_SYM_BITS)
/*The number of bits available for the last, partial symbol in the code field.*/
# define EC_CODE_EXTRA ((EC_CODE_BITS-2)%EC_SYM_BITS+1)
#endif

View File

@@ -0,0 +1,442 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "celt.h"
#include "modes.h"
#include "rate.h"
#include "os_support.h"
#include "stack_alloc.h"
#include "quant_bands.h"
#include "cpu_support.h"
static const opus_int16 eband5ms[] = {
/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
0, 1, 2, 3, 4, 5, 6, 7, 8, 10, 12, 14, 16, 20, 24, 28, 34, 40, 48, 60, 78, 100
};
/* Alternate tuning (partially derived from Vorbis) */
#define BITALLOC_SIZE 11
/* Bit allocation table in units of 1/32 bit/sample (0.1875 dB SNR) */
static const unsigned char band_allocation[] = {
/*0 200 400 600 800 1k 1.2 1.4 1.6 2k 2.4 2.8 3.2 4k 4.8 5.6 6.8 8k 9.6 12k 15.6 */
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
90, 80, 75, 69, 63, 56, 49, 40, 34, 29, 20, 18, 10, 0, 0, 0, 0, 0, 0, 0, 0,
110,100, 90, 84, 78, 71, 65, 58, 51, 45, 39, 32, 26, 20, 12, 0, 0, 0, 0, 0, 0,
118,110,103, 93, 86, 80, 75, 70, 65, 59, 53, 47, 40, 31, 23, 15, 4, 0, 0, 0, 0,
126,119,112,104, 95, 89, 83, 78, 72, 66, 60, 54, 47, 39, 32, 25, 17, 12, 1, 0, 0,
134,127,120,114,103, 97, 91, 85, 78, 72, 66, 60, 54, 47, 41, 35, 29, 23, 16, 10, 1,
144,137,130,124,113,107,101, 95, 88, 82, 76, 70, 64, 57, 51, 45, 39, 33, 26, 15, 1,
152,145,138,132,123,117,111,105, 98, 92, 86, 80, 74, 67, 61, 55, 49, 43, 36, 20, 1,
162,155,148,142,133,127,121,115,108,102, 96, 90, 84, 77, 71, 65, 59, 53, 46, 30, 1,
172,165,158,152,143,137,131,125,118,112,106,100, 94, 87, 81, 75, 69, 63, 56, 45, 20,
200,200,200,200,200,200,200,200,198,193,188,183,178,173,168,163,158,153,148,129,104,
};
#ifndef CUSTOM_MODES_ONLY
#ifdef FIXED_POINT
#include "static_modes_fixed.h"
#else
#include "static_modes_float.h"
#endif
#endif /* CUSTOM_MODES_ONLY */
#ifndef M_PI
#define M_PI 3.141592653
#endif
#ifdef CUSTOM_MODES
/* Defining 25 critical bands for the full 0-20 kHz audio bandwidth
Taken from http://ccrma.stanford.edu/~jos/bbt/Bark_Frequency_Scale.html */
#define BARK_BANDS 25
static const opus_int16 bark_freq[BARK_BANDS+1] = {
0, 100, 200, 300, 400,
510, 630, 770, 920, 1080,
1270, 1480, 1720, 2000, 2320,
2700, 3150, 3700, 4400, 5300,
6400, 7700, 9500, 12000, 15500,
20000};
static opus_int16 *compute_ebands(opus_int32 Fs, int frame_size, int res, int *nbEBands)
{
opus_int16 *eBands;
int i, j, lin, low, high, nBark, offset=0;
/* All modes that have 2.5 ms short blocks use the same definition */
if (Fs == 400*(opus_int32)frame_size)
{
*nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+1));
for (i=0;i<*nbEBands+1;i++)
eBands[i] = eband5ms[i];
return eBands;
}
/* Find the number of critical bands supported by our sampling rate */
for (nBark=1;nBark<BARK_BANDS;nBark++)
if (bark_freq[nBark+1]*2 >= Fs)
break;
/* Find where the linear part ends (i.e. where the spacing is more than min_width */
for (lin=0;lin<nBark;lin++)
if (bark_freq[lin+1]-bark_freq[lin] >= res)
break;
low = (bark_freq[lin]+res/2)/res;
high = nBark-lin;
*nbEBands = low+high;
eBands = opus_alloc(sizeof(opus_int16)*(*nbEBands+2));
if (eBands==NULL)
return NULL;
/* Linear spacing (min_width) */
for (i=0;i<low;i++)
eBands[i] = i;
if (low>0)
offset = eBands[low-1]*res - bark_freq[lin-1];
/* Spacing follows critical bands */
for (i=0;i<high;i++)
{
int target = bark_freq[lin+i];
/* Round to an even value */
eBands[i+low] = (target+offset/2+res)/(2*res)*2;
offset = eBands[i+low]*res - target;
}
/* Enforce the minimum spacing at the boundary */
for (i=0;i<*nbEBands;i++)
if (eBands[i] < i)
eBands[i] = i;
/* Round to an even value */
eBands[*nbEBands] = (bark_freq[nBark]+res)/(2*res)*2;
if (eBands[*nbEBands] > frame_size)
eBands[*nbEBands] = frame_size;
for (i=1;i<*nbEBands-1;i++)
{
if (eBands[i+1]-eBands[i] < eBands[i]-eBands[i-1])
{
eBands[i] -= (2*eBands[i]-eBands[i-1]-eBands[i+1])/2;
}
}
/* Remove any empty bands. */
for (i=j=0;i<*nbEBands;i++)
if(eBands[i+1]>eBands[j])
eBands[++j]=eBands[i+1];
*nbEBands=j;
for (i=1;i<*nbEBands;i++)
{
/* Every band must be smaller than the last band. */
celt_assert(eBands[i]-eBands[i-1]<=eBands[*nbEBands]-eBands[*nbEBands-1]);
/* Each band must be no larger than twice the size of the previous one. */
celt_assert(eBands[i+1]-eBands[i]<=2*(eBands[i]-eBands[i-1]));
}
return eBands;
}
static void compute_allocation_table(CELTMode *mode)
{
int i, j;
unsigned char *allocVectors;
int maxBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
mode->nbAllocVectors = BITALLOC_SIZE;
allocVectors = opus_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
if (allocVectors==NULL)
return;
/* Check for standard mode */
if (mode->Fs == 400*(opus_int32)mode->shortMdctSize)
{
for (i=0;i<BITALLOC_SIZE*mode->nbEBands;i++)
allocVectors[i] = band_allocation[i];
mode->allocVectors = allocVectors;
return;
}
/* If not the standard mode, interpolate */
/* Compute per-codec-band allocation from per-critical-band matrix */
for (i=0;i<BITALLOC_SIZE;i++)
{
for (j=0;j<mode->nbEBands;j++)
{
int k;
for (k=0;k<maxBands;k++)
{
if (400*(opus_int32)eband5ms[k] > mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize)
break;
}
if (k>maxBands-1)
allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
else {
opus_int32 a0, a1;
a1 = mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize - 400*(opus_int32)eband5ms[k-1];
a0 = 400*(opus_int32)eband5ms[k] - mode->eBands[j]*(opus_int32)mode->Fs/mode->shortMdctSize;
allocVectors[i*mode->nbEBands+j] = (a0*band_allocation[i*maxBands+k-1]
+ a1*band_allocation[i*maxBands+k])/(a0+a1);
}
}
}
/*printf ("\n");
for (i=0;i<BITALLOC_SIZE;i++)
{
for (j=0;j<mode->nbEBands;j++)
printf ("%d ", allocVectors[i*mode->nbEBands+j]);
printf ("\n");
}
exit(0);*/
mode->allocVectors = allocVectors;
}
#endif /* CUSTOM_MODES */
CELTMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error)
{
int i;
#ifdef CUSTOM_MODES
CELTMode *mode=NULL;
int res;
opus_val16 *window;
opus_int16 *logN;
int LM;
int arch = opus_select_arch();
ALLOC_STACK;
#if !defined(VAR_ARRAYS) && !defined(USE_ALLOCA)
if (global_stack==NULL)
goto failure;
#endif
#endif
#ifndef CUSTOM_MODES_ONLY
for (i=0;i<TOTAL_MODES;i++)
{
int j;
for (j=0;j<4;j++)
{
if (Fs == static_mode_list[i]->Fs &&
(frame_size<<j) == static_mode_list[i]->shortMdctSize*static_mode_list[i]->nbShortMdcts)
{
if (error)
*error = OPUS_OK;
return (CELTMode*)static_mode_list[i];
}
}
}
#endif /* CUSTOM_MODES_ONLY */
#ifndef CUSTOM_MODES
if (error)
*error = OPUS_BAD_ARG;
return NULL;
#else
/* The good thing here is that permutation of the arguments will automatically be invalid */
if (Fs < 8000 || Fs > 96000)
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
/* Frames of less than 1ms are not supported. */
if ((opus_int32)frame_size*1000 < Fs)
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
if ((opus_int32)frame_size*75 >= Fs && (frame_size%16)==0)
{
LM = 3;
} else if ((opus_int32)frame_size*150 >= Fs && (frame_size%8)==0)
{
LM = 2;
} else if ((opus_int32)frame_size*300 >= Fs && (frame_size%4)==0)
{
LM = 1;
} else
{
LM = 0;
}
/* Shorts longer than 3.3ms are not supported. */
if ((opus_int32)(frame_size>>LM)*300 > Fs)
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
mode = opus_alloc(sizeof(CELTMode));
if (mode==NULL)
goto failure;
mode->Fs = Fs;
/* Pre/de-emphasis depends on sampling rate. The "standard" pre-emphasis
is defined as A(z) = 1 - 0.85*z^-1 at 48 kHz. Other rates should
approximate that. */
if(Fs < 12000) /* 8 kHz */
{
mode->preemph[0] = QCONST16(0.3500061035f, 15);
mode->preemph[1] = -QCONST16(0.1799926758f, 15);
mode->preemph[2] = QCONST16(0.2719968125f, SIG_SHIFT); /* exact 1/preemph[3] */
mode->preemph[3] = QCONST16(3.6765136719f, 13);
} else if(Fs < 24000) /* 16 kHz */
{
mode->preemph[0] = QCONST16(0.6000061035f, 15);
mode->preemph[1] = -QCONST16(0.1799926758f, 15);
mode->preemph[2] = QCONST16(0.4424998650f, SIG_SHIFT); /* exact 1/preemph[3] */
mode->preemph[3] = QCONST16(2.2598876953f, 13);
} else if(Fs < 40000) /* 32 kHz */
{
mode->preemph[0] = QCONST16(0.7799987793f, 15);
mode->preemph[1] = -QCONST16(0.1000061035f, 15);
mode->preemph[2] = QCONST16(0.7499771125f, SIG_SHIFT); /* exact 1/preemph[3] */
mode->preemph[3] = QCONST16(1.3333740234f, 13);
} else /* 48 kHz */
{
mode->preemph[0] = QCONST16(0.8500061035f, 15);
mode->preemph[1] = QCONST16(0.0f, 15);
mode->preemph[2] = QCONST16(1.f, SIG_SHIFT);
mode->preemph[3] = QCONST16(1.f, 13);
}
mode->maxLM = LM;
mode->nbShortMdcts = 1<<LM;
mode->shortMdctSize = frame_size/mode->nbShortMdcts;
res = (mode->Fs+mode->shortMdctSize)/(2*mode->shortMdctSize);
mode->eBands = compute_ebands(Fs, mode->shortMdctSize, res, &mode->nbEBands);
if (mode->eBands==NULL)
goto failure;
#if !defined(SMALL_FOOTPRINT)
/* Make sure we don't allocate a band larger than our PVQ table.
208 should be enough, but let's be paranoid. */
if ((mode->eBands[mode->nbEBands] - mode->eBands[mode->nbEBands-1])<<LM >
208) {
goto failure;
}
#endif
mode->effEBands = mode->nbEBands;
while (mode->eBands[mode->effEBands] > mode->shortMdctSize)
mode->effEBands--;
/* Overlap must be divisible by 4 */
mode->overlap = ((mode->shortMdctSize>>2)<<2);
compute_allocation_table(mode);
if (mode->allocVectors==NULL)
goto failure;
window = (opus_val16*)opus_alloc(mode->overlap*sizeof(opus_val16));
if (window==NULL)
goto failure;
#ifndef FIXED_POINT
for (i=0;i<mode->overlap;i++)
window[i] = Q15ONE*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap));
#else
for (i=0;i<mode->overlap;i++)
window[i] = MIN32(32767,floor(.5+32768.*sin(.5*M_PI* sin(.5*M_PI*(i+.5)/mode->overlap) * sin(.5*M_PI*(i+.5)/mode->overlap))));
#endif
mode->window = window;
logN = (opus_int16*)opus_alloc(mode->nbEBands*sizeof(opus_int16));
if (logN==NULL)
goto failure;
for (i=0;i<mode->nbEBands;i++)
logN[i] = log2_frac(mode->eBands[i+1]-mode->eBands[i], BITRES);
mode->logN = logN;
compute_pulse_cache(mode, mode->maxLM);
if (clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts,
mode->maxLM, arch) == 0)
goto failure;
if (error)
*error = OPUS_OK;
return mode;
failure:
if (error)
*error = OPUS_ALLOC_FAIL;
if (mode!=NULL)
opus_custom_mode_destroy(mode);
return NULL;
#endif /* !CUSTOM_MODES */
}
#ifdef CUSTOM_MODES
void opus_custom_mode_destroy(CELTMode *mode)
{
int arch = opus_select_arch();
if (mode == NULL)
return;
#ifndef CUSTOM_MODES_ONLY
{
int i;
for (i=0;i<TOTAL_MODES;i++)
{
if (mode == static_mode_list[i])
{
return;
}
}
}
#endif /* CUSTOM_MODES_ONLY */
opus_free((opus_int16*)mode->eBands);
opus_free((unsigned char*)mode->allocVectors);
opus_free((opus_val16*)mode->window);
opus_free((opus_int16*)mode->logN);
opus_free((opus_int16*)mode->cache.index);
opus_free((unsigned char*)mode->cache.bits);
opus_free((unsigned char*)mode->cache.caps);
clt_mdct_clear(&mode->mdct, arch);
opus_free((CELTMode *)mode);
}
#endif

View File

@@ -0,0 +1,75 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef MODES_H
#define MODES_H
#include "../opus_types.h"
#include "celt.h"
#include "arch.h"
#include "mdct.h"
#include "entenc.h"
#include "entdec.h"
#define MAX_PERIOD 1024
typedef struct {
int size;
const opus_int16 *index;
const unsigned char *bits;
const unsigned char *caps;
} PulseCache;
/** Mode definition (opaque)
@brief Mode definition
*/
struct OpusCustomMode {
opus_int32 Fs;
int overlap;
int nbEBands;
int effEBands;
opus_val16 preemph[4];
const opus_int16 *eBands; /**< Definition for each "pseudo-critical band" */
int maxLM;
int nbShortMdcts;
int shortMdctSize;
int nbAllocVectors; /**< Number of lines in the matrix below */
const unsigned char *allocVectors; /**< Number of bits in each band for several rates */
const opus_int16 *logN;
const opus_val16 *window;
mdct_lookup mdct;
PulseCache cache;
};
#endif

View File

@@ -0,0 +1,92 @@
/* Copyright (C) 2007 Jean-Marc Valin
File: os_support.h
This is the (tiny) OS abstraction layer. Aside from math.h, this is the
only place where system headers are allowed.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are
met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. 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.
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
*/
#ifndef OS_SUPPORT_H
#define OS_SUPPORT_H
#ifdef CUSTOM_SUPPORT
# include "custom_support.h"
#endif
#include "../opus_types.h"
#include "../opus_defines.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/** Opus wrapper for malloc(). To do your own dynamic allocation, all you need to do is replace this function and opus_free */
#ifndef OVERRIDE_OPUS_ALLOC
static OPUS_INLINE void *opus_alloc (size_t size)
{
return malloc(size);
}
#endif
/** Same as celt_alloc(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */
#ifndef OVERRIDE_OPUS_ALLOC_SCRATCH
static OPUS_INLINE void *opus_alloc_scratch (size_t size)
{
/* Scratch space doesn't need to be cleared */
return opus_alloc(size);
}
#endif
/** Opus wrapper for free(). To do your own dynamic allocation, all you need to do is replace this function and opus_alloc */
#ifndef OVERRIDE_OPUS_FREE
static OPUS_INLINE void opus_free (void *ptr)
{
free(ptr);
}
#endif
/** Copy n elements from src to dst. The 0* term provides compile-time type checking */
#ifndef OVERRIDE_OPUS_COPY
#define OPUS_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif
/** Copy n elements from src to dst, allowing overlapping regions. The 0* term
provides compile-time type checking */
#ifndef OVERRIDE_OPUS_MOVE
#define OPUS_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
#endif
/** Set n elements of dst to zero */
#ifndef OVERRIDE_OPUS_CLEAR
#define OPUS_CLEAR(dst, n) (memset((dst), 0, (n)*sizeof(*(dst))))
#endif
/*#ifdef __GNUC__
#pragma GCC poison printf sprintf
#pragma GCC poison malloc free realloc calloc
#endif*/
#endif /* OS_SUPPORT_H */

View File

@@ -0,0 +1,537 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/**
@file pitch.c
@brief Pitch analysis
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "pitch.h"
#include "os_support.h"
#include "modes.h"
#include "stack_alloc.h"
#include "mathops.h"
#include "celt_lpc.h"
static void find_best_pitch(opus_val32 *xcorr, opus_val16 *y, int len,
int max_pitch, int *best_pitch
#ifdef FIXED_POINT
, int yshift, opus_val32 maxcorr
#endif
)
{
int i, j;
opus_val32 Syy=1;
opus_val16 best_num[2];
opus_val32 best_den[2];
#ifdef FIXED_POINT
int xshift;
xshift = celt_ilog2(maxcorr)-14;
#endif
best_num[0] = -1;
best_num[1] = -1;
best_den[0] = 0;
best_den[1] = 0;
best_pitch[0] = 0;
best_pitch[1] = 1;
for (j=0;j<len;j++)
Syy = ADD32(Syy, SHR32(MULT16_16(y[j],y[j]), yshift));
for (i=0;i<max_pitch;i++)
{
if (xcorr[i]>0)
{
opus_val16 num;
opus_val32 xcorr16;
xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
#ifndef FIXED_POINT
/* Considering the range of xcorr16, this should avoid both underflows
and overflows (inf) when squaring xcorr16 */
xcorr16 *= 1e-12f;
#endif
num = MULT16_16_Q15(xcorr16,xcorr16);
if (MULT16_32_Q15(num,best_den[1]) > MULT16_32_Q15(best_num[1],Syy))
{
if (MULT16_32_Q15(num,best_den[0]) > MULT16_32_Q15(best_num[0],Syy))
{
best_num[1] = best_num[0];
best_den[1] = best_den[0];
best_pitch[1] = best_pitch[0];
best_num[0] = num;
best_den[0] = Syy;
best_pitch[0] = i;
} else {
best_num[1] = num;
best_den[1] = Syy;
best_pitch[1] = i;
}
}
}
Syy += SHR32(MULT16_16(y[i+len],y[i+len]),yshift) - SHR32(MULT16_16(y[i],y[i]),yshift);
Syy = MAX32(1, Syy);
}
}
static void celt_fir5(opus_val16 *x,
const opus_val16 *num,
int N)
{
int i;
opus_val16 num0, num1, num2, num3, num4;
opus_val32 mem0, mem1, mem2, mem3, mem4;
num0=num[0];
num1=num[1];
num2=num[2];
num3=num[3];
num4=num[4];
mem0=0;
mem1=0;
mem2=0;
mem3=0;
mem4=0;
for (i=0;i<N;i++)
{
opus_val32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
sum = MAC16_16(sum,num0,mem0);
sum = MAC16_16(sum,num1,mem1);
sum = MAC16_16(sum,num2,mem2);
sum = MAC16_16(sum,num3,mem3);
sum = MAC16_16(sum,num4,mem4);
mem4 = mem3;
mem3 = mem2;
mem2 = mem1;
mem1 = mem0;
mem0 = x[i];
x[i] = ROUND16(sum, SIG_SHIFT);
}
}
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
int len, int C, int arch)
{
int i;
opus_val32 ac[5];
opus_val16 tmp=Q15ONE;
opus_val16 lpc[4];
opus_val16 lpc2[5];
opus_val16 c1 = QCONST16(.8f,15);
#ifdef FIXED_POINT
int shift;
opus_val32 maxabs = celt_maxabs32(x[0], len);
if (C==2)
{
opus_val32 maxabs_1 = celt_maxabs32(x[1], len);
maxabs = MAX32(maxabs, maxabs_1);
}
if (maxabs<1)
maxabs=1;
shift = celt_ilog2(maxabs)-10;
if (shift<0)
shift=0;
if (C==2)
shift++;
#endif
for (i=1;i<len>>1;i++)
x_lp[i] = SHR32(HALF32(HALF32(x[0][(2*i-1)]+x[0][(2*i+1)])+x[0][2*i]), shift);
x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), shift);
if (C==2)
{
for (i=1;i<len>>1;i++)
x_lp[i] += SHR32(HALF32(HALF32(x[1][(2*i-1)]+x[1][(2*i+1)])+x[1][2*i]), shift);
x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), shift);
}
_celt_autocorr(x_lp, ac, NULL, 0,
4, len>>1, arch);
/* Noise floor -40 dB */
#ifdef FIXED_POINT
ac[0] += SHR32(ac[0],13);
#else
ac[0] *= 1.0001f;
#endif
/* Lag windowing */
for (i=1;i<=4;i++)
{
/*ac[i] *= exp(-.5*(2*M_PI*.002*i)*(2*M_PI*.002*i));*/
#ifdef FIXED_POINT
ac[i] -= MULT16_32_Q15(2*i*i, ac[i]);
#else
ac[i] -= ac[i]*(.008f*i)*(.008f*i);
#endif
}
_celt_lpc(lpc, ac, 4);
for (i=0;i<4;i++)
{
tmp = MULT16_16_Q15(QCONST16(.9f,15), tmp);
lpc[i] = MULT16_16_Q15(lpc[i], tmp);
}
/* Add a zero */
lpc2[0] = lpc[0] + QCONST16(.8f,SIG_SHIFT);
lpc2[1] = lpc[1] + MULT16_16_Q15(c1,lpc[0]);
lpc2[2] = lpc[2] + MULT16_16_Q15(c1,lpc[1]);
lpc2[3] = lpc[3] + MULT16_16_Q15(c1,lpc[2]);
lpc2[4] = MULT16_16_Q15(c1,lpc[3]);
celt_fir5(x_lp, lpc2, len>>1);
}
/* Pure C implementation. */
#ifdef FIXED_POINT
opus_val32
#else
void
#endif
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch)
{
#if 0 /* This is a simple version of the pitch correlation that should work
well on DSPs like Blackfin and TI C5x/C6x */
int i, j;
#ifdef FIXED_POINT
opus_val32 maxcorr=1;
#endif
#if !defined(OVERRIDE_PITCH_XCORR)
(void)arch;
#endif
for (i=0;i<max_pitch;i++)
{
opus_val32 sum = 0;
for (j=0;j<len;j++)
sum = MAC16_16(sum, _x[j], _y[i+j]);
xcorr[i] = sum;
#ifdef FIXED_POINT
maxcorr = MAX32(maxcorr, sum);
#endif
}
#ifdef FIXED_POINT
return maxcorr;
#endif
#else /* Unrolled version of the pitch correlation -- runs faster on x86 and ARM */
int i;
/*The EDSP version requires that max_pitch is at least 1, and that _x is
32-bit aligned.
Since it's hard to put asserts in assembly, put them here.*/
#ifdef FIXED_POINT
opus_val32 maxcorr=1;
#endif
celt_assert(max_pitch>0);
celt_sig_assert((((unsigned char *)_x-(unsigned char *)NULL)&3)==0);
for (i=0;i<max_pitch-3;i+=4)
{
opus_val32 sum[4]={0,0,0,0};
xcorr_kernel(_x, _y+i, sum, len, arch);
xcorr[i]=sum[0];
xcorr[i+1]=sum[1];
xcorr[i+2]=sum[2];
xcorr[i+3]=sum[3];
#ifdef FIXED_POINT
sum[0] = MAX32(sum[0], sum[1]);
sum[2] = MAX32(sum[2], sum[3]);
sum[0] = MAX32(sum[0], sum[2]);
maxcorr = MAX32(maxcorr, sum[0]);
#endif
}
/* In case max_pitch isn't a multiple of 4, do non-unrolled version. */
for (;i<max_pitch;i++)
{
opus_val32 sum;
sum = celt_inner_prod(_x, _y+i, len, arch);
xcorr[i] = sum;
#ifdef FIXED_POINT
maxcorr = MAX32(maxcorr, sum);
#endif
}
#ifdef FIXED_POINT
return maxcorr;
#endif
#endif
}
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
int len, int max_pitch, int *pitch, int arch)
{
int i, j;
int lag;
int best_pitch[2]={0,0};
VARDECL(opus_val16, x_lp4);
VARDECL(opus_val16, y_lp4);
VARDECL(opus_val32, xcorr);
#ifdef FIXED_POINT
opus_val32 maxcorr;
opus_val32 xmax, ymax;
int shift=0;
#endif
int offset;
SAVE_STACK;
celt_assert(len>0);
celt_assert(max_pitch>0);
lag = len+max_pitch;
ALLOC(x_lp4, len>>2, opus_val16);
ALLOC(y_lp4, lag>>2, opus_val16);
ALLOC(xcorr, max_pitch>>1, opus_val32);
/* Downsample by 2 again */
for (j=0;j<len>>2;j++)
x_lp4[j] = x_lp[2*j];
for (j=0;j<lag>>2;j++)
y_lp4[j] = y[2*j];
#ifdef FIXED_POINT
xmax = celt_maxabs16(x_lp4, len>>2);
ymax = celt_maxabs16(y_lp4, lag>>2);
shift = celt_ilog2(MAX32(1, MAX32(xmax, ymax)))-11;
if (shift>0)
{
for (j=0;j<len>>2;j++)
x_lp4[j] = SHR16(x_lp4[j], shift);
for (j=0;j<lag>>2;j++)
y_lp4[j] = SHR16(y_lp4[j], shift);
/* Use double the shift for a MAC */
shift *= 2;
} else {
shift = 0;
}
#endif
/* Coarse search with 4x decimation */
#ifdef FIXED_POINT
maxcorr =
#endif
celt_pitch_xcorr(x_lp4, y_lp4, xcorr, len>>2, max_pitch>>2, arch);
find_best_pitch(xcorr, y_lp4, len>>2, max_pitch>>2, best_pitch
#ifdef FIXED_POINT
, 0, maxcorr
#endif
);
/* Finer search with 2x decimation */
#ifdef FIXED_POINT
maxcorr=1;
#endif
for (i=0;i<max_pitch>>1;i++)
{
opus_val32 sum;
xcorr[i] = 0;
if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
continue;
#ifdef FIXED_POINT
sum = 0;
for (j=0;j<len>>1;j++)
sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
#else
sum = celt_inner_prod(x_lp, y+i, len>>1, arch);
#endif
xcorr[i] = MAX32(-1, sum);
#ifdef FIXED_POINT
maxcorr = MAX32(maxcorr, sum);
#endif
}
find_best_pitch(xcorr, y, len>>1, max_pitch>>1, best_pitch
#ifdef FIXED_POINT
, shift+1, maxcorr
#endif
);
/* Refine by pseudo-interpolation */
if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
{
opus_val32 a, b, c;
a = xcorr[best_pitch[0]-1];
b = xcorr[best_pitch[0]];
c = xcorr[best_pitch[0]+1];
if ((c-a) > MULT16_32_Q15(QCONST16(.7f,15),b-a))
offset = 1;
else if ((a-c) > MULT16_32_Q15(QCONST16(.7f,15),b-c))
offset = -1;
else
offset = 0;
} else {
offset = 0;
}
*pitch = 2*best_pitch[0]-offset;
RESTORE_STACK;
}
#ifdef FIXED_POINT
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
{
opus_val32 x2y2;
int sx, sy, shift;
opus_val32 g;
opus_val16 den;
if (xy == 0 || xx == 0 || yy == 0)
return 0;
sx = celt_ilog2(xx)-14;
sy = celt_ilog2(yy)-14;
shift = sx + sy;
x2y2 = SHR32(MULT16_16(VSHR32(xx, sx), VSHR32(yy, sy)), 14);
if (shift & 1) {
if (x2y2 < 32768)
{
x2y2 <<= 1;
shift--;
} else {
x2y2 >>= 1;
shift++;
}
}
den = celt_rsqrt_norm(x2y2);
g = MULT16_32_Q15(den, xy);
g = VSHR32(g, (shift>>1)-1);
return EXTRACT16(MIN32(g, Q15ONE));
}
#else
static opus_val16 compute_pitch_gain(opus_val32 xy, opus_val32 xx, opus_val32 yy)
{
return xy/celt_sqrt(1+xx*yy);
}
#endif
static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
int N, int *T0_, int prev_period, opus_val16 prev_gain, int arch)
{
int k, i, T, T0;
opus_val16 g, g0;
opus_val16 pg;
opus_val32 xy,xx,yy,xy2;
opus_val32 xcorr[3];
opus_val32 best_xy, best_yy;
int offset;
int minperiod0;
VARDECL(opus_val32, yy_lookup);
SAVE_STACK;
minperiod0 = minperiod;
maxperiod /= 2;
minperiod /= 2;
*T0_ /= 2;
prev_period /= 2;
N /= 2;
x += maxperiod;
if (*T0_>=maxperiod)
*T0_=maxperiod-1;
T = T0 = *T0_;
ALLOC(yy_lookup, maxperiod+1, opus_val32);
dual_inner_prod(x, x, x-T0, N, &xx, &xy, arch);
yy_lookup[0] = xx;
yy=xx;
for (i=1;i<=maxperiod;i++)
{
yy = yy+MULT16_16(x[-i],x[-i])-MULT16_16(x[N-i],x[N-i]);
yy_lookup[i] = MAX32(0, yy);
}
yy = yy_lookup[T0];
best_xy = xy;
best_yy = yy;
g = g0 = compute_pitch_gain(xy, xx, yy);
/* Look for any pitch at T/k */
for (k=2;k<=15;k++)
{
int T1, T1b;
opus_val16 g1;
opus_val16 cont=0;
opus_val16 thresh;
T1 = celt_udiv(2*T0+k, 2*k);
if (T1 < minperiod)
break;
/* Look for another strong correlation at T1b */
if (k==2)
{
if (T1+T0>maxperiod)
T1b = T0;
else
T1b = T0+T1;
} else
{
T1b = celt_udiv(2*second_check[k]*T0+k, 2*k);
}
dual_inner_prod(x, &x[-T1], &x[-T1b], N, &xy, &xy2, arch);
xy = HALF32(xy + xy2);
yy = HALF32(yy_lookup[T1] + yy_lookup[T1b]);
g1 = compute_pitch_gain(xy, xx, yy);
if (abs(T1-prev_period)<=1)
cont = prev_gain;
else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
cont = HALF16(prev_gain);
else
cont = 0;
thresh = MAX16(QCONST16(.3f,15), MULT16_16_Q15(QCONST16(.7f,15),g0)-cont);
/* Bias against very high pitch (very short period) to avoid false-positives
due to short-term correlation */
if (T1<3*minperiod)
thresh = MAX16(QCONST16(.4f,15), MULT16_16_Q15(QCONST16(.85f,15),g0)-cont);
else if (T1<2*minperiod)
thresh = MAX16(QCONST16(.5f,15), MULT16_16_Q15(QCONST16(.9f,15),g0)-cont);
if (g1 > thresh)
{
best_xy = xy;
best_yy = yy;
T = T1;
g = g1;
}
}
best_xy = MAX32(0, best_xy);
if (best_yy <= best_xy)
pg = Q15ONE;
else
pg = SHR32(frac_div32(best_xy,best_yy+1),16);
for (k=0;k<3;k++)
xcorr[k] = celt_inner_prod(x, x-(T+k-1), N, arch);
if ((xcorr[2]-xcorr[0]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[0]))
offset = 1;
else if ((xcorr[0]-xcorr[2]) > MULT16_32_Q15(QCONST16(.7f,15),xcorr[1]-xcorr[2]))
offset = -1;
else
offset = 0;
if (pg > g)
pg = g;
*T0_ = 2*T+offset;
if (*T0_<minperiod0)
*T0_=minperiod0;
RESTORE_STACK;
return pg;
}

View File

@@ -0,0 +1,192 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/**
@file pitch.h
@brief Pitch analysis
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef PITCH_H
#define PITCH_H
#include "modes.h"
#include "cpu_support.h"
#if (defined(OPUS_X86_MAY_HAVE_SSE) && !defined(FIXED_POINT)) \
|| ((defined(OPUS_X86_MAY_HAVE_SSE4_1) || defined(OPUS_X86_MAY_HAVE_SSE2)) && defined(FIXED_POINT))
#include "x86/pitch_sse.h"
#endif
#if defined(MIPSr1_ASM)
#include "mips/pitch_mipsr1.h"
#endif
#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
# include "arm/pitch_arm.h"
#endif
void pitch_downsample(celt_sig * OPUS_RESTRICT x[], opus_val16 * OPUS_RESTRICT x_lp,
int len, int C, int arch);
void pitch_search(const opus_val16 * OPUS_RESTRICT x_lp, opus_val16 * OPUS_RESTRICT y,
int len, int max_pitch, int *pitch, int arch);
opus_val16 remove_doubling(opus_val16 *x, int maxperiod, int minperiod,
int N, int *T0, int prev_period, opus_val16 prev_gain, int arch);
/* OPT: This is the kernel you really want to optimize. It gets used a lot
by the prefilter and by the PLC. */
static OPUS_INLINE void xcorr_kernel_c(const opus_val16 * x, const opus_val16 * y, opus_val32 sum[4], int len)
{
int j;
opus_val16 y_0, y_1, y_2, y_3;
celt_assert(len>=3);
y_3=0; /* gcc doesn't realize that y_3 can't be used uninitialized */
y_0=*y++;
y_1=*y++;
y_2=*y++;
for (j=0;j<len-3;j+=4)
{
opus_val16 tmp;
tmp = *x++;
y_3=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_0);
sum[1] = MAC16_16(sum[1],tmp,y_1);
sum[2] = MAC16_16(sum[2],tmp,y_2);
sum[3] = MAC16_16(sum[3],tmp,y_3);
tmp=*x++;
y_0=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_1);
sum[1] = MAC16_16(sum[1],tmp,y_2);
sum[2] = MAC16_16(sum[2],tmp,y_3);
sum[3] = MAC16_16(sum[3],tmp,y_0);
tmp=*x++;
y_1=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_2);
sum[1] = MAC16_16(sum[1],tmp,y_3);
sum[2] = MAC16_16(sum[2],tmp,y_0);
sum[3] = MAC16_16(sum[3],tmp,y_1);
tmp=*x++;
y_2=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_3);
sum[1] = MAC16_16(sum[1],tmp,y_0);
sum[2] = MAC16_16(sum[2],tmp,y_1);
sum[3] = MAC16_16(sum[3],tmp,y_2);
}
if (j++<len)
{
opus_val16 tmp = *x++;
y_3=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_0);
sum[1] = MAC16_16(sum[1],tmp,y_1);
sum[2] = MAC16_16(sum[2],tmp,y_2);
sum[3] = MAC16_16(sum[3],tmp,y_3);
}
if (j++<len)
{
opus_val16 tmp=*x++;
y_0=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_1);
sum[1] = MAC16_16(sum[1],tmp,y_2);
sum[2] = MAC16_16(sum[2],tmp,y_3);
sum[3] = MAC16_16(sum[3],tmp,y_0);
}
if (j<len)
{
opus_val16 tmp=*x++;
y_1=*y++;
sum[0] = MAC16_16(sum[0],tmp,y_2);
sum[1] = MAC16_16(sum[1],tmp,y_3);
sum[2] = MAC16_16(sum[2],tmp,y_0);
sum[3] = MAC16_16(sum[3],tmp,y_1);
}
}
#ifndef OVERRIDE_XCORR_KERNEL
#define xcorr_kernel(x, y, sum, len, arch) \
((void)(arch),xcorr_kernel_c(x, y, sum, len))
#endif /* OVERRIDE_XCORR_KERNEL */
static OPUS_INLINE void dual_inner_prod_c(const opus_val16 *x, const opus_val16 *y01, const opus_val16 *y02,
int N, opus_val32 *xy1, opus_val32 *xy2)
{
int i;
opus_val32 xy01=0;
opus_val32 xy02=0;
for (i=0;i<N;i++)
{
xy01 = MAC16_16(xy01, x[i], y01[i]);
xy02 = MAC16_16(xy02, x[i], y02[i]);
}
*xy1 = xy01;
*xy2 = xy02;
}
#ifndef OVERRIDE_DUAL_INNER_PROD
# define dual_inner_prod(x, y01, y02, N, xy1, xy2, arch) \
((void)(arch),dual_inner_prod_c(x, y01, y02, N, xy1, xy2))
#endif
/*We make sure a C version is always available for cases where the overhead of
vectorization and passing around an arch flag aren't worth it.*/
static OPUS_INLINE opus_val32 celt_inner_prod_c(const opus_val16 *x,
const opus_val16 *y, int N)
{
int i;
opus_val32 xy=0;
for (i=0;i<N;i++)
xy = MAC16_16(xy, x[i], y[i]);
return xy;
}
#if !defined(OVERRIDE_CELT_INNER_PROD)
# define celt_inner_prod(x, y, N, arch) \
((void)(arch),celt_inner_prod_c(x, y, N))
#endif
#ifdef NON_STATIC_COMB_FILTER_CONST_C
void comb_filter_const_c(opus_val32 *y, opus_val32 *x, int T, int N,
opus_val16 g10, opus_val16 g11, opus_val16 g12);
#endif
#ifdef FIXED_POINT
opus_val32
#else
void
#endif
celt_pitch_xcorr_c(const opus_val16 *_x, const opus_val16 *_y,
opus_val32 *xcorr, int len, int max_pitch, int arch);
#ifndef OVERRIDE_PITCH_XCORR
# define celt_pitch_xcorr celt_pitch_xcorr_c
#endif
#endif

View File

@@ -0,0 +1,563 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "quant_bands.h"
#include "laplace.h"
#include <math.h>
#include "os_support.h"
#include "arch.h"
#include "mathops.h"
#include "stack_alloc.h"
#include "rate.h"
#ifdef FIXED_POINT
/* Mean energy in each band quantized in Q4 */
const signed char eMeans[25] = {
103,100, 92, 85, 81,
77, 72, 70, 78, 75,
73, 71, 78, 74, 69,
72, 70, 74, 76, 71,
60, 60, 60, 60, 60
};
#else
/* Mean energy in each band quantized in Q4 and converted back to float */
const opus_val16 eMeans[25] = {
6.437500f, 6.250000f, 5.750000f, 5.312500f, 5.062500f,
4.812500f, 4.500000f, 4.375000f, 4.875000f, 4.687500f,
4.562500f, 4.437500f, 4.875000f, 4.625000f, 4.312500f,
4.500000f, 4.375000f, 4.625000f, 4.750000f, 4.437500f,
3.750000f, 3.750000f, 3.750000f, 3.750000f, 3.750000f
};
#endif
/* prediction coefficients: 0.9, 0.8, 0.65, 0.5 */
#ifdef FIXED_POINT
static const opus_val16 pred_coef[4] = {29440, 26112, 21248, 16384};
static const opus_val16 beta_coef[4] = {30147, 22282, 12124, 6554};
static const opus_val16 beta_intra = 4915;
#else
static const opus_val16 pred_coef[4] = {29440/32768., 26112/32768., 21248/32768., 16384/32768.};
static const opus_val16 beta_coef[4] = {30147/32768., 22282/32768., 12124/32768., 6554/32768.};
static const opus_val16 beta_intra = 4915/32768.;
#endif
/*Parameters of the Laplace-like probability models used for the coarse energy.
There is one pair of parameters for each frame size, prediction type
(inter/intra), and band number.
The first number of each pair is the probability of 0, and the second is the
decay rate, both in Q8 precision.*/
static const unsigned char e_prob_model[4][2][42] = {
/*120 sample frames.*/
{
/*Inter*/
{
72, 127, 65, 129, 66, 128, 65, 128, 64, 128, 62, 128, 64, 128,
64, 128, 92, 78, 92, 79, 92, 78, 90, 79, 116, 41, 115, 40,
114, 40, 132, 26, 132, 26, 145, 17, 161, 12, 176, 10, 177, 11
},
/*Intra*/
{
24, 179, 48, 138, 54, 135, 54, 132, 53, 134, 56, 133, 55, 132,
55, 132, 61, 114, 70, 96, 74, 88, 75, 88, 87, 74, 89, 66,
91, 67, 100, 59, 108, 50, 120, 40, 122, 37, 97, 43, 78, 50
}
},
/*240 sample frames.*/
{
/*Inter*/
{
83, 78, 84, 81, 88, 75, 86, 74, 87, 71, 90, 73, 93, 74,
93, 74, 109, 40, 114, 36, 117, 34, 117, 34, 143, 17, 145, 18,
146, 19, 162, 12, 165, 10, 178, 7, 189, 6, 190, 8, 177, 9
},
/*Intra*/
{
23, 178, 54, 115, 63, 102, 66, 98, 69, 99, 74, 89, 71, 91,
73, 91, 78, 89, 86, 80, 92, 66, 93, 64, 102, 59, 103, 60,
104, 60, 117, 52, 123, 44, 138, 35, 133, 31, 97, 38, 77, 45
}
},
/*480 sample frames.*/
{
/*Inter*/
{
61, 90, 93, 60, 105, 42, 107, 41, 110, 45, 116, 38, 113, 38,
112, 38, 124, 26, 132, 27, 136, 19, 140, 20, 155, 14, 159, 16,
158, 18, 170, 13, 177, 10, 187, 8, 192, 6, 175, 9, 159, 10
},
/*Intra*/
{
21, 178, 59, 110, 71, 86, 75, 85, 84, 83, 91, 66, 88, 73,
87, 72, 92, 75, 98, 72, 105, 58, 107, 54, 115, 52, 114, 55,
112, 56, 129, 51, 132, 40, 150, 33, 140, 29, 98, 35, 77, 42
}
},
/*960 sample frames.*/
{
/*Inter*/
{
42, 121, 96, 66, 108, 43, 111, 40, 117, 44, 123, 32, 120, 36,
119, 33, 127, 33, 134, 34, 139, 21, 147, 23, 152, 20, 158, 25,
154, 26, 166, 21, 173, 16, 184, 13, 184, 10, 150, 13, 139, 15
},
/*Intra*/
{
22, 178, 63, 114, 74, 82, 84, 83, 92, 82, 103, 62, 96, 72,
96, 67, 101, 73, 107, 72, 113, 55, 118, 52, 125, 52, 118, 52,
117, 55, 135, 49, 137, 39, 157, 32, 145, 29, 97, 33, 77, 40
}
}
};
static const unsigned char small_energy_icdf[3]={2,1,0};
static opus_val32 loss_distortion(const opus_val16 *eBands, opus_val16 *oldEBands, int start, int end, int len, int C)
{
int c, i;
opus_val32 dist = 0;
c=0; do {
for (i=start;i<end;i++)
{
opus_val16 d = SUB16(SHR16(eBands[i+c*len], 3), SHR16(oldEBands[i+c*len], 3));
dist = MAC16_16(dist, d,d);
}
} while (++c<C);
return MIN32(200,SHR32(dist,2*DB_SHIFT-6));
}
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
const opus_val16 *eBands, opus_val16 *oldEBands,
opus_int32 budget, opus_int32 tell,
const unsigned char *prob_model, opus_val16 *error, ec_enc *enc,
int C, int LM, int intra, opus_val16 max_decay, int lfe)
{
int i, c;
int badness = 0;
opus_val32 prev[2] = {0,0};
opus_val16 coef;
opus_val16 beta;
if (tell+3 <= budget)
ec_enc_bit_logp(enc, intra, 3);
if (intra)
{
coef = 0;
beta = beta_intra;
} else {
beta = beta_coef[LM];
coef = pred_coef[LM];
}
/* Encode at a fixed coarse resolution */
for (i=start;i<end;i++)
{
c=0;
do {
int bits_left;
int qi, qi0;
opus_val32 q;
opus_val16 x;
opus_val32 f, tmp;
opus_val16 oldE;
opus_val16 decay_bound;
x = eBands[i+c*m->nbEBands];
oldE = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]);
#ifdef FIXED_POINT
f = SHL32(EXTEND32(x),7) - PSHR32(MULT16_16(coef,oldE), 8) - prev[c];
/* Rounding to nearest integer here is really important! */
qi = (f+QCONST32(.5f,DB_SHIFT+7))>>(DB_SHIFT+7);
decay_bound = EXTRACT16(MAX32(-QCONST16(28.f,DB_SHIFT),
SUB32((opus_val32)oldEBands[i+c*m->nbEBands],max_decay)));
#else
f = x-coef*oldE-prev[c];
/* Rounding to nearest integer here is really important! */
qi = (int)floor(.5f+f);
decay_bound = MAX16(-QCONST16(28.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]) - max_decay;
#endif
/* Prevent the energy from going down too quickly (e.g. for bands
that have just one bin) */
if (qi < 0 && x < decay_bound)
{
qi += (int)SHR16(SUB16(decay_bound,x), DB_SHIFT);
if (qi > 0)
qi = 0;
}
qi0 = qi;
/* If we don't have enough bits to encode all the energy, just assume
something safe. */
tell = ec_tell(enc);
bits_left = budget-tell-3*C*(end-i);
if (i!=start && bits_left < 30)
{
if (bits_left < 24)
qi = IMIN(1, qi);
if (bits_left < 16)
qi = IMAX(-1, qi);
}
if (lfe && i>=2)
qi = IMIN(qi, 0);
if (budget-tell >= 15)
{
int pi;
pi = 2*IMIN(i,20);
ec_laplace_encode(enc, &qi,
prob_model[pi]<<7, prob_model[pi+1]<<6);
}
else if(budget-tell >= 2)
{
qi = IMAX(-1, IMIN(qi, 1));
ec_enc_icdf(enc, 2*qi^-(qi<0), small_energy_icdf, 2);
}
else if(budget-tell >= 1)
{
qi = IMIN(0, qi);
ec_enc_bit_logp(enc, -qi, 1);
}
else
qi = -1;
error[i+c*m->nbEBands] = PSHR32(f,7) - SHL16(qi,DB_SHIFT);
badness += abs(qi0-qi);
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
tmp = PSHR32(MULT16_16(coef,oldE),8) + prev[c] + SHL32(q,7);
#ifdef FIXED_POINT
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp);
#endif
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7);
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8));
} while (++c < C);
}
return lfe ? 0 : badness;
}
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
opus_val16 *error, ec_enc *enc, int C, int LM, int nbAvailableBytes,
int force_intra, opus_val32 *delayedIntra, int two_pass, int loss_rate, int lfe)
{
int intra;
opus_val16 max_decay;
VARDECL(opus_val16, oldEBands_intra);
VARDECL(opus_val16, error_intra);
ec_enc enc_start_state;
opus_uint32 tell;
int badness1=0;
opus_int32 intra_bias;
opus_val32 new_distortion;
SAVE_STACK;
intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C);
intra_bias = (opus_int32)((budget**delayedIntra*loss_rate)/(C*512));
new_distortion = loss_distortion(eBands, oldEBands, start, effEnd, m->nbEBands, C);
tell = ec_tell(enc);
if (tell+3 > budget)
two_pass = intra = 0;
max_decay = QCONST16(16.f,DB_SHIFT);
if (end-start>10)
{
#ifdef FIXED_POINT
max_decay = MIN32(max_decay, SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3));
#else
max_decay = MIN32(max_decay, .125f*nbAvailableBytes);
#endif
}
if (lfe)
max_decay = QCONST16(3.f,DB_SHIFT);
enc_start_state = *enc;
ALLOC(oldEBands_intra, C*m->nbEBands, opus_val16);
ALLOC(error_intra, C*m->nbEBands, opus_val16);
OPUS_COPY(oldEBands_intra, oldEBands, C*m->nbEBands);
if (two_pass || intra)
{
badness1 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands_intra, budget,
tell, e_prob_model[LM][1], error_intra, enc, C, LM, 1, max_decay, lfe);
}
if (!intra)
{
unsigned char *intra_buf;
ec_enc enc_intra_state;
opus_int32 tell_intra;
opus_uint32 nstart_bytes;
opus_uint32 nintra_bytes;
opus_uint32 save_bytes;
int badness2;
VARDECL(unsigned char, intra_bits);
tell_intra = ec_tell_frac(enc);
enc_intra_state = *enc;
nstart_bytes = ec_range_bytes(&enc_start_state);
nintra_bytes = ec_range_bytes(&enc_intra_state);
intra_buf = ec_get_buffer(&enc_intra_state) + nstart_bytes;
save_bytes = nintra_bytes-nstart_bytes;
if (save_bytes == 0)
save_bytes = ALLOC_NONE;
ALLOC(intra_bits, save_bytes, unsigned char);
/* Copy bits from intra bit-stream */
OPUS_COPY(intra_bits, intra_buf, nintra_bytes - nstart_bytes);
*enc = enc_start_state;
badness2 = quant_coarse_energy_impl(m, start, end, eBands, oldEBands, budget,
tell, e_prob_model[LM][intra], error, enc, C, LM, 0, max_decay, lfe);
if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ((opus_int32)ec_tell_frac(enc))+intra_bias > tell_intra)))
{
*enc = enc_intra_state;
/* Copy intra bits to bit-stream */
OPUS_COPY(intra_buf, intra_bits, nintra_bytes - nstart_bytes);
OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
OPUS_COPY(error, error_intra, C*m->nbEBands);
intra = 1;
}
} else {
OPUS_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
OPUS_COPY(error, error_intra, C*m->nbEBands);
}
if (intra)
*delayedIntra = new_distortion;
else
*delayedIntra = ADD32(MULT16_32_Q15(MULT16_16_Q15(pred_coef[LM], pred_coef[LM]),*delayedIntra),
new_distortion);
RESTORE_STACK;
}
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C)
{
int i, c;
/* Encode finer resolution */
for (i=start;i<end;i++)
{
opus_int16 frac = 1<<fine_quant[i];
if (fine_quant[i] <= 0)
continue;
c=0;
do {
int q2;
opus_val16 offset;
#ifdef FIXED_POINT
/* Has to be without rounding */
q2 = (error[i+c*m->nbEBands]+QCONST16(.5f,DB_SHIFT))>>(DB_SHIFT-fine_quant[i]);
#else
q2 = (int)floor((error[i+c*m->nbEBands]+.5f)*frac);
#endif
if (q2 > frac-1)
q2 = frac-1;
if (q2<0)
q2 = 0;
ec_enc_bits(enc, q2, fine_quant[i]);
#ifdef FIXED_POINT
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT));
#else
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
#endif
oldEBands[i+c*m->nbEBands] += offset;
error[i+c*m->nbEBands] -= offset;
/*printf ("%f ", error[i] - offset);*/
} while (++c < C);
}
}
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C)
{
int i, prio, c;
/* Use up the remaining bits */
for (prio=0;prio<2;prio++)
{
for (i=start;i<end && bits_left>=C ;i++)
{
if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
continue;
c=0;
do {
int q2;
opus_val16 offset;
q2 = error[i+c*m->nbEBands]<0 ? 0 : 1;
ec_enc_bits(enc, q2, 1);
#ifdef FIXED_POINT
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1);
#else
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif
oldEBands[i+c*m->nbEBands] += offset;
error[i+c*m->nbEBands] -= offset;
bits_left--;
} while (++c < C);
}
}
}
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM)
{
const unsigned char *prob_model = e_prob_model[LM][intra];
int i, c;
opus_val32 prev[2] = {0, 0};
opus_val16 coef;
opus_val16 beta;
opus_int32 budget;
opus_int32 tell;
if (intra)
{
coef = 0;
beta = beta_intra;
} else {
beta = beta_coef[LM];
coef = pred_coef[LM];
}
budget = dec->storage*8;
/* Decode at a fixed coarse resolution */
for (i=start;i<end;i++)
{
c=0;
do {
int qi;
opus_val32 q;
opus_val32 tmp;
/* It would be better to express this invariant as a
test on C at function entry, but that isn't enough
to make the static analyzer happy. */
celt_sig_assert(c<2);
tell = ec_tell(dec);
if(budget-tell>=15)
{
int pi;
pi = 2*IMIN(i,20);
qi = ec_laplace_decode(dec,
prob_model[pi]<<7, prob_model[pi+1]<<6);
}
else if(budget-tell>=2)
{
qi = ec_dec_icdf(dec, small_energy_icdf, 2);
qi = (qi>>1)^-(qi&1);
}
else if(budget-tell>=1)
{
qi = -ec_dec_bit_logp(dec, 1);
}
else
qi = -1;
q = (opus_val32)SHL32(EXTEND32(qi),DB_SHIFT);
oldEBands[i+c*m->nbEBands] = MAX16(-QCONST16(9.f,DB_SHIFT), oldEBands[i+c*m->nbEBands]);
tmp = PSHR32(MULT16_16(coef,oldEBands[i+c*m->nbEBands]),8) + prev[c] + SHL32(q,7);
#ifdef FIXED_POINT
tmp = MAX32(-QCONST32(28.f, DB_SHIFT+7), tmp);
#endif
oldEBands[i+c*m->nbEBands] = PSHR32(tmp, 7);
prev[c] = prev[c] + SHL32(q,7) - MULT16_16(beta,PSHR32(q,8));
} while (++c < C);
}
}
void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C)
{
int i, c;
/* Decode finer resolution */
for (i=start;i<end;i++)
{
if (fine_quant[i] <= 0)
continue;
c=0;
do {
int q2;
opus_val16 offset;
q2 = ec_dec_bits(dec, fine_quant[i]);
#ifdef FIXED_POINT
offset = SUB16(SHR32(SHL32(EXTEND32(q2),DB_SHIFT)+QCONST16(.5f,DB_SHIFT),fine_quant[i]),QCONST16(.5f,DB_SHIFT));
#else
offset = (q2+.5f)*(1<<(14-fine_quant[i]))*(1.f/16384) - .5f;
#endif
oldEBands[i+c*m->nbEBands] += offset;
} while (++c < C);
}
}
void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C)
{
int i, prio, c;
/* Use up the remaining bits */
for (prio=0;prio<2;prio++)
{
for (i=start;i<end && bits_left>=C ;i++)
{
if (fine_quant[i] >= MAX_FINE_BITS || fine_priority[i]!=prio)
continue;
c=0;
do {
int q2;
opus_val16 offset;
q2 = ec_dec_bits(dec, 1);
#ifdef FIXED_POINT
offset = SHR16(SHL16(q2,DB_SHIFT)-QCONST16(.5f,DB_SHIFT),fine_quant[i]+1);
#else
offset = (q2-.5f)*(1<<(14-fine_quant[i]-1))*(1.f/16384);
#endif
oldEBands[i+c*m->nbEBands] += offset;
bits_left--;
} while (++c < C);
}
}
}
void amp2Log2(const CELTMode *m, int effEnd, int end,
celt_ener *bandE, opus_val16 *bandLogE, int C)
{
int c, i;
c=0;
do {
for (i=0;i<effEnd;i++)
{
bandLogE[i+c*m->nbEBands] =
celt_log2(bandE[i+c*m->nbEBands])
- SHL16((opus_val16)eMeans[i],6);
#ifdef FIXED_POINT
/* Compensate for bandE[] being Q12 but celt_log2() taking a Q14 input. */
bandLogE[i+c*m->nbEBands] += QCONST16(2.f, DB_SHIFT);
#endif
}
for (i=effEnd;i<end;i++)
bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
} while (++c < C);
}

View File

@@ -0,0 +1,66 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef QUANT_BANDS
#define QUANT_BANDS
#include "arch.h"
#include "modes.h"
#include "entenc.h"
#include "entdec.h"
#include "mathops.h"
#ifdef FIXED_POINT
extern const signed char eMeans[25];
#else
extern const opus_val16 eMeans[25];
#endif
void amp2Log2(const CELTMode *m, int effEnd, int end,
celt_ener *bandE, opus_val16 *bandLogE, int C);
void log2Amp(const CELTMode *m, int start, int end,
celt_ener *eBands, const opus_val16 *oldEBands, int C);
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
const opus_val16 *eBands, opus_val16 *oldEBands, opus_uint32 budget,
opus_val16 *error, ec_enc *enc, int C, int LM,
int nbAvailableBytes, int force_intra, opus_val32 *delayedIntra,
int two_pass, int loss_rate, int lfe);
void quant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, ec_enc *enc, int C);
void quant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, opus_val16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int C);
void unquant_coarse_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int intra, ec_dec *dec, int C, int LM);
void unquant_fine_energy(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, ec_dec *dec, int C);
void unquant_energy_finalise(const CELTMode *m, int start, int end, opus_val16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int C);
#endif /* QUANT_BANDS */

View File

@@ -0,0 +1,644 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include <math.h>
#include "modes.h"
#include "cwrs.h"
#include "arch.h"
#include "os_support.h"
#include "entcode.h"
#include "rate.h"
static const unsigned char LOG2_FRAC_TABLE[24]={
0,
8,13,
16,19,21,23,
24,26,27,28,29,30,31,32,
32,33,34,34,35,36,36,37,37
};
#ifdef CUSTOM_MODES
/*Determines if V(N,K) fits in a 32-bit unsigned integer.
N and K are themselves limited to 15 bits.*/
static int fits_in32(int _n, int _k)
{
static const opus_int16 maxN[15] = {
32767, 32767, 32767, 1476, 283, 109, 60, 40,
29, 24, 20, 18, 16, 14, 13};
static const opus_int16 maxK[15] = {
32767, 32767, 32767, 32767, 1172, 238, 95, 53,
36, 27, 22, 18, 16, 15, 13};
if (_n>=14)
{
if (_k>=14)
return 0;
else
return _n <= maxN[_k];
} else {
return _k <= maxK[_n];
}
}
void compute_pulse_cache(CELTMode *m, int LM)
{
int C;
int i;
int j;
int curr=0;
int nbEntries=0;
int entryN[100], entryK[100], entryI[100];
const opus_int16 *eBands = m->eBands;
PulseCache *cache = &m->cache;
opus_int16 *cindex;
unsigned char *bits;
unsigned char *cap;
cindex = (opus_int16 *)opus_alloc(sizeof(cache->index[0])*m->nbEBands*(LM+2));
cache->index = cindex;
/* Scan for all unique band sizes */
for (i=0;i<=LM+1;i++)
{
for (j=0;j<m->nbEBands;j++)
{
int k;
int N = (eBands[j+1]-eBands[j])<<i>>1;
cindex[i*m->nbEBands+j] = -1;
/* Find other bands that have the same size */
for (k=0;k<=i;k++)
{
int n;
for (n=0;n<m->nbEBands && (k!=i || n<j);n++)
{
if (N == (eBands[n+1]-eBands[n])<<k>>1)
{
cindex[i*m->nbEBands+j] = cindex[k*m->nbEBands+n];
break;
}
}
}
if (cache->index[i*m->nbEBands+j] == -1 && N!=0)
{
int K;
entryN[nbEntries] = N;
K = 0;
while (fits_in32(N,get_pulses(K+1)) && K<MAX_PSEUDO)
K++;
entryK[nbEntries] = K;
cindex[i*m->nbEBands+j] = curr;
entryI[nbEntries] = curr;
curr += K+1;
nbEntries++;
}
}
}
bits = (unsigned char *)opus_alloc(sizeof(unsigned char)*curr);
cache->bits = bits;
cache->size = curr;
/* Compute the cache for all unique sizes */
for (i=0;i<nbEntries;i++)
{
unsigned char *ptr = bits+entryI[i];
opus_int16 tmp[CELT_MAX_PULSES+1];
get_required_bits(tmp, entryN[i], get_pulses(entryK[i]), BITRES);
for (j=1;j<=entryK[i];j++)
ptr[j] = tmp[get_pulses(j)]-1;
ptr[0] = entryK[i];
}
/* Compute the maximum rate for each band at which we'll reliably use as
many bits as we ask for. */
cache->caps = cap = (unsigned char *)opus_alloc(sizeof(cache->caps[0])*(LM+1)*2*m->nbEBands);
for (i=0;i<=LM;i++)
{
for (C=1;C<=2;C++)
{
for (j=0;j<m->nbEBands;j++)
{
int N0;
int max_bits;
N0 = m->eBands[j+1]-m->eBands[j];
/* N=1 bands only have a sign bit and fine bits. */
if (N0<<i == 1)
max_bits = C*(1+MAX_FINE_BITS)<<BITRES;
else
{
const unsigned char *pcache;
opus_int32 num;
opus_int32 den;
int LM0;
int N;
int offset;
int ndof;
int qb;
int k;
LM0 = 0;
/* Even-sized bands bigger than N=2 can be split one more time.
As of commit 44203907 all bands >1 are even, including custom modes.*/
if (N0 > 2)
{
N0>>=1;
LM0--;
}
/* N0=1 bands can't be split down to N<2. */
else if (N0 <= 1)
{
LM0=IMIN(i,1);
N0<<=LM0;
}
/* Compute the cost for the lowest-level PVQ of a fully split
band. */
pcache = bits + cindex[(LM0+1)*m->nbEBands+j];
max_bits = pcache[pcache[0]]+1;
/* Add in the cost of coding regular splits. */
N = N0;
for(k=0;k<i-LM0;k++){
max_bits <<= 1;
/* Offset the number of qtheta bits by log2(N)/2
+ QTHETA_OFFSET compared to their "fair share" of
total/N */
offset = ((m->logN[j]+((LM0+k)<<BITRES))>>1)-QTHETA_OFFSET;
/* The number of qtheta bits we'll allocate if the remainder
is to be max_bits.
The average measured cost for theta is 0.89701 times qb,
approximated here as 459/512. */
num=459*(opus_int32)((2*N-1)*offset+max_bits);
den=((opus_int32)(2*N-1)<<9)-459;
qb = IMIN((num+(den>>1))/den, 57);
celt_assert(qb >= 0);
max_bits += qb;
N <<= 1;
}
/* Add in the cost of a stereo split, if necessary. */
if (C==2)
{
max_bits <<= 1;
offset = ((m->logN[j]+(i<<BITRES))>>1)-(N==2?QTHETA_OFFSET_TWOPHASE:QTHETA_OFFSET);
ndof = 2*N-1-(N==2);
/* The average measured cost for theta with the step PDF is
0.95164 times qb, approximated here as 487/512. */
num = (N==2?512:487)*(opus_int32)(max_bits+ndof*offset);
den = ((opus_int32)ndof<<9)-(N==2?512:487);
qb = IMIN((num+(den>>1))/den, (N==2?64:61));
celt_assert(qb >= 0);
max_bits += qb;
}
/* Add the fine bits we'll use. */
/* Compensate for the extra DoF in stereo */
ndof = C*N + ((C==2 && N>2) ? 1 : 0);
/* Offset the number of fine bits by log2(N)/2 + FINE_OFFSET
compared to their "fair share" of total/N */
offset = ((m->logN[j] + (i<<BITRES))>>1)-FINE_OFFSET;
/* N=2 is the only point that doesn't match the curve */
if (N==2)
offset += 1<<BITRES>>2;
/* The number of fine bits we'll allocate if the remainder is
to be max_bits. */
num = max_bits+ndof*offset;
den = (ndof-1)<<BITRES;
qb = IMIN((num+(den>>1))/den, MAX_FINE_BITS);
celt_assert(qb >= 0);
max_bits += C*qb<<BITRES;
}
max_bits = (4*max_bits/(C*((m->eBands[j+1]-m->eBands[j])<<i)))-64;
celt_assert(max_bits >= 0);
celt_assert(max_bits < 256);
*cap++ = (unsigned char)max_bits;
}
}
}
}
#endif /* CUSTOM_MODES */
#define ALLOC_STEPS 6
static OPUS_INLINE int interp_bits2pulses(const CELTMode *m, int start, int end, int skip_start,
const int *bits1, const int *bits2, const int *thresh, const int *cap, opus_int32 total, opus_int32 *_balance,
int skip_rsv, int *intensity, int intensity_rsv, int *dual_stereo, int dual_stereo_rsv, int *bits,
int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
{
opus_int32 psum;
int lo, hi;
int i, j;
int logM;
int stereo;
int codedBands=-1;
int alloc_floor;
opus_int32 left, percoeff;
int done;
opus_int32 balance;
SAVE_STACK;
alloc_floor = C<<BITRES;
stereo = C>1;
logM = LM<<BITRES;
lo = 0;
hi = 1<<ALLOC_STEPS;
for (i=0;i<ALLOC_STEPS;i++)
{
int mid = (lo+hi)>>1;
psum = 0;
done = 0;
for (j=end;j-->start;)
{
int tmp = bits1[j] + (mid*(opus_int32)bits2[j]>>ALLOC_STEPS);
if (tmp >= thresh[j] || done)
{
done = 1;
/* Don't allocate more than we can actually use */
psum += IMIN(tmp, cap[j]);
} else {
if (tmp >= alloc_floor)
psum += alloc_floor;
}
}
if (psum > total)
hi = mid;
else
lo = mid;
}
psum = 0;
/*printf ("interp bisection gave %d\n", lo);*/
done = 0;
for (j=end;j-->start;)
{
int tmp = bits1[j] + ((opus_int32)lo*bits2[j]>>ALLOC_STEPS);
if (tmp < thresh[j] && !done)
{
if (tmp >= alloc_floor)
tmp = alloc_floor;
else
tmp = 0;
} else
done = 1;
/* Don't allocate more than we can actually use */
tmp = IMIN(tmp, cap[j]);
bits[j] = tmp;
psum += tmp;
}
/* Decide which bands to skip, working backwards from the end. */
for (codedBands=end;;codedBands--)
{
int band_width;
int band_bits;
int rem;
j = codedBands-1;
/* Never skip the first band, nor a band that has been boosted by
dynalloc.
In the first case, we'd be coding a bit to signal we're going to waste
all the other bits.
In the second case, we'd be coding a bit to redistribute all the bits
we just signaled should be cocentrated in this band. */
if (j<=skip_start)
{
/* Give the bit we reserved to end skipping back. */
total += skip_rsv;
break;
}
/*Figure out how many left-over bits we would be adding to this band.
This can include bits we've stolen back from higher, skipped bands.*/
left = total-psum;
percoeff = celt_udiv(left, m->eBands[codedBands]-m->eBands[start]);
left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
rem = IMAX(left-(m->eBands[j]-m->eBands[start]),0);
band_width = m->eBands[codedBands]-m->eBands[j];
band_bits = (int)(bits[j] + percoeff*band_width + rem);
/*Only code a skip decision if we're above the threshold for this band.
Otherwise it is force-skipped.
This ensures that we have enough bits to code the skip flag.*/
if (band_bits >= IMAX(thresh[j], alloc_floor+(1<<BITRES)))
{
if (encode)
{
/*This if() block is the only part of the allocation function that
is not a mandatory part of the bitstream: any bands we choose to
skip here must be explicitly signaled.*/
int depth_threshold;
/*We choose a threshold with some hysteresis to keep bands from
fluctuating in and out, but we try not to fold below a certain point. */
if (codedBands > 17)
depth_threshold = j<prev ? 7 : 9;
else
depth_threshold = 0;
#ifdef FUZZING
if ((rand()&0x1) == 0)
#else
if (codedBands<=start+2 || (band_bits > (depth_threshold*band_width<<LM<<BITRES)>>4 && j<=signalBandwidth))
#endif
{
ec_enc_bit_logp(ec, 1, 1);
break;
}
ec_enc_bit_logp(ec, 0, 1);
} else if (ec_dec_bit_logp(ec, 1)) {
break;
}
/*We used a bit to skip this band.*/
psum += 1<<BITRES;
band_bits -= 1<<BITRES;
}
/*Reclaim the bits originally allocated to this band.*/
psum -= bits[j]+intensity_rsv;
if (intensity_rsv > 0)
intensity_rsv = LOG2_FRAC_TABLE[j-start];
psum += intensity_rsv;
if (band_bits >= alloc_floor)
{
/*If we have enough for a fine energy bit per channel, use it.*/
psum += alloc_floor;
bits[j] = alloc_floor;
} else {
/*Otherwise this band gets nothing at all.*/
bits[j] = 0;
}
}
celt_assert(codedBands > start);
/* Code the intensity and dual stereo parameters. */
if (intensity_rsv > 0)
{
if (encode)
{
*intensity = IMIN(*intensity, codedBands);
ec_enc_uint(ec, *intensity-start, codedBands+1-start);
}
else
*intensity = start+ec_dec_uint(ec, codedBands+1-start);
}
else
*intensity = 0;
if (*intensity <= start)
{
total += dual_stereo_rsv;
dual_stereo_rsv = 0;
}
if (dual_stereo_rsv > 0)
{
if (encode)
ec_enc_bit_logp(ec, *dual_stereo, 1);
else
*dual_stereo = ec_dec_bit_logp(ec, 1);
}
else
*dual_stereo = 0;
/* Allocate the remaining bits */
left = total-psum;
percoeff = celt_udiv(left, m->eBands[codedBands]-m->eBands[start]);
left -= (m->eBands[codedBands]-m->eBands[start])*percoeff;
for (j=start;j<codedBands;j++)
bits[j] += ((int)percoeff*(m->eBands[j+1]-m->eBands[j]));
for (j=start;j<codedBands;j++)
{
int tmp = (int)IMIN(left, m->eBands[j+1]-m->eBands[j]);
bits[j] += tmp;
left -= tmp;
}
/*for (j=0;j<end;j++)printf("%d ", bits[j]);printf("\n");*/
balance = 0;
for (j=start;j<codedBands;j++)
{
int N0, N, den;
int offset;
int NClogN;
opus_int32 excess, bit;
celt_assert(bits[j] >= 0);
N0 = m->eBands[j+1]-m->eBands[j];
N=N0<<LM;
bit = (opus_int32)bits[j]+balance;
if (N>1)
{
excess = MAX32(bit-cap[j],0);
bits[j] = bit-excess;
/* Compensate for the extra DoF in stereo */
den=(C*N+ ((C==2 && N>2 && !*dual_stereo && j<*intensity) ? 1 : 0));
NClogN = den*(m->logN[j] + logM);
/* Offset for the number of fine bits by log2(N)/2 + FINE_OFFSET
compared to their "fair share" of total/N */
offset = (NClogN>>1)-den*FINE_OFFSET;
/* N=2 is the only point that doesn't match the curve */
if (N==2)
offset += den<<BITRES>>2;
/* Changing the offset for allocating the second and third
fine energy bit */
if (bits[j] + offset < den*2<<BITRES)
offset += NClogN>>2;
else if (bits[j] + offset < den*3<<BITRES)
offset += NClogN>>3;
/* Divide with rounding */
ebits[j] = IMAX(0, (bits[j] + offset + (den<<(BITRES-1))));
ebits[j] = celt_udiv(ebits[j], den)>>BITRES;
/* Make sure not to bust */
if (C*ebits[j] > (bits[j]>>BITRES))
ebits[j] = bits[j] >> stereo >> BITRES;
/* More than that is useless because that's about as far as PVQ can go */
ebits[j] = IMIN(ebits[j], MAX_FINE_BITS);
/* If we rounded down or capped this band, make it a candidate for the
final fine energy pass */
fine_priority[j] = ebits[j]*(den<<BITRES) >= bits[j]+offset;
/* Remove the allocated fine bits; the rest are assigned to PVQ */
bits[j] -= C*ebits[j]<<BITRES;
} else {
/* For N=1, all bits go to fine energy except for a single sign bit */
excess = MAX32(0,bit-(C<<BITRES));
bits[j] = bit-excess;
ebits[j] = 0;
fine_priority[j] = 1;
}
/* Fine energy can't take advantage of the re-balancing in
quant_all_bands().
Instead, do the re-balancing here.*/
if(excess > 0)
{
int extra_fine;
int extra_bits;
extra_fine = IMIN(excess>>(stereo+BITRES),MAX_FINE_BITS-ebits[j]);
ebits[j] += extra_fine;
extra_bits = extra_fine*C<<BITRES;
fine_priority[j] = extra_bits >= excess-balance;
excess -= extra_bits;
}
balance = excess;
celt_assert(bits[j] >= 0);
celt_assert(ebits[j] >= 0);
}
/* Save any remaining bits over the cap for the rebalancing in
quant_all_bands(). */
*_balance = balance;
/* The skipped bands use all their bits for fine energy. */
for (;j<end;j++)
{
ebits[j] = bits[j] >> stereo >> BITRES;
celt_assert(C*ebits[j]<<BITRES == bits[j]);
bits[j] = 0;
fine_priority[j] = ebits[j]<1;
}
RESTORE_STACK;
return codedBands;
}
int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth)
{
int lo, hi, len, j;
int codedBands;
int skip_start;
int skip_rsv;
int intensity_rsv;
int dual_stereo_rsv;
VARDECL(int, bits1);
VARDECL(int, bits2);
VARDECL(int, thresh);
VARDECL(int, trim_offset);
SAVE_STACK;
total = IMAX(total, 0);
len = m->nbEBands;
skip_start = start;
/* Reserve a bit to signal the end of manually skipped bands. */
skip_rsv = total >= 1<<BITRES ? 1<<BITRES : 0;
total -= skip_rsv;
/* Reserve bits for the intensity and dual stereo parameters. */
intensity_rsv = dual_stereo_rsv = 0;
if (C==2)
{
intensity_rsv = LOG2_FRAC_TABLE[end-start];
if (intensity_rsv>total)
intensity_rsv = 0;
else
{
total -= intensity_rsv;
dual_stereo_rsv = total>=1<<BITRES ? 1<<BITRES : 0;
total -= dual_stereo_rsv;
}
}
ALLOC(bits1, len, int);
ALLOC(bits2, len, int);
ALLOC(thresh, len, int);
ALLOC(trim_offset, len, int);
for (j=start;j<end;j++)
{
/* Below this threshold, we're sure not to allocate any PVQ bits */
thresh[j] = IMAX((C)<<BITRES, (3*(m->eBands[j+1]-m->eBands[j])<<LM<<BITRES)>>4);
/* Tilt of the allocation curve */
trim_offset[j] = C*(m->eBands[j+1]-m->eBands[j])*(alloc_trim-5-LM)*(end-j-1)
*(1<<(LM+BITRES))>>6;
/* Giving less resolution to single-coefficient bands because they get
more benefit from having one coarse value per coefficient*/
if ((m->eBands[j+1]-m->eBands[j])<<LM==1)
trim_offset[j] -= C<<BITRES;
}
lo = 1;
hi = m->nbAllocVectors - 1;
do
{
int done = 0;
int psum = 0;
int mid = (lo+hi) >> 1;
for (j=end;j-->start;)
{
int bitsj;
int N = m->eBands[j+1]-m->eBands[j];
bitsj = C*N*m->allocVectors[mid*len+j]<<LM>>2;
if (bitsj > 0)
bitsj = IMAX(0, bitsj + trim_offset[j]);
bitsj += offsets[j];
if (bitsj >= thresh[j] || done)
{
done = 1;
/* Don't allocate more than we can actually use */
psum += IMIN(bitsj, cap[j]);
} else {
if (bitsj >= C<<BITRES)
psum += C<<BITRES;
}
}
if (psum > total)
hi = mid - 1;
else
lo = mid + 1;
/*printf ("lo = %d, hi = %d\n", lo, hi);*/
}
while (lo <= hi);
hi = lo--;
/*printf ("interp between %d and %d\n", lo, hi);*/
for (j=start;j<end;j++)
{
int bits1j, bits2j;
int N = m->eBands[j+1]-m->eBands[j];
bits1j = C*N*m->allocVectors[lo*len+j]<<LM>>2;
bits2j = hi>=m->nbAllocVectors ?
cap[j] : C*N*m->allocVectors[hi*len+j]<<LM>>2;
if (bits1j > 0)
bits1j = IMAX(0, bits1j + trim_offset[j]);
if (bits2j > 0)
bits2j = IMAX(0, bits2j + trim_offset[j]);
if (lo > 0)
bits1j += offsets[j];
bits2j += offsets[j];
if (offsets[j]>0)
skip_start = j;
bits2j = IMAX(0,bits2j-bits1j);
bits1[j] = bits1j;
bits2[j] = bits2j;
}
codedBands = interp_bits2pulses(m, start, end, skip_start, bits1, bits2, thresh, cap,
total, balance, skip_rsv, intensity, intensity_rsv, dual_stereo, dual_stereo_rsv,
pulses, ebits, fine_priority, C, LM, ec, encode, prev, signalBandwidth);
RESTORE_STACK;
return codedBands;
}

View File

@@ -0,0 +1,101 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef RATE_H
#define RATE_H
#define MAX_PSEUDO 40
#define LOG_MAX_PSEUDO 6
#define CELT_MAX_PULSES 128
#define MAX_FINE_BITS 8
#define FINE_OFFSET 21
#define QTHETA_OFFSET 4
#define QTHETA_OFFSET_TWOPHASE 16
#include "cwrs.h"
#include "modes.h"
void compute_pulse_cache(CELTMode *m, int LM);
static OPUS_INLINE int get_pulses(int i)
{
return i<8 ? i : (8 + (i&7)) << ((i>>3)-1);
}
static OPUS_INLINE int bits2pulses(const CELTMode *m, int band, int LM, int bits)
{
int i;
int lo, hi;
const unsigned char *cache;
LM++;
cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
lo = 0;
hi = cache[0];
bits--;
for (i=0;i<LOG_MAX_PSEUDO;i++)
{
int mid = (lo+hi+1)>>1;
/* OPT: Make sure this is implemented with a conditional move */
if ((int)cache[mid] >= bits)
hi = mid;
else
lo = mid;
}
if (bits- (lo == 0 ? -1 : (int)cache[lo]) <= (int)cache[hi]-bits)
return lo;
else
return hi;
}
static OPUS_INLINE int pulses2bits(const CELTMode *m, int band, int LM, int pulses)
{
const unsigned char *cache;
LM++;
cache = m->cache.bits + m->cache.index[LM*m->nbEBands+band];
return pulses == 0 ? 0 : cache[pulses]+1;
}
/** Compute the pulse allocation, i.e. how many pulses will go in each
* band.
@param m mode
@param offsets Requested increase or decrease in the number of bits for
each band
@param total Number of bands
@param pulses Number of pulses per band (returned)
@return Total number of bits allocated
*/
int clt_compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
opus_int32 total, opus_int32 *balance, int *pulses, int *ebits, int *fine_priority, int C, int LM, ec_ctx *ec, int encode, int prev, int signalBandwidth);
#endif

View File

@@ -0,0 +1,184 @@
/* Copyright (C) 2002-2003 Jean-Marc Valin
Copyright (C) 2007-2009 Xiph.Org Foundation */
/**
@file stack_alloc.h
@brief Temporary memory allocation on stack
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef STACK_ALLOC_H
#define STACK_ALLOC_H
#include "../opus_types.h"
#include "../opus_defines.h"
#if (!defined (VAR_ARRAYS) && !defined (USE_ALLOCA) && !defined (NONTHREADSAFE_PSEUDOSTACK))
#error "Opus requires one of VAR_ARRAYS, USE_ALLOCA, or NONTHREADSAFE_PSEUDOSTACK be defined to select the temporary allocation mode."
#endif
#ifdef USE_ALLOCA
# ifdef WIN32
# include <malloc.h>
# else
# ifdef HAVE_ALLOCA_H
# include <alloca.h>
# else
# include <stdlib.h>
# endif
# endif
#endif
/**
* @def ALIGN(stack, size)
*
* Aligns the stack to a 'size' boundary
*
* @param stack Stack
* @param size New size boundary
*/
/**
* @def PUSH(stack, size, type)
*
* Allocates 'size' elements of type 'type' on the stack
*
* @param stack Stack
* @param size Number of elements
* @param type Type of element
*/
/**
* @def VARDECL(var)
*
* Declare variable on stack
*
* @param var Variable to declare
*/
/**
* @def ALLOC(var, size, type)
*
* Allocate 'size' elements of 'type' on stack
*
* @param var Name of variable to allocate
* @param size Number of elements
* @param type Type of element
*/
#if defined(VAR_ARRAYS)
#define VARDECL(type, var)
#define ALLOC(var, size, type) type var[size]
#define SAVE_STACK
#define RESTORE_STACK
#define ALLOC_STACK
/* C99 does not allow VLAs of size zero */
#define ALLOC_NONE 1
#elif defined(USE_ALLOCA)
#define VARDECL(type, var) type *var
# ifdef WIN32
# define ALLOC(var, size, type) var = ((type*)_alloca(sizeof(type)*(size)))
# else
# define ALLOC(var, size, type) var = ((type*)alloca(sizeof(type)*(size)))
# endif
#define SAVE_STACK
#define RESTORE_STACK
#define ALLOC_STACK
#define ALLOC_NONE 0
#else
#ifdef CELT_C
char *scratch_ptr=0;
char *global_stack=0;
#else
extern char *global_stack;
extern char *scratch_ptr;
#endif /* CELT_C */
#ifdef ENABLE_VALGRIND
#include <valgrind/memcheck.h>
#ifdef CELT_C
char *global_stack_top=0;
#else
extern char *global_stack_top;
#endif /* CELT_C */
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (VALGRIND_MAKE_MEM_NOACCESS(stack, global_stack_top-stack),ALIGN((stack),sizeof(type)/sizeof(char)),VALGRIND_MAKE_MEM_UNDEFINED(stack, ((size)*sizeof(type)/sizeof(char))),(stack)+=(2*(size)*sizeof(type)/sizeof(char)),(type*)((stack)-(2*(size)*sizeof(type)/sizeof(char))))
#define RESTORE_STACK ((global_stack = _saved_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack))
#define ALLOC_STACK char *_saved_stack; ((global_stack = (global_stack==0) ? ((global_stack_top=opus_alloc_scratch(GLOBAL_STACK_SIZE*2)+(GLOBAL_STACK_SIZE*2))-(GLOBAL_STACK_SIZE*2)) : global_stack),VALGRIND_MAKE_MEM_NOACCESS(global_stack, global_stack_top-global_stack)); _saved_stack = global_stack;
#else
#define ALIGN(stack, size) ((stack) += ((size) - (long)(stack)) & ((size) - 1))
#define PUSH(stack, size, type) (ALIGN((stack),sizeof(type)/sizeof(char)),(stack)+=(size)*(sizeof(type)/sizeof(char)),(type*)((stack)-(size)*(sizeof(type)/sizeof(char))))
#if 0 /* Set this to 1 to instrument pseudostack usage */
#define RESTORE_STACK (printf("%ld %s:%d\n", global_stack-scratch_ptr, __FILE__, __LINE__),global_stack = _saved_stack)
#else
#define RESTORE_STACK (global_stack = _saved_stack)
#endif
#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? (scratch_ptr=opus_alloc_scratch(GLOBAL_STACK_SIZE)) : global_stack); _saved_stack = global_stack;
#endif /* ENABLE_VALGRIND */
#include "os_support.h"
#define VARDECL(type, var) type *var
#define ALLOC(var, size, type) var = PUSH(global_stack, size, type)
#define SAVE_STACK char *_saved_stack = global_stack;
#define ALLOC_NONE 0
#endif /* VAR_ARRAYS */
#ifdef ENABLE_VALGRIND
#include <valgrind/memcheck.h>
#define OPUS_CHECK_ARRAY(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
#define OPUS_CHECK_VALUE(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
#define OPUS_CHECK_ARRAY_COND(ptr, len) VALGRIND_CHECK_MEM_IS_DEFINED(ptr, len*sizeof(*ptr))
#define OPUS_CHECK_VALUE_COND(value) VALGRIND_CHECK_VALUE_IS_DEFINED(value)
#define OPUS_PRINT_INT(value) do {fprintf(stderr, #value " = %d at %s:%d\n", value, __FILE__, __LINE__);}while(0)
#define OPUS_FPRINTF fprintf
#else
static OPUS_INLINE int _opus_false(void) {return 0;}
#define OPUS_CHECK_ARRAY(ptr, len) _opus_false()
#define OPUS_CHECK_VALUE(value) _opus_false()
#define OPUS_PRINT_INT(value) do{}while(0)
#define OPUS_FPRINTF (void)
#endif
#endif /* STACK_ALLOC_H */

View File

@@ -0,0 +1,892 @@
/* The contents of this file was automatically generated by dump_modes.c
with arguments: 48000 960
It contains static definitions for some pre-defined modes. */
#include "modes.h"
#include "rate.h"
#ifdef HAVE_ARM_NE10
#define OVERRIDE_FFT 1
#include "static_modes_fixed_arm_ne10.h"
#endif
#ifndef DEF_WINDOW120
#define DEF_WINDOW120
static const opus_val16 window120[120] = {
2, 20, 55, 108, 178,
266, 372, 494, 635, 792,
966, 1157, 1365, 1590, 1831,
2089, 2362, 2651, 2956, 3276,
3611, 3961, 4325, 4703, 5094,
5499, 5916, 6346, 6788, 7241,
7705, 8179, 8663, 9156, 9657,
10167, 10684, 11207, 11736, 12271,
12810, 13353, 13899, 14447, 14997,
15547, 16098, 16648, 17197, 17744,
18287, 18827, 19363, 19893, 20418,
20936, 21447, 21950, 22445, 22931,
23407, 23874, 24330, 24774, 25208,
25629, 26039, 26435, 26819, 27190,
27548, 27893, 28224, 28541, 28845,
29135, 29411, 29674, 29924, 30160,
30384, 30594, 30792, 30977, 31151,
31313, 31463, 31602, 31731, 31849,
31958, 32057, 32148, 32229, 32303,
32370, 32429, 32481, 32528, 32568,
32604, 32634, 32661, 32683, 32701,
32717, 32729, 32740, 32748, 32754,
32758, 32762, 32764, 32766, 32767,
32767, 32767, 32767, 32767, 32767,
};
#endif
#ifndef DEF_LOGN400
#define DEF_LOGN400
static const opus_int16 logN400[21] = {
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
#endif
#ifndef DEF_PULSE_CACHE50
#define DEF_PULSE_CACHE50
static const opus_int16 cache_index50[105] = {
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
};
static const unsigned char cache_bits50[392] = {
40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
182, 234, };
static const unsigned char cache_caps50[168] = {
224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
140, 66, 40, };
#endif
#ifndef FFT_TWIDDLES48000_960
#define FFT_TWIDDLES48000_960
static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
{32767, 0}, {32766, -429},
{32757, -858}, {32743, -1287},
{32724, -1715}, {32698, -2143},
{32667, -2570}, {32631, -2998},
{32588, -3425}, {32541, -3851},
{32488, -4277}, {32429, -4701},
{32364, -5125}, {32295, -5548},
{32219, -5971}, {32138, -6393},
{32051, -6813}, {31960, -7231},
{31863, -7650}, {31760, -8067},
{31652, -8481}, {31539, -8895},
{31419, -9306}, {31294, -9716},
{31165, -10126}, {31030, -10532},
{30889, -10937}, {30743, -11340},
{30592, -11741}, {30436, -12141},
{30274, -12540}, {30107, -12935},
{29936, -13328}, {29758, -13718},
{29577, -14107}, {29390, -14493},
{29197, -14875}, {29000, -15257},
{28797, -15635}, {28590, -16010},
{28379, -16384}, {28162, -16753},
{27940, -17119}, {27714, -17484},
{27482, -17845}, {27246, -18205},
{27006, -18560}, {26760, -18911},
{26510, -19260}, {26257, -19606},
{25997, -19947}, {25734, -20286},
{25466, -20621}, {25194, -20952},
{24918, -21281}, {24637, -21605},
{24353, -21926}, {24063, -22242},
{23770, -22555}, {23473, -22865},
{23171, -23171}, {22866, -23472},
{22557, -23769}, {22244, -24063},
{21927, -24352}, {21606, -24636},
{21282, -24917}, {20954, -25194},
{20622, -25465}, {20288, -25733},
{19949, -25997}, {19607, -26255},
{19261, -26509}, {18914, -26760},
{18561, -27004}, {18205, -27246},
{17846, -27481}, {17485, -27713},
{17122, -27940}, {16755, -28162},
{16385, -28378}, {16012, -28590},
{15636, -28797}, {15258, -28999},
{14878, -29197}, {14494, -29389},
{14108, -29576}, {13720, -29757},
{13329, -29934}, {12937, -30107},
{12540, -30274}, {12142, -30435},
{11744, -30592}, {11342, -30743},
{10939, -30889}, {10534, -31030},
{10127, -31164}, {9718, -31294},
{9307, -31418}, {8895, -31537},
{8482, -31652}, {8067, -31759},
{7650, -31862}, {7233, -31960},
{6815, -32051}, {6393, -32138},
{5973, -32219}, {5549, -32294},
{5127, -32364}, {4703, -32429},
{4278, -32487}, {3852, -32541},
{3426, -32588}, {2999, -32630},
{2572, -32667}, {2144, -32698},
{1716, -32724}, {1287, -32742},
{860, -32757}, {430, -32766},
{0, -32767}, {-429, -32766},
{-858, -32757}, {-1287, -32743},
{-1715, -32724}, {-2143, -32698},
{-2570, -32667}, {-2998, -32631},
{-3425, -32588}, {-3851, -32541},
{-4277, -32488}, {-4701, -32429},
{-5125, -32364}, {-5548, -32295},
{-5971, -32219}, {-6393, -32138},
{-6813, -32051}, {-7231, -31960},
{-7650, -31863}, {-8067, -31760},
{-8481, -31652}, {-8895, -31539},
{-9306, -31419}, {-9716, -31294},
{-10126, -31165}, {-10532, -31030},
{-10937, -30889}, {-11340, -30743},
{-11741, -30592}, {-12141, -30436},
{-12540, -30274}, {-12935, -30107},
{-13328, -29936}, {-13718, -29758},
{-14107, -29577}, {-14493, -29390},
{-14875, -29197}, {-15257, -29000},
{-15635, -28797}, {-16010, -28590},
{-16384, -28379}, {-16753, -28162},
{-17119, -27940}, {-17484, -27714},
{-17845, -27482}, {-18205, -27246},
{-18560, -27006}, {-18911, -26760},
{-19260, -26510}, {-19606, -26257},
{-19947, -25997}, {-20286, -25734},
{-20621, -25466}, {-20952, -25194},
{-21281, -24918}, {-21605, -24637},
{-21926, -24353}, {-22242, -24063},
{-22555, -23770}, {-22865, -23473},
{-23171, -23171}, {-23472, -22866},
{-23769, -22557}, {-24063, -22244},
{-24352, -21927}, {-24636, -21606},
{-24917, -21282}, {-25194, -20954},
{-25465, -20622}, {-25733, -20288},
{-25997, -19949}, {-26255, -19607},
{-26509, -19261}, {-26760, -18914},
{-27004, -18561}, {-27246, -18205},
{-27481, -17846}, {-27713, -17485},
{-27940, -17122}, {-28162, -16755},
{-28378, -16385}, {-28590, -16012},
{-28797, -15636}, {-28999, -15258},
{-29197, -14878}, {-29389, -14494},
{-29576, -14108}, {-29757, -13720},
{-29934, -13329}, {-30107, -12937},
{-30274, -12540}, {-30435, -12142},
{-30592, -11744}, {-30743, -11342},
{-30889, -10939}, {-31030, -10534},
{-31164, -10127}, {-31294, -9718},
{-31418, -9307}, {-31537, -8895},
{-31652, -8482}, {-31759, -8067},
{-31862, -7650}, {-31960, -7233},
{-32051, -6815}, {-32138, -6393},
{-32219, -5973}, {-32294, -5549},
{-32364, -5127}, {-32429, -4703},
{-32487, -4278}, {-32541, -3852},
{-32588, -3426}, {-32630, -2999},
{-32667, -2572}, {-32698, -2144},
{-32724, -1716}, {-32742, -1287},
{-32757, -860}, {-32766, -430},
{-32767, 0}, {-32766, 429},
{-32757, 858}, {-32743, 1287},
{-32724, 1715}, {-32698, 2143},
{-32667, 2570}, {-32631, 2998},
{-32588, 3425}, {-32541, 3851},
{-32488, 4277}, {-32429, 4701},
{-32364, 5125}, {-32295, 5548},
{-32219, 5971}, {-32138, 6393},
{-32051, 6813}, {-31960, 7231},
{-31863, 7650}, {-31760, 8067},
{-31652, 8481}, {-31539, 8895},
{-31419, 9306}, {-31294, 9716},
{-31165, 10126}, {-31030, 10532},
{-30889, 10937}, {-30743, 11340},
{-30592, 11741}, {-30436, 12141},
{-30274, 12540}, {-30107, 12935},
{-29936, 13328}, {-29758, 13718},
{-29577, 14107}, {-29390, 14493},
{-29197, 14875}, {-29000, 15257},
{-28797, 15635}, {-28590, 16010},
{-28379, 16384}, {-28162, 16753},
{-27940, 17119}, {-27714, 17484},
{-27482, 17845}, {-27246, 18205},
{-27006, 18560}, {-26760, 18911},
{-26510, 19260}, {-26257, 19606},
{-25997, 19947}, {-25734, 20286},
{-25466, 20621}, {-25194, 20952},
{-24918, 21281}, {-24637, 21605},
{-24353, 21926}, {-24063, 22242},
{-23770, 22555}, {-23473, 22865},
{-23171, 23171}, {-22866, 23472},
{-22557, 23769}, {-22244, 24063},
{-21927, 24352}, {-21606, 24636},
{-21282, 24917}, {-20954, 25194},
{-20622, 25465}, {-20288, 25733},
{-19949, 25997}, {-19607, 26255},
{-19261, 26509}, {-18914, 26760},
{-18561, 27004}, {-18205, 27246},
{-17846, 27481}, {-17485, 27713},
{-17122, 27940}, {-16755, 28162},
{-16385, 28378}, {-16012, 28590},
{-15636, 28797}, {-15258, 28999},
{-14878, 29197}, {-14494, 29389},
{-14108, 29576}, {-13720, 29757},
{-13329, 29934}, {-12937, 30107},
{-12540, 30274}, {-12142, 30435},
{-11744, 30592}, {-11342, 30743},
{-10939, 30889}, {-10534, 31030},
{-10127, 31164}, {-9718, 31294},
{-9307, 31418}, {-8895, 31537},
{-8482, 31652}, {-8067, 31759},
{-7650, 31862}, {-7233, 31960},
{-6815, 32051}, {-6393, 32138},
{-5973, 32219}, {-5549, 32294},
{-5127, 32364}, {-4703, 32429},
{-4278, 32487}, {-3852, 32541},
{-3426, 32588}, {-2999, 32630},
{-2572, 32667}, {-2144, 32698},
{-1716, 32724}, {-1287, 32742},
{-860, 32757}, {-430, 32766},
{0, 32767}, {429, 32766},
{858, 32757}, {1287, 32743},
{1715, 32724}, {2143, 32698},
{2570, 32667}, {2998, 32631},
{3425, 32588}, {3851, 32541},
{4277, 32488}, {4701, 32429},
{5125, 32364}, {5548, 32295},
{5971, 32219}, {6393, 32138},
{6813, 32051}, {7231, 31960},
{7650, 31863}, {8067, 31760},
{8481, 31652}, {8895, 31539},
{9306, 31419}, {9716, 31294},
{10126, 31165}, {10532, 31030},
{10937, 30889}, {11340, 30743},
{11741, 30592}, {12141, 30436},
{12540, 30274}, {12935, 30107},
{13328, 29936}, {13718, 29758},
{14107, 29577}, {14493, 29390},
{14875, 29197}, {15257, 29000},
{15635, 28797}, {16010, 28590},
{16384, 28379}, {16753, 28162},
{17119, 27940}, {17484, 27714},
{17845, 27482}, {18205, 27246},
{18560, 27006}, {18911, 26760},
{19260, 26510}, {19606, 26257},
{19947, 25997}, {20286, 25734},
{20621, 25466}, {20952, 25194},
{21281, 24918}, {21605, 24637},
{21926, 24353}, {22242, 24063},
{22555, 23770}, {22865, 23473},
{23171, 23171}, {23472, 22866},
{23769, 22557}, {24063, 22244},
{24352, 21927}, {24636, 21606},
{24917, 21282}, {25194, 20954},
{25465, 20622}, {25733, 20288},
{25997, 19949}, {26255, 19607},
{26509, 19261}, {26760, 18914},
{27004, 18561}, {27246, 18205},
{27481, 17846}, {27713, 17485},
{27940, 17122}, {28162, 16755},
{28378, 16385}, {28590, 16012},
{28797, 15636}, {28999, 15258},
{29197, 14878}, {29389, 14494},
{29576, 14108}, {29757, 13720},
{29934, 13329}, {30107, 12937},
{30274, 12540}, {30435, 12142},
{30592, 11744}, {30743, 11342},
{30889, 10939}, {31030, 10534},
{31164, 10127}, {31294, 9718},
{31418, 9307}, {31537, 8895},
{31652, 8482}, {31759, 8067},
{31862, 7650}, {31960, 7233},
{32051, 6815}, {32138, 6393},
{32219, 5973}, {32294, 5549},
{32364, 5127}, {32429, 4703},
{32487, 4278}, {32541, 3852},
{32588, 3426}, {32630, 2999},
{32667, 2572}, {32698, 2144},
{32724, 1716}, {32742, 1287},
{32757, 860}, {32766, 430},
};
#ifndef FFT_BITREV480
#define FFT_BITREV480
static const opus_int16 fft_bitrev480[480] = {
0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
};
#endif
#ifndef FFT_BITREV240
#define FFT_BITREV240
static const opus_int16 fft_bitrev240[240] = {
0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
};
#endif
#ifndef FFT_BITREV120
#define FFT_BITREV120
static const opus_int16 fft_bitrev120[120] = {
0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
};
#endif
#ifndef FFT_BITREV60
#define FFT_BITREV60
static const opus_int16 fft_bitrev60[60] = {
0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
};
#endif
#ifndef FFT_STATE48000_960_0
#define FFT_STATE48000_960_0
static const kiss_fft_state fft_state48000_960_0 = {
480, /* nfft */
17476, /* scale */
8, /* scale_shift */
-1, /* shift */
{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev480, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_480,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_1
#define FFT_STATE48000_960_1
static const kiss_fft_state fft_state48000_960_1 = {
240, /* nfft */
17476, /* scale */
7, /* scale_shift */
1, /* shift */
{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev240, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_240,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_2
#define FFT_STATE48000_960_2
static const kiss_fft_state fft_state48000_960_2 = {
120, /* nfft */
17476, /* scale */
6, /* scale_shift */
2, /* shift */
{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev120, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_120,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_3
#define FFT_STATE48000_960_3
static const kiss_fft_state fft_state48000_960_3 = {
60, /* nfft */
17476, /* scale */
5, /* scale_shift */
3, /* shift */
{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev60, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_60,
#else
NULL,
#endif
};
#endif
#endif
#ifndef MDCT_TWIDDLES960
#define MDCT_TWIDDLES960
static const opus_val16 mdct_twiddles960[1800] = {
32767, 32767, 32767, 32766, 32765,
32763, 32761, 32759, 32756, 32753,
32750, 32746, 32742, 32738, 32733,
32728, 32722, 32717, 32710, 32704,
32697, 32690, 32682, 32674, 32666,
32657, 32648, 32639, 32629, 32619,
32609, 32598, 32587, 32576, 32564,
32552, 32539, 32526, 32513, 32500,
32486, 32472, 32457, 32442, 32427,
32411, 32395, 32379, 32362, 32345,
32328, 32310, 32292, 32274, 32255,
32236, 32217, 32197, 32177, 32157,
32136, 32115, 32093, 32071, 32049,
32027, 32004, 31981, 31957, 31933,
31909, 31884, 31859, 31834, 31809,
31783, 31756, 31730, 31703, 31676,
31648, 31620, 31592, 31563, 31534,
31505, 31475, 31445, 31415, 31384,
31353, 31322, 31290, 31258, 31226,
31193, 31160, 31127, 31093, 31059,
31025, 30990, 30955, 30920, 30884,
30848, 30812, 30775, 30738, 30701,
30663, 30625, 30587, 30548, 30509,
30470, 30430, 30390, 30350, 30309,
30269, 30227, 30186, 30144, 30102,
30059, 30016, 29973, 29930, 29886,
29842, 29797, 29752, 29707, 29662,
29616, 29570, 29524, 29477, 29430,
29383, 29335, 29287, 29239, 29190,
29142, 29092, 29043, 28993, 28943,
28892, 28842, 28791, 28739, 28688,
28636, 28583, 28531, 28478, 28425,
28371, 28317, 28263, 28209, 28154,
28099, 28044, 27988, 27932, 27876,
27820, 27763, 27706, 27648, 27591,
27533, 27474, 27416, 27357, 27298,
27238, 27178, 27118, 27058, 26997,
26936, 26875, 26814, 26752, 26690,
26628, 26565, 26502, 26439, 26375,
26312, 26247, 26183, 26119, 26054,
25988, 25923, 25857, 25791, 25725,
25658, 25592, 25524, 25457, 25389,
25322, 25253, 25185, 25116, 25047,
24978, 24908, 24838, 24768, 24698,
24627, 24557, 24485, 24414, 24342,
24270, 24198, 24126, 24053, 23980,
23907, 23834, 23760, 23686, 23612,
23537, 23462, 23387, 23312, 23237,
23161, 23085, 23009, 22932, 22856,
22779, 22701, 22624, 22546, 22468,
22390, 22312, 22233, 22154, 22075,
21996, 21916, 21836, 21756, 21676,
21595, 21515, 21434, 21352, 21271,
21189, 21107, 21025, 20943, 20860,
20777, 20694, 20611, 20528, 20444,
20360, 20276, 20192, 20107, 20022,
19937, 19852, 19767, 19681, 19595,
19509, 19423, 19336, 19250, 19163,
19076, 18988, 18901, 18813, 18725,
18637, 18549, 18460, 18372, 18283,
18194, 18104, 18015, 17925, 17835,
17745, 17655, 17565, 17474, 17383,
17292, 17201, 17110, 17018, 16927,
16835, 16743, 16650, 16558, 16465,
16372, 16279, 16186, 16093, 15999,
15906, 15812, 15718, 15624, 15529,
15435, 15340, 15245, 15150, 15055,
14960, 14864, 14769, 14673, 14577,
14481, 14385, 14288, 14192, 14095,
13998, 13901, 13804, 13706, 13609,
13511, 13414, 13316, 13218, 13119,
13021, 12923, 12824, 12725, 12626,
12527, 12428, 12329, 12230, 12130,
12030, 11930, 11831, 11730, 11630,
11530, 11430, 11329, 11228, 11128,
11027, 10926, 10824, 10723, 10622,
10520, 10419, 10317, 10215, 10113,
10011, 9909, 9807, 9704, 9602,
9499, 9397, 9294, 9191, 9088,
8985, 8882, 8778, 8675, 8572,
8468, 8364, 8261, 8157, 8053,
7949, 7845, 7741, 7637, 7532,
7428, 7323, 7219, 7114, 7009,
6905, 6800, 6695, 6590, 6485,
6380, 6274, 6169, 6064, 5958,
5853, 5747, 5642, 5536, 5430,
5325, 5219, 5113, 5007, 4901,
4795, 4689, 4583, 4476, 4370,
4264, 4157, 4051, 3945, 3838,
3732, 3625, 3518, 3412, 3305,
3198, 3092, 2985, 2878, 2771,
2664, 2558, 2451, 2344, 2237,
2130, 2023, 1916, 1809, 1702,
1594, 1487, 1380, 1273, 1166,
1059, 952, 844, 737, 630,
523, 416, 308, 201, 94,
-13, -121, -228, -335, -442,
-550, -657, -764, -871, -978,
-1086, -1193, -1300, -1407, -1514,
-1621, -1728, -1835, -1942, -2049,
-2157, -2263, -2370, -2477, -2584,
-2691, -2798, -2905, -3012, -3118,
-3225, -3332, -3439, -3545, -3652,
-3758, -3865, -3971, -4078, -4184,
-4290, -4397, -4503, -4609, -4715,
-4821, -4927, -5033, -5139, -5245,
-5351, -5457, -5562, -5668, -5774,
-5879, -5985, -6090, -6195, -6301,
-6406, -6511, -6616, -6721, -6826,
-6931, -7036, -7140, -7245, -7349,
-7454, -7558, -7663, -7767, -7871,
-7975, -8079, -8183, -8287, -8390,
-8494, -8597, -8701, -8804, -8907,
-9011, -9114, -9217, -9319, -9422,
-9525, -9627, -9730, -9832, -9934,
-10037, -10139, -10241, -10342, -10444,
-10546, -10647, -10748, -10850, -10951,
-11052, -11153, -11253, -11354, -11455,
-11555, -11655, -11756, -11856, -11955,
-12055, -12155, -12254, -12354, -12453,
-12552, -12651, -12750, -12849, -12947,
-13046, -13144, -13242, -13340, -13438,
-13536, -13633, -13731, -13828, -13925,
-14022, -14119, -14216, -14312, -14409,
-14505, -14601, -14697, -14793, -14888,
-14984, -15079, -15174, -15269, -15364,
-15459, -15553, -15647, -15741, -15835,
-15929, -16023, -16116, -16210, -16303,
-16396, -16488, -16581, -16673, -16766,
-16858, -16949, -17041, -17133, -17224,
-17315, -17406, -17497, -17587, -17678,
-17768, -17858, -17948, -18037, -18127,
-18216, -18305, -18394, -18483, -18571,
-18659, -18747, -18835, -18923, -19010,
-19098, -19185, -19271, -19358, -19444,
-19531, -19617, -19702, -19788, -19873,
-19959, -20043, -20128, -20213, -20297,
-20381, -20465, -20549, -20632, -20715,
-20798, -20881, -20963, -21046, -21128,
-21210, -21291, -21373, -21454, -21535,
-21616, -21696, -21776, -21856, -21936,
-22016, -22095, -22174, -22253, -22331,
-22410, -22488, -22566, -22643, -22721,
-22798, -22875, -22951, -23028, -23104,
-23180, -23256, -23331, -23406, -23481,
-23556, -23630, -23704, -23778, -23852,
-23925, -23998, -24071, -24144, -24216,
-24288, -24360, -24432, -24503, -24574,
-24645, -24716, -24786, -24856, -24926,
-24995, -25064, -25133, -25202, -25270,
-25339, -25406, -25474, -25541, -25608,
-25675, -25742, -25808, -25874, -25939,
-26005, -26070, -26135, -26199, -26264,
-26327, -26391, -26455, -26518, -26581,
-26643, -26705, -26767, -26829, -26891,
-26952, -27013, -27073, -27133, -27193,
-27253, -27312, -27372, -27430, -27489,
-27547, -27605, -27663, -27720, -27777,
-27834, -27890, -27946, -28002, -28058,
-28113, -28168, -28223, -28277, -28331,
-28385, -28438, -28491, -28544, -28596,
-28649, -28701, -28752, -28803, -28854,
-28905, -28955, -29006, -29055, -29105,
-29154, -29203, -29251, -29299, -29347,
-29395, -29442, -29489, -29535, -29582,
-29628, -29673, -29719, -29764, -29808,
-29853, -29897, -29941, -29984, -30027,
-30070, -30112, -30154, -30196, -30238,
-30279, -30320, -30360, -30400, -30440,
-30480, -30519, -30558, -30596, -30635,
-30672, -30710, -30747, -30784, -30821,
-30857, -30893, -30929, -30964, -30999,
-31033, -31068, -31102, -31135, -31168,
-31201, -31234, -31266, -31298, -31330,
-31361, -31392, -31422, -31453, -31483,
-31512, -31541, -31570, -31599, -31627,
-31655, -31682, -31710, -31737, -31763,
-31789, -31815, -31841, -31866, -31891,
-31915, -31939, -31963, -31986, -32010,
-32032, -32055, -32077, -32099, -32120,
-32141, -32162, -32182, -32202, -32222,
-32241, -32260, -32279, -32297, -32315,
-32333, -32350, -32367, -32383, -32399,
-32415, -32431, -32446, -32461, -32475,
-32489, -32503, -32517, -32530, -32542,
-32555, -32567, -32579, -32590, -32601,
-32612, -32622, -32632, -32641, -32651,
-32659, -32668, -32676, -32684, -32692,
-32699, -32706, -32712, -32718, -32724,
-32729, -32734, -32739, -32743, -32747,
-32751, -32754, -32757, -32760, -32762,
-32764, -32765, -32767, -32767, -32767,
32767, 32767, 32765, 32761, 32756,
32750, 32742, 32732, 32722, 32710,
32696, 32681, 32665, 32647, 32628,
32608, 32586, 32562, 32538, 32512,
32484, 32455, 32425, 32393, 32360,
32326, 32290, 32253, 32214, 32174,
32133, 32090, 32046, 32001, 31954,
31906, 31856, 31805, 31753, 31700,
31645, 31588, 31530, 31471, 31411,
31349, 31286, 31222, 31156, 31089,
31020, 30951, 30880, 30807, 30733,
30658, 30582, 30504, 30425, 30345,
30263, 30181, 30096, 30011, 29924,
29836, 29747, 29656, 29564, 29471,
29377, 29281, 29184, 29086, 28987,
28886, 28784, 28681, 28577, 28471,
28365, 28257, 28147, 28037, 27925,
27812, 27698, 27583, 27467, 27349,
27231, 27111, 26990, 26868, 26744,
26620, 26494, 26367, 26239, 26110,
25980, 25849, 25717, 25583, 25449,
25313, 25176, 25038, 24900, 24760,
24619, 24477, 24333, 24189, 24044,
23898, 23751, 23602, 23453, 23303,
23152, 22999, 22846, 22692, 22537,
22380, 22223, 22065, 21906, 21746,
21585, 21423, 21261, 21097, 20933,
20767, 20601, 20434, 20265, 20096,
19927, 19756, 19584, 19412, 19239,
19065, 18890, 18714, 18538, 18361,
18183, 18004, 17824, 17644, 17463,
17281, 17098, 16915, 16731, 16546,
16361, 16175, 15988, 15800, 15612,
15423, 15234, 15043, 14852, 14661,
14469, 14276, 14083, 13889, 13694,
13499, 13303, 13107, 12910, 12713,
12515, 12317, 12118, 11918, 11718,
11517, 11316, 11115, 10913, 10710,
10508, 10304, 10100, 9896, 9691,
9486, 9281, 9075, 8869, 8662,
8455, 8248, 8040, 7832, 7623,
7415, 7206, 6996, 6787, 6577,
6366, 6156, 5945, 5734, 5523,
5311, 5100, 4888, 4675, 4463,
4251, 4038, 3825, 3612, 3399,
3185, 2972, 2758, 2544, 2330,
2116, 1902, 1688, 1474, 1260,
1045, 831, 617, 402, 188,
-27, -241, -456, -670, -885,
-1099, -1313, -1528, -1742, -1956,
-2170, -2384, -2598, -2811, -3025,
-3239, -3452, -3665, -3878, -4091,
-4304, -4516, -4728, -4941, -5153,
-5364, -5576, -5787, -5998, -6209,
-6419, -6629, -6839, -7049, -7258,
-7467, -7676, -7884, -8092, -8300,
-8507, -8714, -8920, -9127, -9332,
-9538, -9743, -9947, -10151, -10355,
-10558, -10761, -10963, -11165, -11367,
-11568, -11768, -11968, -12167, -12366,
-12565, -12762, -12960, -13156, -13352,
-13548, -13743, -13937, -14131, -14324,
-14517, -14709, -14900, -15091, -15281,
-15470, -15659, -15847, -16035, -16221,
-16407, -16593, -16777, -16961, -17144,
-17326, -17508, -17689, -17869, -18049,
-18227, -18405, -18582, -18758, -18934,
-19108, -19282, -19455, -19627, -19799,
-19969, -20139, -20308, -20475, -20642,
-20809, -20974, -21138, -21301, -21464,
-21626, -21786, -21946, -22105, -22263,
-22420, -22575, -22730, -22884, -23037,
-23189, -23340, -23490, -23640, -23788,
-23935, -24080, -24225, -24369, -24512,
-24654, -24795, -24934, -25073, -25211,
-25347, -25482, -25617, -25750, -25882,
-26013, -26143, -26272, -26399, -26526,
-26651, -26775, -26898, -27020, -27141,
-27260, -27379, -27496, -27612, -27727,
-27841, -27953, -28065, -28175, -28284,
-28391, -28498, -28603, -28707, -28810,
-28911, -29012, -29111, -29209, -29305,
-29401, -29495, -29587, -29679, -29769,
-29858, -29946, -30032, -30118, -30201,
-30284, -30365, -30445, -30524, -30601,
-30677, -30752, -30825, -30897, -30968,
-31038, -31106, -31172, -31238, -31302,
-31365, -31426, -31486, -31545, -31602,
-31658, -31713, -31766, -31818, -31869,
-31918, -31966, -32012, -32058, -32101,
-32144, -32185, -32224, -32262, -32299,
-32335, -32369, -32401, -32433, -32463,
-32491, -32518, -32544, -32568, -32591,
-32613, -32633, -32652, -32669, -32685,
-32700, -32713, -32724, -32735, -32744,
-32751, -32757, -32762, -32766, -32767,
32767, 32764, 32755, 32741, 32720,
32694, 32663, 32626, 32583, 32535,
32481, 32421, 32356, 32286, 32209,
32128, 32041, 31948, 31850, 31747,
31638, 31523, 31403, 31278, 31148,
31012, 30871, 30724, 30572, 30415,
30253, 30086, 29913, 29736, 29553,
29365, 29172, 28974, 28771, 28564,
28351, 28134, 27911, 27684, 27452,
27216, 26975, 26729, 26478, 26223,
25964, 25700, 25432, 25159, 24882,
24601, 24315, 24026, 23732, 23434,
23133, 22827, 22517, 22204, 21886,
21565, 21240, 20912, 20580, 20244,
19905, 19563, 19217, 18868, 18516,
18160, 17802, 17440, 17075, 16708,
16338, 15964, 15588, 15210, 14829,
14445, 14059, 13670, 13279, 12886,
12490, 12093, 11693, 11291, 10888,
10482, 10075, 9666, 9255, 8843,
8429, 8014, 7597, 7180, 6760,
6340, 5919, 5496, 5073, 4649,
4224, 3798, 3372, 2945, 2517,
2090, 1661, 1233, 804, 375,
-54, -483, -911, -1340, -1768,
-2197, -2624, -3052, -3479, -3905,
-4330, -4755, -5179, -5602, -6024,
-6445, -6865, -7284, -7702, -8118,
-8533, -8946, -9358, -9768, -10177,
-10584, -10989, -11392, -11793, -12192,
-12589, -12984, -13377, -13767, -14155,
-14541, -14924, -15305, -15683, -16058,
-16430, -16800, -17167, -17531, -17892,
-18249, -18604, -18956, -19304, -19649,
-19990, -20329, -20663, -20994, -21322,
-21646, -21966, -22282, -22595, -22904,
-23208, -23509, -23806, -24099, -24387,
-24672, -24952, -25228, -25499, -25766,
-26029, -26288, -26541, -26791, -27035,
-27275, -27511, -27741, -27967, -28188,
-28405, -28616, -28823, -29024, -29221,
-29412, -29599, -29780, -29957, -30128,
-30294, -30455, -30611, -30761, -30906,
-31046, -31181, -31310, -31434, -31552,
-31665, -31773, -31875, -31972, -32063,
-32149, -32229, -32304, -32373, -32437,
-32495, -32547, -32594, -32635, -32671,
-32701, -32726, -32745, -32758, -32766,
32767, 32754, 32717, 32658, 32577,
32473, 32348, 32200, 32029, 31837,
31624, 31388, 31131, 30853, 30553,
30232, 29891, 29530, 29148, 28746,
28324, 27883, 27423, 26944, 26447,
25931, 25398, 24847, 24279, 23695,
23095, 22478, 21846, 21199, 20538,
19863, 19174, 18472, 17757, 17030,
16291, 15541, 14781, 14010, 13230,
12441, 11643, 10837, 10024, 9204,
8377, 7545, 6708, 5866, 5020,
4171, 3319, 2464, 1608, 751,
-107, -965, -1822, -2678, -3532,
-4383, -5232, -6077, -6918, -7754,
-8585, -9409, -10228, -11039, -11843,
-12639, -13426, -14204, -14972, -15730,
-16477, -17213, -17937, -18648, -19347,
-20033, -20705, -21363, -22006, -22634,
-23246, -23843, -24423, -24986, -25533,
-26062, -26573, -27066, -27540, -27995,
-28431, -28848, -29245, -29622, -29979,
-30315, -30630, -30924, -31197, -31449,
-31679, -31887, -32074, -32239, -32381,
-32501, -32600, -32675, -32729, -32759,
};
#endif
static const CELTMode mode48000_960_120 = {
48000, /* Fs */
120, /* overlap */
21, /* nbEBands */
21, /* effEBands */
{27853, 0, 4096, 8192, }, /* preemph */
eband5ms, /* eBands */
3, /* maxLM */
8, /* nbShortMdcts */
120, /* shortMdctSize */
11, /* nbAllocVectors */
band_allocation, /* allocVectors */
logN400, /* logN */
window120, /* window */
{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
};
/* List of all the available modes */
#define TOTAL_MODES 1
static const CELTMode * const static_mode_list[TOTAL_MODES] = {
&mode48000_960_120,
};

View File

@@ -0,0 +1,888 @@
/* The contents of this file was automatically generated by dump_modes.c
with arguments: 48000 960
It contains static definitions for some pre-defined modes. */
#include "modes.h"
#include "rate.h"
#ifdef HAVE_ARM_NE10
#define OVERRIDE_FFT 1
#include "static_modes_float_arm_ne10.h"
#endif
#ifndef DEF_WINDOW120
#define DEF_WINDOW120
static const opus_val16 window120[120] = {
6.7286966e-05f, 0.00060551348f, 0.0016815970f, 0.0032947962f, 0.0054439943f,
0.0081276923f, 0.011344001f, 0.015090633f, 0.019364886f, 0.024163635f,
0.029483315f, 0.035319905f, 0.041668911f, 0.048525347f, 0.055883718f,
0.063737999f, 0.072081616f, 0.080907428f, 0.090207705f, 0.099974111f,
0.11019769f, 0.12086883f, 0.13197729f, 0.14351214f, 0.15546177f,
0.16781389f, 0.18055550f, 0.19367290f, 0.20715171f, 0.22097682f,
0.23513243f, 0.24960208f, 0.26436860f, 0.27941419f, 0.29472040f,
0.31026818f, 0.32603788f, 0.34200931f, 0.35816177f, 0.37447407f,
0.39092462f, 0.40749142f, 0.42415215f, 0.44088423f, 0.45766484f,
0.47447104f, 0.49127978f, 0.50806798f, 0.52481261f, 0.54149077f,
0.55807973f, 0.57455701f, 0.59090049f, 0.60708841f, 0.62309951f,
0.63891306f, 0.65450896f, 0.66986776f, 0.68497077f, 0.69980010f,
0.71433873f, 0.72857055f, 0.74248043f, 0.75605424f, 0.76927895f,
0.78214257f, 0.79463430f, 0.80674445f, 0.81846456f, 0.82978733f,
0.84070669f, 0.85121779f, 0.86131698f, 0.87100183f, 0.88027111f,
0.88912479f, 0.89756398f, 0.90559094f, 0.91320904f, 0.92042270f,
0.92723738f, 0.93365955f, 0.93969656f, 0.94535671f, 0.95064907f,
0.95558353f, 0.96017067f, 0.96442171f, 0.96834849f, 0.97196334f,
0.97527906f, 0.97830883f, 0.98106616f, 0.98356480f, 0.98581869f,
0.98784191f, 0.98964856f, 0.99125274f, 0.99266849f, 0.99390969f,
0.99499004f, 0.99592297f, 0.99672162f, 0.99739874f, 0.99796667f,
0.99843728f, 0.99882195f, 0.99913147f, 0.99937606f, 0.99956527f,
0.99970802f, 0.99981248f, 0.99988613f, 0.99993565f, 0.99996697f,
0.99998518f, 0.99999457f, 0.99999859f, 0.99999982f, 1.0000000f,
};
#endif
#ifndef DEF_LOGN400
#define DEF_LOGN400
static const opus_int16 logN400[21] = {
0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8, 16, 16, 16, 21, 21, 24, 29, 34, 36, };
#endif
#ifndef DEF_PULSE_CACHE50
#define DEF_PULSE_CACHE50
static const opus_int16 cache_index50[105] = {
-1, -1, -1, -1, -1, -1, -1, -1, 0, 0, 0, 0, 41, 41, 41,
82, 82, 123, 164, 200, 222, 0, 0, 0, 0, 0, 0, 0, 0, 41,
41, 41, 41, 123, 123, 123, 164, 164, 240, 266, 283, 295, 41, 41, 41,
41, 41, 41, 41, 41, 123, 123, 123, 123, 240, 240, 240, 266, 266, 305,
318, 328, 336, 123, 123, 123, 123, 123, 123, 123, 123, 240, 240, 240, 240,
305, 305, 305, 318, 318, 343, 351, 358, 364, 240, 240, 240, 240, 240, 240,
240, 240, 305, 305, 305, 305, 343, 343, 343, 351, 351, 370, 376, 382, 387,
};
static const unsigned char cache_bits50[392] = {
40, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 40, 15, 23, 28,
31, 34, 36, 38, 39, 41, 42, 43, 44, 45, 46, 47, 47, 49, 50,
51, 52, 53, 54, 55, 55, 57, 58, 59, 60, 61, 62, 63, 63, 65,
66, 67, 68, 69, 70, 71, 71, 40, 20, 33, 41, 48, 53, 57, 61,
64, 66, 69, 71, 73, 75, 76, 78, 80, 82, 85, 87, 89, 91, 92,
94, 96, 98, 101, 103, 105, 107, 108, 110, 112, 114, 117, 119, 121, 123,
124, 126, 128, 40, 23, 39, 51, 60, 67, 73, 79, 83, 87, 91, 94,
97, 100, 102, 105, 107, 111, 115, 118, 121, 124, 126, 129, 131, 135, 139,
142, 145, 148, 150, 153, 155, 159, 163, 166, 169, 172, 174, 177, 179, 35,
28, 49, 65, 78, 89, 99, 107, 114, 120, 126, 132, 136, 141, 145, 149,
153, 159, 165, 171, 176, 180, 185, 189, 192, 199, 205, 211, 216, 220, 225,
229, 232, 239, 245, 251, 21, 33, 58, 79, 97, 112, 125, 137, 148, 157,
166, 174, 182, 189, 195, 201, 207, 217, 227, 235, 243, 251, 17, 35, 63,
86, 106, 123, 139, 152, 165, 177, 187, 197, 206, 214, 222, 230, 237, 250,
25, 31, 55, 75, 91, 105, 117, 128, 138, 146, 154, 161, 168, 174, 180,
185, 190, 200, 208, 215, 222, 229, 235, 240, 245, 255, 16, 36, 65, 89,
110, 128, 144, 159, 173, 185, 196, 207, 217, 226, 234, 242, 250, 11, 41,
74, 103, 128, 151, 172, 191, 209, 225, 241, 255, 9, 43, 79, 110, 138,
163, 186, 207, 227, 246, 12, 39, 71, 99, 123, 144, 164, 182, 198, 214,
228, 241, 253, 9, 44, 81, 113, 142, 168, 192, 214, 235, 255, 7, 49,
90, 127, 160, 191, 220, 247, 6, 51, 95, 134, 170, 203, 234, 7, 47,
87, 123, 155, 184, 212, 237, 6, 52, 97, 137, 174, 208, 240, 5, 57,
106, 151, 192, 231, 5, 59, 111, 158, 202, 243, 5, 55, 103, 147, 187,
224, 5, 60, 113, 161, 206, 248, 4, 65, 122, 175, 224, 4, 67, 127,
182, 234, };
static const unsigned char cache_caps50[168] = {
224, 224, 224, 224, 224, 224, 224, 224, 160, 160, 160, 160, 185, 185, 185,
178, 178, 168, 134, 61, 37, 224, 224, 224, 224, 224, 224, 224, 224, 240,
240, 240, 240, 207, 207, 207, 198, 198, 183, 144, 66, 40, 160, 160, 160,
160, 160, 160, 160, 160, 185, 185, 185, 185, 193, 193, 193, 183, 183, 172,
138, 64, 38, 240, 240, 240, 240, 240, 240, 240, 240, 207, 207, 207, 207,
204, 204, 204, 193, 193, 180, 143, 66, 40, 185, 185, 185, 185, 185, 185,
185, 185, 193, 193, 193, 193, 193, 193, 193, 183, 183, 172, 138, 65, 39,
207, 207, 207, 207, 207, 207, 207, 207, 204, 204, 204, 204, 201, 201, 201,
188, 188, 176, 141, 66, 40, 193, 193, 193, 193, 193, 193, 193, 193, 193,
193, 193, 193, 194, 194, 194, 184, 184, 173, 139, 65, 39, 204, 204, 204,
204, 204, 204, 204, 204, 201, 201, 201, 201, 198, 198, 198, 187, 187, 175,
140, 66, 40, };
#endif
#ifndef FFT_TWIDDLES48000_960
#define FFT_TWIDDLES48000_960
static const kiss_twiddle_cpx fft_twiddles48000_960[480] = {
{1.0000000f, -0.0000000f}, {0.99991433f, -0.013089596f},
{0.99965732f, -0.026176948f}, {0.99922904f, -0.039259816f},
{0.99862953f, -0.052335956f}, {0.99785892f, -0.065403129f},
{0.99691733f, -0.078459096f}, {0.99580493f, -0.091501619f},
{0.99452190f, -0.10452846f}, {0.99306846f, -0.11753740f},
{0.99144486f, -0.13052619f}, {0.98965139f, -0.14349262f},
{0.98768834f, -0.15643447f}, {0.98555606f, -0.16934950f},
{0.98325491f, -0.18223553f}, {0.98078528f, -0.19509032f},
{0.97814760f, -0.20791169f}, {0.97534232f, -0.22069744f},
{0.97236992f, -0.23344536f}, {0.96923091f, -0.24615329f},
{0.96592583f, -0.25881905f}, {0.96245524f, -0.27144045f},
{0.95881973f, -0.28401534f}, {0.95501994f, -0.29654157f},
{0.95105652f, -0.30901699f}, {0.94693013f, -0.32143947f},
{0.94264149f, -0.33380686f}, {0.93819134f, -0.34611706f},
{0.93358043f, -0.35836795f}, {0.92880955f, -0.37055744f},
{0.92387953f, -0.38268343f}, {0.91879121f, -0.39474386f},
{0.91354546f, -0.40673664f}, {0.90814317f, -0.41865974f},
{0.90258528f, -0.43051110f}, {0.89687274f, -0.44228869f},
{0.89100652f, -0.45399050f}, {0.88498764f, -0.46561452f},
{0.87881711f, -0.47715876f}, {0.87249601f, -0.48862124f},
{0.86602540f, -0.50000000f}, {0.85940641f, -0.51129309f},
{0.85264016f, -0.52249856f}, {0.84572782f, -0.53361452f},
{0.83867057f, -0.54463904f}, {0.83146961f, -0.55557023f},
{0.82412619f, -0.56640624f}, {0.81664156f, -0.57714519f},
{0.80901699f, -0.58778525f}, {0.80125381f, -0.59832460f},
{0.79335334f, -0.60876143f}, {0.78531693f, -0.61909395f},
{0.77714596f, -0.62932039f}, {0.76884183f, -0.63943900f},
{0.76040597f, -0.64944805f}, {0.75183981f, -0.65934582f},
{0.74314483f, -0.66913061f}, {0.73432251f, -0.67880075f},
{0.72537437f, -0.68835458f}, {0.71630194f, -0.69779046f},
{0.70710678f, -0.70710678f}, {0.69779046f, -0.71630194f},
{0.68835458f, -0.72537437f}, {0.67880075f, -0.73432251f},
{0.66913061f, -0.74314483f}, {0.65934582f, -0.75183981f},
{0.64944805f, -0.76040597f}, {0.63943900f, -0.76884183f},
{0.62932039f, -0.77714596f}, {0.61909395f, -0.78531693f},
{0.60876143f, -0.79335334f}, {0.59832460f, -0.80125381f},
{0.58778525f, -0.80901699f}, {0.57714519f, -0.81664156f},
{0.56640624f, -0.82412619f}, {0.55557023f, -0.83146961f},
{0.54463904f, -0.83867057f}, {0.53361452f, -0.84572782f},
{0.52249856f, -0.85264016f}, {0.51129309f, -0.85940641f},
{0.50000000f, -0.86602540f}, {0.48862124f, -0.87249601f},
{0.47715876f, -0.87881711f}, {0.46561452f, -0.88498764f},
{0.45399050f, -0.89100652f}, {0.44228869f, -0.89687274f},
{0.43051110f, -0.90258528f}, {0.41865974f, -0.90814317f},
{0.40673664f, -0.91354546f}, {0.39474386f, -0.91879121f},
{0.38268343f, -0.92387953f}, {0.37055744f, -0.92880955f},
{0.35836795f, -0.93358043f}, {0.34611706f, -0.93819134f},
{0.33380686f, -0.94264149f}, {0.32143947f, -0.94693013f},
{0.30901699f, -0.95105652f}, {0.29654157f, -0.95501994f},
{0.28401534f, -0.95881973f}, {0.27144045f, -0.96245524f},
{0.25881905f, -0.96592583f}, {0.24615329f, -0.96923091f},
{0.23344536f, -0.97236992f}, {0.22069744f, -0.97534232f},
{0.20791169f, -0.97814760f}, {0.19509032f, -0.98078528f},
{0.18223553f, -0.98325491f}, {0.16934950f, -0.98555606f},
{0.15643447f, -0.98768834f}, {0.14349262f, -0.98965139f},
{0.13052619f, -0.99144486f}, {0.11753740f, -0.99306846f},
{0.10452846f, -0.99452190f}, {0.091501619f, -0.99580493f},
{0.078459096f, -0.99691733f}, {0.065403129f, -0.99785892f},
{0.052335956f, -0.99862953f}, {0.039259816f, -0.99922904f},
{0.026176948f, -0.99965732f}, {0.013089596f, -0.99991433f},
{6.1230318e-17f, -1.0000000f}, {-0.013089596f, -0.99991433f},
{-0.026176948f, -0.99965732f}, {-0.039259816f, -0.99922904f},
{-0.052335956f, -0.99862953f}, {-0.065403129f, -0.99785892f},
{-0.078459096f, -0.99691733f}, {-0.091501619f, -0.99580493f},
{-0.10452846f, -0.99452190f}, {-0.11753740f, -0.99306846f},
{-0.13052619f, -0.99144486f}, {-0.14349262f, -0.98965139f},
{-0.15643447f, -0.98768834f}, {-0.16934950f, -0.98555606f},
{-0.18223553f, -0.98325491f}, {-0.19509032f, -0.98078528f},
{-0.20791169f, -0.97814760f}, {-0.22069744f, -0.97534232f},
{-0.23344536f, -0.97236992f}, {-0.24615329f, -0.96923091f},
{-0.25881905f, -0.96592583f}, {-0.27144045f, -0.96245524f},
{-0.28401534f, -0.95881973f}, {-0.29654157f, -0.95501994f},
{-0.30901699f, -0.95105652f}, {-0.32143947f, -0.94693013f},
{-0.33380686f, -0.94264149f}, {-0.34611706f, -0.93819134f},
{-0.35836795f, -0.93358043f}, {-0.37055744f, -0.92880955f},
{-0.38268343f, -0.92387953f}, {-0.39474386f, -0.91879121f},
{-0.40673664f, -0.91354546f}, {-0.41865974f, -0.90814317f},
{-0.43051110f, -0.90258528f}, {-0.44228869f, -0.89687274f},
{-0.45399050f, -0.89100652f}, {-0.46561452f, -0.88498764f},
{-0.47715876f, -0.87881711f}, {-0.48862124f, -0.87249601f},
{-0.50000000f, -0.86602540f}, {-0.51129309f, -0.85940641f},
{-0.52249856f, -0.85264016f}, {-0.53361452f, -0.84572782f},
{-0.54463904f, -0.83867057f}, {-0.55557023f, -0.83146961f},
{-0.56640624f, -0.82412619f}, {-0.57714519f, -0.81664156f},
{-0.58778525f, -0.80901699f}, {-0.59832460f, -0.80125381f},
{-0.60876143f, -0.79335334f}, {-0.61909395f, -0.78531693f},
{-0.62932039f, -0.77714596f}, {-0.63943900f, -0.76884183f},
{-0.64944805f, -0.76040597f}, {-0.65934582f, -0.75183981f},
{-0.66913061f, -0.74314483f}, {-0.67880075f, -0.73432251f},
{-0.68835458f, -0.72537437f}, {-0.69779046f, -0.71630194f},
{-0.70710678f, -0.70710678f}, {-0.71630194f, -0.69779046f},
{-0.72537437f, -0.68835458f}, {-0.73432251f, -0.67880075f},
{-0.74314483f, -0.66913061f}, {-0.75183981f, -0.65934582f},
{-0.76040597f, -0.64944805f}, {-0.76884183f, -0.63943900f},
{-0.77714596f, -0.62932039f}, {-0.78531693f, -0.61909395f},
{-0.79335334f, -0.60876143f}, {-0.80125381f, -0.59832460f},
{-0.80901699f, -0.58778525f}, {-0.81664156f, -0.57714519f},
{-0.82412619f, -0.56640624f}, {-0.83146961f, -0.55557023f},
{-0.83867057f, -0.54463904f}, {-0.84572782f, -0.53361452f},
{-0.85264016f, -0.52249856f}, {-0.85940641f, -0.51129309f},
{-0.86602540f, -0.50000000f}, {-0.87249601f, -0.48862124f},
{-0.87881711f, -0.47715876f}, {-0.88498764f, -0.46561452f},
{-0.89100652f, -0.45399050f}, {-0.89687274f, -0.44228869f},
{-0.90258528f, -0.43051110f}, {-0.90814317f, -0.41865974f},
{-0.91354546f, -0.40673664f}, {-0.91879121f, -0.39474386f},
{-0.92387953f, -0.38268343f}, {-0.92880955f, -0.37055744f},
{-0.93358043f, -0.35836795f}, {-0.93819134f, -0.34611706f},
{-0.94264149f, -0.33380686f}, {-0.94693013f, -0.32143947f},
{-0.95105652f, -0.30901699f}, {-0.95501994f, -0.29654157f},
{-0.95881973f, -0.28401534f}, {-0.96245524f, -0.27144045f},
{-0.96592583f, -0.25881905f}, {-0.96923091f, -0.24615329f},
{-0.97236992f, -0.23344536f}, {-0.97534232f, -0.22069744f},
{-0.97814760f, -0.20791169f}, {-0.98078528f, -0.19509032f},
{-0.98325491f, -0.18223553f}, {-0.98555606f, -0.16934950f},
{-0.98768834f, -0.15643447f}, {-0.98965139f, -0.14349262f},
{-0.99144486f, -0.13052619f}, {-0.99306846f, -0.11753740f},
{-0.99452190f, -0.10452846f}, {-0.99580493f, -0.091501619f},
{-0.99691733f, -0.078459096f}, {-0.99785892f, -0.065403129f},
{-0.99862953f, -0.052335956f}, {-0.99922904f, -0.039259816f},
{-0.99965732f, -0.026176948f}, {-0.99991433f, -0.013089596f},
{-1.0000000f, -1.2246064e-16f}, {-0.99991433f, 0.013089596f},
{-0.99965732f, 0.026176948f}, {-0.99922904f, 0.039259816f},
{-0.99862953f, 0.052335956f}, {-0.99785892f, 0.065403129f},
{-0.99691733f, 0.078459096f}, {-0.99580493f, 0.091501619f},
{-0.99452190f, 0.10452846f}, {-0.99306846f, 0.11753740f},
{-0.99144486f, 0.13052619f}, {-0.98965139f, 0.14349262f},
{-0.98768834f, 0.15643447f}, {-0.98555606f, 0.16934950f},
{-0.98325491f, 0.18223553f}, {-0.98078528f, 0.19509032f},
{-0.97814760f, 0.20791169f}, {-0.97534232f, 0.22069744f},
{-0.97236992f, 0.23344536f}, {-0.96923091f, 0.24615329f},
{-0.96592583f, 0.25881905f}, {-0.96245524f, 0.27144045f},
{-0.95881973f, 0.28401534f}, {-0.95501994f, 0.29654157f},
{-0.95105652f, 0.30901699f}, {-0.94693013f, 0.32143947f},
{-0.94264149f, 0.33380686f}, {-0.93819134f, 0.34611706f},
{-0.93358043f, 0.35836795f}, {-0.92880955f, 0.37055744f},
{-0.92387953f, 0.38268343f}, {-0.91879121f, 0.39474386f},
{-0.91354546f, 0.40673664f}, {-0.90814317f, 0.41865974f},
{-0.90258528f, 0.43051110f}, {-0.89687274f, 0.44228869f},
{-0.89100652f, 0.45399050f}, {-0.88498764f, 0.46561452f},
{-0.87881711f, 0.47715876f}, {-0.87249601f, 0.48862124f},
{-0.86602540f, 0.50000000f}, {-0.85940641f, 0.51129309f},
{-0.85264016f, 0.52249856f}, {-0.84572782f, 0.53361452f},
{-0.83867057f, 0.54463904f}, {-0.83146961f, 0.55557023f},
{-0.82412619f, 0.56640624f}, {-0.81664156f, 0.57714519f},
{-0.80901699f, 0.58778525f}, {-0.80125381f, 0.59832460f},
{-0.79335334f, 0.60876143f}, {-0.78531693f, 0.61909395f},
{-0.77714596f, 0.62932039f}, {-0.76884183f, 0.63943900f},
{-0.76040597f, 0.64944805f}, {-0.75183981f, 0.65934582f},
{-0.74314483f, 0.66913061f}, {-0.73432251f, 0.67880075f},
{-0.72537437f, 0.68835458f}, {-0.71630194f, 0.69779046f},
{-0.70710678f, 0.70710678f}, {-0.69779046f, 0.71630194f},
{-0.68835458f, 0.72537437f}, {-0.67880075f, 0.73432251f},
{-0.66913061f, 0.74314483f}, {-0.65934582f, 0.75183981f},
{-0.64944805f, 0.76040597f}, {-0.63943900f, 0.76884183f},
{-0.62932039f, 0.77714596f}, {-0.61909395f, 0.78531693f},
{-0.60876143f, 0.79335334f}, {-0.59832460f, 0.80125381f},
{-0.58778525f, 0.80901699f}, {-0.57714519f, 0.81664156f},
{-0.56640624f, 0.82412619f}, {-0.55557023f, 0.83146961f},
{-0.54463904f, 0.83867057f}, {-0.53361452f, 0.84572782f},
{-0.52249856f, 0.85264016f}, {-0.51129309f, 0.85940641f},
{-0.50000000f, 0.86602540f}, {-0.48862124f, 0.87249601f},
{-0.47715876f, 0.87881711f}, {-0.46561452f, 0.88498764f},
{-0.45399050f, 0.89100652f}, {-0.44228869f, 0.89687274f},
{-0.43051110f, 0.90258528f}, {-0.41865974f, 0.90814317f},
{-0.40673664f, 0.91354546f}, {-0.39474386f, 0.91879121f},
{-0.38268343f, 0.92387953f}, {-0.37055744f, 0.92880955f},
{-0.35836795f, 0.93358043f}, {-0.34611706f, 0.93819134f},
{-0.33380686f, 0.94264149f}, {-0.32143947f, 0.94693013f},
{-0.30901699f, 0.95105652f}, {-0.29654157f, 0.95501994f},
{-0.28401534f, 0.95881973f}, {-0.27144045f, 0.96245524f},
{-0.25881905f, 0.96592583f}, {-0.24615329f, 0.96923091f},
{-0.23344536f, 0.97236992f}, {-0.22069744f, 0.97534232f},
{-0.20791169f, 0.97814760f}, {-0.19509032f, 0.98078528f},
{-0.18223553f, 0.98325491f}, {-0.16934950f, 0.98555606f},
{-0.15643447f, 0.98768834f}, {-0.14349262f, 0.98965139f},
{-0.13052619f, 0.99144486f}, {-0.11753740f, 0.99306846f},
{-0.10452846f, 0.99452190f}, {-0.091501619f, 0.99580493f},
{-0.078459096f, 0.99691733f}, {-0.065403129f, 0.99785892f},
{-0.052335956f, 0.99862953f}, {-0.039259816f, 0.99922904f},
{-0.026176948f, 0.99965732f}, {-0.013089596f, 0.99991433f},
{-1.8369095e-16f, 1.0000000f}, {0.013089596f, 0.99991433f},
{0.026176948f, 0.99965732f}, {0.039259816f, 0.99922904f},
{0.052335956f, 0.99862953f}, {0.065403129f, 0.99785892f},
{0.078459096f, 0.99691733f}, {0.091501619f, 0.99580493f},
{0.10452846f, 0.99452190f}, {0.11753740f, 0.99306846f},
{0.13052619f, 0.99144486f}, {0.14349262f, 0.98965139f},
{0.15643447f, 0.98768834f}, {0.16934950f, 0.98555606f},
{0.18223553f, 0.98325491f}, {0.19509032f, 0.98078528f},
{0.20791169f, 0.97814760f}, {0.22069744f, 0.97534232f},
{0.23344536f, 0.97236992f}, {0.24615329f, 0.96923091f},
{0.25881905f, 0.96592583f}, {0.27144045f, 0.96245524f},
{0.28401534f, 0.95881973f}, {0.29654157f, 0.95501994f},
{0.30901699f, 0.95105652f}, {0.32143947f, 0.94693013f},
{0.33380686f, 0.94264149f}, {0.34611706f, 0.93819134f},
{0.35836795f, 0.93358043f}, {0.37055744f, 0.92880955f},
{0.38268343f, 0.92387953f}, {0.39474386f, 0.91879121f},
{0.40673664f, 0.91354546f}, {0.41865974f, 0.90814317f},
{0.43051110f, 0.90258528f}, {0.44228869f, 0.89687274f},
{0.45399050f, 0.89100652f}, {0.46561452f, 0.88498764f},
{0.47715876f, 0.87881711f}, {0.48862124f, 0.87249601f},
{0.50000000f, 0.86602540f}, {0.51129309f, 0.85940641f},
{0.52249856f, 0.85264016f}, {0.53361452f, 0.84572782f},
{0.54463904f, 0.83867057f}, {0.55557023f, 0.83146961f},
{0.56640624f, 0.82412619f}, {0.57714519f, 0.81664156f},
{0.58778525f, 0.80901699f}, {0.59832460f, 0.80125381f},
{0.60876143f, 0.79335334f}, {0.61909395f, 0.78531693f},
{0.62932039f, 0.77714596f}, {0.63943900f, 0.76884183f},
{0.64944805f, 0.76040597f}, {0.65934582f, 0.75183981f},
{0.66913061f, 0.74314483f}, {0.67880075f, 0.73432251f},
{0.68835458f, 0.72537437f}, {0.69779046f, 0.71630194f},
{0.70710678f, 0.70710678f}, {0.71630194f, 0.69779046f},
{0.72537437f, 0.68835458f}, {0.73432251f, 0.67880075f},
{0.74314483f, 0.66913061f}, {0.75183981f, 0.65934582f},
{0.76040597f, 0.64944805f}, {0.76884183f, 0.63943900f},
{0.77714596f, 0.62932039f}, {0.78531693f, 0.61909395f},
{0.79335334f, 0.60876143f}, {0.80125381f, 0.59832460f},
{0.80901699f, 0.58778525f}, {0.81664156f, 0.57714519f},
{0.82412619f, 0.56640624f}, {0.83146961f, 0.55557023f},
{0.83867057f, 0.54463904f}, {0.84572782f, 0.53361452f},
{0.85264016f, 0.52249856f}, {0.85940641f, 0.51129309f},
{0.86602540f, 0.50000000f}, {0.87249601f, 0.48862124f},
{0.87881711f, 0.47715876f}, {0.88498764f, 0.46561452f},
{0.89100652f, 0.45399050f}, {0.89687274f, 0.44228869f},
{0.90258528f, 0.43051110f}, {0.90814317f, 0.41865974f},
{0.91354546f, 0.40673664f}, {0.91879121f, 0.39474386f},
{0.92387953f, 0.38268343f}, {0.92880955f, 0.37055744f},
{0.93358043f, 0.35836795f}, {0.93819134f, 0.34611706f},
{0.94264149f, 0.33380686f}, {0.94693013f, 0.32143947f},
{0.95105652f, 0.30901699f}, {0.95501994f, 0.29654157f},
{0.95881973f, 0.28401534f}, {0.96245524f, 0.27144045f},
{0.96592583f, 0.25881905f}, {0.96923091f, 0.24615329f},
{0.97236992f, 0.23344536f}, {0.97534232f, 0.22069744f},
{0.97814760f, 0.20791169f}, {0.98078528f, 0.19509032f},
{0.98325491f, 0.18223553f}, {0.98555606f, 0.16934950f},
{0.98768834f, 0.15643447f}, {0.98965139f, 0.14349262f},
{0.99144486f, 0.13052619f}, {0.99306846f, 0.11753740f},
{0.99452190f, 0.10452846f}, {0.99580493f, 0.091501619f},
{0.99691733f, 0.078459096f}, {0.99785892f, 0.065403129f},
{0.99862953f, 0.052335956f}, {0.99922904f, 0.039259816f},
{0.99965732f, 0.026176948f}, {0.99991433f, 0.013089596f},
};
#ifndef FFT_BITREV480
#define FFT_BITREV480
static const opus_int16 fft_bitrev480[480] = {
0, 96, 192, 288, 384, 32, 128, 224, 320, 416, 64, 160, 256, 352, 448,
8, 104, 200, 296, 392, 40, 136, 232, 328, 424, 72, 168, 264, 360, 456,
16, 112, 208, 304, 400, 48, 144, 240, 336, 432, 80, 176, 272, 368, 464,
24, 120, 216, 312, 408, 56, 152, 248, 344, 440, 88, 184, 280, 376, 472,
4, 100, 196, 292, 388, 36, 132, 228, 324, 420, 68, 164, 260, 356, 452,
12, 108, 204, 300, 396, 44, 140, 236, 332, 428, 76, 172, 268, 364, 460,
20, 116, 212, 308, 404, 52, 148, 244, 340, 436, 84, 180, 276, 372, 468,
28, 124, 220, 316, 412, 60, 156, 252, 348, 444, 92, 188, 284, 380, 476,
1, 97, 193, 289, 385, 33, 129, 225, 321, 417, 65, 161, 257, 353, 449,
9, 105, 201, 297, 393, 41, 137, 233, 329, 425, 73, 169, 265, 361, 457,
17, 113, 209, 305, 401, 49, 145, 241, 337, 433, 81, 177, 273, 369, 465,
25, 121, 217, 313, 409, 57, 153, 249, 345, 441, 89, 185, 281, 377, 473,
5, 101, 197, 293, 389, 37, 133, 229, 325, 421, 69, 165, 261, 357, 453,
13, 109, 205, 301, 397, 45, 141, 237, 333, 429, 77, 173, 269, 365, 461,
21, 117, 213, 309, 405, 53, 149, 245, 341, 437, 85, 181, 277, 373, 469,
29, 125, 221, 317, 413, 61, 157, 253, 349, 445, 93, 189, 285, 381, 477,
2, 98, 194, 290, 386, 34, 130, 226, 322, 418, 66, 162, 258, 354, 450,
10, 106, 202, 298, 394, 42, 138, 234, 330, 426, 74, 170, 266, 362, 458,
18, 114, 210, 306, 402, 50, 146, 242, 338, 434, 82, 178, 274, 370, 466,
26, 122, 218, 314, 410, 58, 154, 250, 346, 442, 90, 186, 282, 378, 474,
6, 102, 198, 294, 390, 38, 134, 230, 326, 422, 70, 166, 262, 358, 454,
14, 110, 206, 302, 398, 46, 142, 238, 334, 430, 78, 174, 270, 366, 462,
22, 118, 214, 310, 406, 54, 150, 246, 342, 438, 86, 182, 278, 374, 470,
30, 126, 222, 318, 414, 62, 158, 254, 350, 446, 94, 190, 286, 382, 478,
3, 99, 195, 291, 387, 35, 131, 227, 323, 419, 67, 163, 259, 355, 451,
11, 107, 203, 299, 395, 43, 139, 235, 331, 427, 75, 171, 267, 363, 459,
19, 115, 211, 307, 403, 51, 147, 243, 339, 435, 83, 179, 275, 371, 467,
27, 123, 219, 315, 411, 59, 155, 251, 347, 443, 91, 187, 283, 379, 475,
7, 103, 199, 295, 391, 39, 135, 231, 327, 423, 71, 167, 263, 359, 455,
15, 111, 207, 303, 399, 47, 143, 239, 335, 431, 79, 175, 271, 367, 463,
23, 119, 215, 311, 407, 55, 151, 247, 343, 439, 87, 183, 279, 375, 471,
31, 127, 223, 319, 415, 63, 159, 255, 351, 447, 95, 191, 287, 383, 479,
};
#endif
#ifndef FFT_BITREV240
#define FFT_BITREV240
static const opus_int16 fft_bitrev240[240] = {
0, 48, 96, 144, 192, 16, 64, 112, 160, 208, 32, 80, 128, 176, 224,
4, 52, 100, 148, 196, 20, 68, 116, 164, 212, 36, 84, 132, 180, 228,
8, 56, 104, 152, 200, 24, 72, 120, 168, 216, 40, 88, 136, 184, 232,
12, 60, 108, 156, 204, 28, 76, 124, 172, 220, 44, 92, 140, 188, 236,
1, 49, 97, 145, 193, 17, 65, 113, 161, 209, 33, 81, 129, 177, 225,
5, 53, 101, 149, 197, 21, 69, 117, 165, 213, 37, 85, 133, 181, 229,
9, 57, 105, 153, 201, 25, 73, 121, 169, 217, 41, 89, 137, 185, 233,
13, 61, 109, 157, 205, 29, 77, 125, 173, 221, 45, 93, 141, 189, 237,
2, 50, 98, 146, 194, 18, 66, 114, 162, 210, 34, 82, 130, 178, 226,
6, 54, 102, 150, 198, 22, 70, 118, 166, 214, 38, 86, 134, 182, 230,
10, 58, 106, 154, 202, 26, 74, 122, 170, 218, 42, 90, 138, 186, 234,
14, 62, 110, 158, 206, 30, 78, 126, 174, 222, 46, 94, 142, 190, 238,
3, 51, 99, 147, 195, 19, 67, 115, 163, 211, 35, 83, 131, 179, 227,
7, 55, 103, 151, 199, 23, 71, 119, 167, 215, 39, 87, 135, 183, 231,
11, 59, 107, 155, 203, 27, 75, 123, 171, 219, 43, 91, 139, 187, 235,
15, 63, 111, 159, 207, 31, 79, 127, 175, 223, 47, 95, 143, 191, 239,
};
#endif
#ifndef FFT_BITREV120
#define FFT_BITREV120
static const opus_int16 fft_bitrev120[120] = {
0, 24, 48, 72, 96, 8, 32, 56, 80, 104, 16, 40, 64, 88, 112,
4, 28, 52, 76, 100, 12, 36, 60, 84, 108, 20, 44, 68, 92, 116,
1, 25, 49, 73, 97, 9, 33, 57, 81, 105, 17, 41, 65, 89, 113,
5, 29, 53, 77, 101, 13, 37, 61, 85, 109, 21, 45, 69, 93, 117,
2, 26, 50, 74, 98, 10, 34, 58, 82, 106, 18, 42, 66, 90, 114,
6, 30, 54, 78, 102, 14, 38, 62, 86, 110, 22, 46, 70, 94, 118,
3, 27, 51, 75, 99, 11, 35, 59, 83, 107, 19, 43, 67, 91, 115,
7, 31, 55, 79, 103, 15, 39, 63, 87, 111, 23, 47, 71, 95, 119,
};
#endif
#ifndef FFT_BITREV60
#define FFT_BITREV60
static const opus_int16 fft_bitrev60[60] = {
0, 12, 24, 36, 48, 4, 16, 28, 40, 52, 8, 20, 32, 44, 56,
1, 13, 25, 37, 49, 5, 17, 29, 41, 53, 9, 21, 33, 45, 57,
2, 14, 26, 38, 50, 6, 18, 30, 42, 54, 10, 22, 34, 46, 58,
3, 15, 27, 39, 51, 7, 19, 31, 43, 55, 11, 23, 35, 47, 59,
};
#endif
#ifndef FFT_STATE48000_960_0
#define FFT_STATE48000_960_0
static const kiss_fft_state fft_state48000_960_0 = {
480, /* nfft */
0.002083333f, /* scale */
-1, /* shift */
{5, 96, 3, 32, 4, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev480, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_480,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_1
#define FFT_STATE48000_960_1
static const kiss_fft_state fft_state48000_960_1 = {
240, /* nfft */
0.004166667f, /* scale */
1, /* shift */
{5, 48, 3, 16, 4, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev240, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_240,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_2
#define FFT_STATE48000_960_2
static const kiss_fft_state fft_state48000_960_2 = {
120, /* nfft */
0.008333333f, /* scale */
2, /* shift */
{5, 24, 3, 8, 2, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev120, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_120,
#else
NULL,
#endif
};
#endif
#ifndef FFT_STATE48000_960_3
#define FFT_STATE48000_960_3
static const kiss_fft_state fft_state48000_960_3 = {
60, /* nfft */
0.016666667f, /* scale */
3, /* shift */
{5, 12, 3, 4, 4, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, }, /* factors */
fft_bitrev60, /* bitrev */
fft_twiddles48000_960, /* bitrev */
#ifdef OVERRIDE_FFT
(arch_fft_state *)&cfg_arch_60,
#else
NULL,
#endif
};
#endif
#endif
#ifndef MDCT_TWIDDLES960
#define MDCT_TWIDDLES960
static const opus_val16 mdct_twiddles960[1800] = {
0.99999994f, 0.99999321f, 0.99997580f, 0.99994773f, 0.99990886f,
0.99985933f, 0.99979913f, 0.99972820f, 0.99964654f, 0.99955416f,
0.99945110f, 0.99933738f, 0.99921292f, 0.99907774f, 0.99893188f,
0.99877530f, 0.99860805f, 0.99843007f, 0.99824142f, 0.99804211f,
0.99783206f, 0.99761140f, 0.99737996f, 0.99713790f, 0.99688518f,
0.99662173f, 0.99634761f, 0.99606287f, 0.99576741f, 0.99546129f,
0.99514455f, 0.99481714f, 0.99447906f, 0.99413031f, 0.99377096f,
0.99340093f, 0.99302030f, 0.99262899f, 0.99222708f, 0.99181455f,
0.99139136f, 0.99095762f, 0.99051321f, 0.99005818f, 0.98959261f,
0.98911643f, 0.98862964f, 0.98813224f, 0.98762429f, 0.98710573f,
0.98657662f, 0.98603696f, 0.98548669f, 0.98492593f, 0.98435456f,
0.98377270f, 0.98318028f, 0.98257732f, 0.98196387f, 0.98133987f,
0.98070538f, 0.98006040f, 0.97940493f, 0.97873890f, 0.97806245f,
0.97737551f, 0.97667813f, 0.97597027f, 0.97525197f, 0.97452319f,
0.97378403f, 0.97303438f, 0.97227436f, 0.97150391f, 0.97072303f,
0.96993178f, 0.96913016f, 0.96831810f, 0.96749574f, 0.96666300f,
0.96581990f, 0.96496642f, 0.96410263f, 0.96322852f, 0.96234411f,
0.96144938f, 0.96054435f, 0.95962906f, 0.95870346f, 0.95776761f,
0.95682150f, 0.95586514f, 0.95489854f, 0.95392174f, 0.95293468f,
0.95193744f, 0.95093000f, 0.94991243f, 0.94888461f, 0.94784665f,
0.94679856f, 0.94574034f, 0.94467193f, 0.94359344f, 0.94250488f,
0.94140619f, 0.94029742f, 0.93917859f, 0.93804967f, 0.93691075f,
0.93576175f, 0.93460274f, 0.93343377f, 0.93225473f, 0.93106574f,
0.92986679f, 0.92865789f, 0.92743903f, 0.92621022f, 0.92497152f,
0.92372292f, 0.92246443f, 0.92119598f, 0.91991776f, 0.91862965f,
0.91733170f, 0.91602397f, 0.91470635f, 0.91337901f, 0.91204184f,
0.91069490f, 0.90933824f, 0.90797186f, 0.90659571f, 0.90520984f,
0.90381432f, 0.90240908f, 0.90099424f, 0.89956969f, 0.89813554f,
0.89669174f, 0.89523834f, 0.89377540f, 0.89230281f, 0.89082074f,
0.88932908f, 0.88782793f, 0.88631725f, 0.88479710f, 0.88326746f,
0.88172835f, 0.88017982f, 0.87862182f, 0.87705445f, 0.87547767f,
0.87389153f, 0.87229604f, 0.87069118f, 0.86907703f, 0.86745358f,
0.86582077f, 0.86417878f, 0.86252749f, 0.86086690f, 0.85919720f,
0.85751826f, 0.85583007f, 0.85413277f, 0.85242635f, 0.85071075f,
0.84898609f, 0.84725231f, 0.84550947f, 0.84375757f, 0.84199661f,
0.84022665f, 0.83844769f, 0.83665979f, 0.83486289f, 0.83305705f,
0.83124226f, 0.82941860f, 0.82758605f, 0.82574469f, 0.82389444f,
0.82203537f, 0.82016748f, 0.81829083f, 0.81640542f, 0.81451124f,
0.81260836f, 0.81069672f, 0.80877650f, 0.80684757f, 0.80490994f,
0.80296379f, 0.80100900f, 0.79904562f, 0.79707366f, 0.79509324f,
0.79310423f, 0.79110676f, 0.78910083f, 0.78708643f, 0.78506362f,
0.78303236f, 0.78099275f, 0.77894479f, 0.77688843f, 0.77482378f,
0.77275085f, 0.77066964f, 0.76858020f, 0.76648247f, 0.76437658f,
0.76226246f, 0.76014024f, 0.75800985f, 0.75587130f, 0.75372469f,
0.75157005f, 0.74940729f, 0.74723655f, 0.74505776f, 0.74287105f,
0.74067634f, 0.73847371f, 0.73626316f, 0.73404479f, 0.73181850f,
0.72958434f, 0.72734243f, 0.72509271f, 0.72283524f, 0.72057003f,
0.71829706f, 0.71601641f, 0.71372813f, 0.71143216f, 0.70912862f,
0.70681745f, 0.70449871f, 0.70217246f, 0.69983864f, 0.69749737f,
0.69514859f, 0.69279242f, 0.69042879f, 0.68805778f, 0.68567938f,
0.68329364f, 0.68090063f, 0.67850029f, 0.67609268f, 0.67367786f,
0.67125577f, 0.66882652f, 0.66639012f, 0.66394657f, 0.66149592f,
0.65903819f, 0.65657341f, 0.65410155f, 0.65162271f, 0.64913690f,
0.64664418f, 0.64414448f, 0.64163786f, 0.63912445f, 0.63660413f,
0.63407701f, 0.63154310f, 0.62900239f, 0.62645501f, 0.62390089f,
0.62134010f, 0.61877263f, 0.61619854f, 0.61361790f, 0.61103064f,
0.60843682f, 0.60583651f, 0.60322970f, 0.60061646f, 0.59799677f,
0.59537065f, 0.59273821f, 0.59009939f, 0.58745426f, 0.58480281f,
0.58214509f, 0.57948118f, 0.57681108f, 0.57413477f, 0.57145232f,
0.56876373f, 0.56606907f, 0.56336832f, 0.56066155f, 0.55794877f,
0.55523002f, 0.55250537f, 0.54977477f, 0.54703826f, 0.54429591f,
0.54154772f, 0.53879374f, 0.53603399f, 0.53326851f, 0.53049731f,
0.52772039f, 0.52493787f, 0.52214974f, 0.51935595f, 0.51655668f,
0.51375180f, 0.51094145f, 0.50812566f, 0.50530440f, 0.50247771f,
0.49964568f, 0.49680826f, 0.49396557f, 0.49111754f, 0.48826426f,
0.48540577f, 0.48254207f, 0.47967321f, 0.47679919f, 0.47392011f,
0.47103590f, 0.46814668f, 0.46525243f, 0.46235323f, 0.45944905f,
0.45653993f, 0.45362595f, 0.45070711f, 0.44778344f, 0.44485497f,
0.44192174f, 0.43898380f, 0.43604112f, 0.43309379f, 0.43014181f,
0.42718524f, 0.42422408f, 0.42125839f, 0.41828820f, 0.41531351f,
0.41233435f, 0.40935081f, 0.40636289f, 0.40337059f, 0.40037400f,
0.39737311f, 0.39436796f, 0.39135858f, 0.38834500f, 0.38532731f,
0.38230544f, 0.37927949f, 0.37624949f, 0.37321547f, 0.37017745f,
0.36713544f, 0.36408952f, 0.36103970f, 0.35798600f, 0.35492846f,
0.35186714f, 0.34880206f, 0.34573323f, 0.34266070f, 0.33958447f,
0.33650464f, 0.33342120f, 0.33033419f, 0.32724363f, 0.32414958f,
0.32105204f, 0.31795108f, 0.31484672f, 0.31173897f, 0.30862790f,
0.30551350f, 0.30239585f, 0.29927495f, 0.29615086f, 0.29302359f,
0.28989318f, 0.28675964f, 0.28362307f, 0.28048345f, 0.27734083f,
0.27419522f, 0.27104670f, 0.26789525f, 0.26474094f, 0.26158381f,
0.25842386f, 0.25526115f, 0.25209570f, 0.24892756f, 0.24575676f,
0.24258332f, 0.23940729f, 0.23622867f, 0.23304754f, 0.22986393f,
0.22667783f, 0.22348931f, 0.22029841f, 0.21710514f, 0.21390954f,
0.21071166f, 0.20751151f, 0.20430915f, 0.20110460f, 0.19789790f,
0.19468907f, 0.19147816f, 0.18826519f, 0.18505022f, 0.18183327f,
0.17861435f, 0.17539354f, 0.17217083f, 0.16894630f, 0.16571994f,
0.16249183f, 0.15926196f, 0.15603039f, 0.15279715f, 0.14956227f,
0.14632578f, 0.14308774f, 0.13984816f, 0.13660708f, 0.13336454f,
0.13012058f, 0.12687522f, 0.12362850f, 0.12038045f, 0.11713112f,
0.11388054f, 0.11062872f, 0.10737573f, 0.10412160f, 0.10086634f,
0.097609997f, 0.094352618f, 0.091094226f, 0.087834857f, 0.084574550f,
0.081313334f, 0.078051247f, 0.074788325f, 0.071524605f, 0.068260118f,
0.064994894f, 0.061728980f, 0.058462404f, 0.055195201f, 0.051927410f,
0.048659060f, 0.045390189f, 0.042120833f, 0.038851023f, 0.035580799f,
0.032310195f, 0.029039243f, 0.025767982f, 0.022496443f, 0.019224664f,
0.015952680f, 0.012680525f, 0.0094082337f, 0.0061358409f, 0.0028633832f,
-0.00040910527f, -0.0036815894f, -0.0069540343f, -0.010226404f, -0.013498665f,
-0.016770782f, -0.020042717f, -0.023314439f, -0.026585912f, -0.029857099f,
-0.033127967f, -0.036398482f, -0.039668605f, -0.042938303f, -0.046207540f,
-0.049476285f, -0.052744497f, -0.056012146f, -0.059279196f, -0.062545612f,
-0.065811358f, -0.069076397f, -0.072340697f, -0.075604223f, -0.078866936f,
-0.082128808f, -0.085389800f, -0.088649876f, -0.091909006f, -0.095167145f,
-0.098424271f, -0.10168034f, -0.10493532f, -0.10818918f, -0.11144188f,
-0.11469338f, -0.11794366f, -0.12119267f, -0.12444039f, -0.12768677f,
-0.13093179f, -0.13417540f, -0.13741758f, -0.14065829f, -0.14389749f,
-0.14713514f, -0.15037122f, -0.15360570f, -0.15683852f, -0.16006967f,
-0.16329910f, -0.16652679f, -0.16975269f, -0.17297678f, -0.17619900f,
-0.17941935f, -0.18263777f, -0.18585424f, -0.18906870f, -0.19228116f,
-0.19549155f, -0.19869985f, -0.20190603f, -0.20511003f, -0.20831184f,
-0.21151142f, -0.21470875f, -0.21790376f, -0.22109644f, -0.22428675f,
-0.22747467f, -0.23066014f, -0.23384315f, -0.23702365f, -0.24020162f,
-0.24337701f, -0.24654980f, -0.24971995f, -0.25288740f, -0.25605217f,
-0.25921419f, -0.26237345f, -0.26552987f, -0.26868346f, -0.27183419f,
-0.27498198f, -0.27812684f, -0.28126872f, -0.28440759f, -0.28754342f,
-0.29067615f, -0.29380578f, -0.29693225f, -0.30005556f, -0.30317566f,
-0.30629250f, -0.30940607f, -0.31251630f, -0.31562322f, -0.31872672f,
-0.32182685f, -0.32492352f, -0.32801670f, -0.33110636f, -0.33419248f,
-0.33727503f, -0.34035397f, -0.34342924f, -0.34650084f, -0.34956875f,
-0.35263291f, -0.35569328f, -0.35874987f, -0.36180258f, -0.36485144f,
-0.36789638f, -0.37093741f, -0.37397444f, -0.37700745f, -0.38003644f,
-0.38306138f, -0.38608220f, -0.38909888f, -0.39211139f, -0.39511973f,
-0.39812380f, -0.40112361f, -0.40411916f, -0.40711036f, -0.41009718f,
-0.41307965f, -0.41605768f, -0.41903123f, -0.42200032f, -0.42496487f,
-0.42792490f, -0.43088034f, -0.43383113f, -0.43677729f, -0.43971881f,
-0.44265559f, -0.44558764f, -0.44851488f, -0.45143735f, -0.45435500f,
-0.45726776f, -0.46017563f, -0.46307856f, -0.46597654f, -0.46886954f,
-0.47175750f, -0.47464043f, -0.47751826f, -0.48039100f, -0.48325855f,
-0.48612097f, -0.48897815f, -0.49183011f, -0.49467680f, -0.49751821f,
-0.50035429f, -0.50318497f, -0.50601029f, -0.50883019f, -0.51164466f,
-0.51445359f, -0.51725709f, -0.52005500f, -0.52284735f, -0.52563411f,
-0.52841520f, -0.53119069f, -0.53396046f, -0.53672451f, -0.53948283f,
-0.54223537f, -0.54498214f, -0.54772300f, -0.55045801f, -0.55318713f,
-0.55591035f, -0.55862761f, -0.56133890f, -0.56404412f, -0.56674337f,
-0.56943649f, -0.57212353f, -0.57480448f, -0.57747924f, -0.58014780f,
-0.58281022f, -0.58546633f, -0.58811617f, -0.59075975f, -0.59339696f,
-0.59602785f, -0.59865236f, -0.60127044f, -0.60388207f, -0.60648727f,
-0.60908598f, -0.61167812f, -0.61426371f, -0.61684275f, -0.61941516f,
-0.62198097f, -0.62454009f, -0.62709254f, -0.62963831f, -0.63217729f,
-0.63470948f, -0.63723493f, -0.63975352f, -0.64226526f, -0.64477009f,
-0.64726806f, -0.64975911f, -0.65224314f, -0.65472025f, -0.65719032f,
-0.65965337f, -0.66210932f, -0.66455823f, -0.66700000f, -0.66943461f,
-0.67186207f, -0.67428231f, -0.67669535f, -0.67910111f, -0.68149966f,
-0.68389088f, -0.68627477f, -0.68865126f, -0.69102043f, -0.69338220f,
-0.69573659f, -0.69808346f, -0.70042288f, -0.70275480f, -0.70507920f,
-0.70739603f, -0.70970529f, -0.71200693f, -0.71430099f, -0.71658736f,
-0.71886611f, -0.72113711f, -0.72340041f, -0.72565591f, -0.72790372f,
-0.73014367f, -0.73237586f, -0.73460019f, -0.73681659f, -0.73902518f,
-0.74122584f, -0.74341851f, -0.74560326f, -0.74778003f, -0.74994880f,
-0.75210953f, -0.75426215f, -0.75640678f, -0.75854325f, -0.76067162f,
-0.76279181f, -0.76490390f, -0.76700771f, -0.76910341f, -0.77119076f,
-0.77326995f, -0.77534080f, -0.77740335f, -0.77945763f, -0.78150350f,
-0.78354102f, -0.78557014f, -0.78759086f, -0.78960317f, -0.79160696f,
-0.79360235f, -0.79558921f, -0.79756755f, -0.79953730f, -0.80149853f,
-0.80345118f, -0.80539525f, -0.80733067f, -0.80925739f, -0.81117553f,
-0.81308490f, -0.81498563f, -0.81687760f, -0.81876087f, -0.82063532f,
-0.82250100f, -0.82435787f, -0.82620591f, -0.82804507f, -0.82987541f,
-0.83169687f, -0.83350939f, -0.83531296f, -0.83710766f, -0.83889335f,
-0.84067005f, -0.84243774f, -0.84419644f, -0.84594607f, -0.84768665f,
-0.84941816f, -0.85114056f, -0.85285389f, -0.85455805f, -0.85625303f,
-0.85793889f, -0.85961550f, -0.86128294f, -0.86294121f, -0.86459017f,
-0.86622989f, -0.86786032f, -0.86948150f, -0.87109333f, -0.87269586f,
-0.87428904f, -0.87587279f, -0.87744725f, -0.87901229f, -0.88056785f,
-0.88211405f, -0.88365078f, -0.88517809f, -0.88669586f, -0.88820416f,
-0.88970292f, -0.89119220f, -0.89267188f, -0.89414203f, -0.89560264f,
-0.89705360f, -0.89849502f, -0.89992678f, -0.90134889f, -0.90276134f,
-0.90416414f, -0.90555727f, -0.90694070f, -0.90831441f, -0.90967834f,
-0.91103262f, -0.91237706f, -0.91371179f, -0.91503674f, -0.91635185f,
-0.91765714f, -0.91895264f, -0.92023826f, -0.92151409f, -0.92277998f,
-0.92403603f, -0.92528218f, -0.92651838f, -0.92774469f, -0.92896110f,
-0.93016750f, -0.93136400f, -0.93255049f, -0.93372697f, -0.93489349f,
-0.93604994f, -0.93719643f, -0.93833286f, -0.93945926f, -0.94057560f,
-0.94168180f, -0.94277799f, -0.94386405f, -0.94494003f, -0.94600588f,
-0.94706154f, -0.94810712f, -0.94914252f, -0.95016778f, -0.95118284f,
-0.95218778f, -0.95318246f, -0.95416695f, -0.95514119f, -0.95610523f,
-0.95705903f, -0.95800257f, -0.95893586f, -0.95985889f, -0.96077162f,
-0.96167403f, -0.96256620f, -0.96344805f, -0.96431959f, -0.96518075f,
-0.96603161f, -0.96687216f, -0.96770233f, -0.96852213f, -0.96933156f,
-0.97013056f, -0.97091925f, -0.97169751f, -0.97246534f, -0.97322279f,
-0.97396982f, -0.97470641f, -0.97543252f, -0.97614825f, -0.97685349f,
-0.97754824f, -0.97823256f, -0.97890645f, -0.97956979f, -0.98022264f,
-0.98086500f, -0.98149687f, -0.98211825f, -0.98272908f, -0.98332942f,
-0.98391914f, -0.98449844f, -0.98506713f, -0.98562527f, -0.98617285f,
-0.98670989f, -0.98723638f, -0.98775226f, -0.98825759f, -0.98875231f,
-0.98923647f, -0.98971003f, -0.99017298f, -0.99062532f, -0.99106705f,
-0.99149817f, -0.99191868f, -0.99232858f, -0.99272782f, -0.99311644f,
-0.99349445f, -0.99386179f, -0.99421853f, -0.99456459f, -0.99489999f,
-0.99522477f, -0.99553883f, -0.99584228f, -0.99613506f, -0.99641716f,
-0.99668860f, -0.99694937f, -0.99719942f, -0.99743885f, -0.99766755f,
-0.99788558f, -0.99809295f, -0.99828959f, -0.99847561f, -0.99865085f,
-0.99881548f, -0.99896932f, -0.99911255f, -0.99924499f, -0.99936682f,
-0.99947786f, -0.99957830f, -0.99966794f, -0.99974692f, -0.99981517f,
-0.99987274f, -0.99991959f, -0.99995571f, -0.99998116f, -0.99999589f,
0.99999964f, 0.99997288f, 0.99990326f, 0.99979085f, 0.99963558f,
0.99943751f, 0.99919659f, 0.99891287f, 0.99858636f, 0.99821711f,
0.99780506f, 0.99735034f, 0.99685282f, 0.99631262f, 0.99572974f,
0.99510419f, 0.99443603f, 0.99372530f, 0.99297196f, 0.99217612f,
0.99133772f, 0.99045694f, 0.98953366f, 0.98856801f, 0.98756003f,
0.98650974f, 0.98541719f, 0.98428243f, 0.98310548f, 0.98188645f,
0.98062533f, 0.97932225f, 0.97797716f, 0.97659022f, 0.97516143f,
0.97369087f, 0.97217858f, 0.97062469f, 0.96902919f, 0.96739221f,
0.96571374f, 0.96399397f, 0.96223283f, 0.96043050f, 0.95858705f,
0.95670253f, 0.95477700f, 0.95281059f, 0.95080340f, 0.94875544f,
0.94666684f, 0.94453770f, 0.94236809f, 0.94015813f, 0.93790787f,
0.93561745f, 0.93328691f, 0.93091643f, 0.92850608f, 0.92605597f,
0.92356616f, 0.92103678f, 0.91846794f, 0.91585976f, 0.91321236f,
0.91052586f, 0.90780038f, 0.90503591f, 0.90223277f, 0.89939094f,
0.89651060f, 0.89359182f, 0.89063478f, 0.88763964f, 0.88460642f,
0.88153529f, 0.87842643f, 0.87527996f, 0.87209594f, 0.86887461f,
0.86561602f, 0.86232042f, 0.85898781f, 0.85561842f, 0.85221243f,
0.84876984f, 0.84529096f, 0.84177583f, 0.83822471f, 0.83463764f,
0.83101481f, 0.82735640f, 0.82366252f, 0.81993335f, 0.81616908f,
0.81236988f, 0.80853581f, 0.80466717f, 0.80076402f, 0.79682660f,
0.79285502f, 0.78884947f, 0.78481019f, 0.78073722f, 0.77663082f,
0.77249116f, 0.76831841f, 0.76411277f, 0.75987434f, 0.75560343f,
0.75130010f, 0.74696463f, 0.74259710f, 0.73819780f, 0.73376691f,
0.72930455f, 0.72481096f, 0.72028631f, 0.71573079f, 0.71114463f,
0.70652801f, 0.70188117f, 0.69720417f, 0.69249737f, 0.68776089f,
0.68299496f, 0.67819971f, 0.67337549f, 0.66852236f, 0.66364062f,
0.65873051f, 0.65379208f, 0.64882571f, 0.64383155f, 0.63880974f,
0.63376063f, 0.62868434f, 0.62358117f, 0.61845124f, 0.61329484f,
0.60811216f, 0.60290343f, 0.59766883f, 0.59240872f, 0.58712316f,
0.58181250f, 0.57647687f, 0.57111657f, 0.56573176f, 0.56032276f,
0.55488980f, 0.54943299f, 0.54395270f, 0.53844911f, 0.53292239f,
0.52737290f, 0.52180082f, 0.51620632f, 0.51058978f, 0.50495136f,
0.49929130f, 0.49360985f, 0.48790723f, 0.48218375f, 0.47643960f,
0.47067502f, 0.46489030f, 0.45908567f, 0.45326138f, 0.44741765f,
0.44155475f, 0.43567297f, 0.42977250f, 0.42385364f, 0.41791660f,
0.41196167f, 0.40598908f, 0.39999911f, 0.39399201f, 0.38796803f,
0.38192743f, 0.37587047f, 0.36979741f, 0.36370850f, 0.35760403f,
0.35148421f, 0.34534934f, 0.33919969f, 0.33303553f, 0.32685706f,
0.32066461f, 0.31445843f, 0.30823877f, 0.30200592f, 0.29576012f,
0.28950164f, 0.28323078f, 0.27694780f, 0.27065292f, 0.26434645f,
0.25802869f, 0.25169984f, 0.24536023f, 0.23901010f, 0.23264973f,
0.22627939f, 0.21989937f, 0.21350993f, 0.20711134f, 0.20070387f,
0.19428782f, 0.18786344f, 0.18143101f, 0.17499080f, 0.16854310f,
0.16208819f, 0.15562633f, 0.14915779f, 0.14268288f, 0.13620184f,
0.12971498f, 0.12322257f, 0.11672486f, 0.11022217f, 0.10371475f,
0.097202882f, 0.090686858f, 0.084166944f, 0.077643424f, 0.071116582f,
0.064586692f, 0.058054037f, 0.051518895f, 0.044981543f, 0.038442269f,
0.031901345f, 0.025359053f, 0.018815678f, 0.012271495f, 0.0057267868f,
-0.00081816671f, -0.0073630852f, -0.013907688f, -0.020451695f, -0.026994826f,
-0.033536803f, -0.040077340f, -0.046616159f, -0.053152986f, -0.059687532f,
-0.066219524f, -0.072748676f, -0.079274714f, -0.085797355f, -0.092316322f,
-0.098831341f, -0.10534211f, -0.11184838f, -0.11834986f, -0.12484626f,
-0.13133731f, -0.13782275f, -0.14430228f, -0.15077563f, -0.15724251f,
-0.16370267f, -0.17015581f, -0.17660165f, -0.18303993f, -0.18947038f,
-0.19589271f, -0.20230664f, -0.20871192f, -0.21510825f, -0.22149536f,
-0.22787298f, -0.23424086f, -0.24059868f, -0.24694622f, -0.25328314f,
-0.25960925f, -0.26592422f, -0.27222782f, -0.27851975f, -0.28479972f,
-0.29106751f, -0.29732284f, -0.30356544f, -0.30979502f, -0.31601134f,
-0.32221413f, -0.32840309f, -0.33457801f, -0.34073856f, -0.34688455f,
-0.35301566f, -0.35913166f, -0.36523229f, -0.37131724f, -0.37738630f,
-0.38343921f, -0.38947567f, -0.39549544f, -0.40149832f, -0.40748394f,
-0.41345215f, -0.41940263f, -0.42533514f, -0.43124944f, -0.43714526f,
-0.44302234f, -0.44888046f, -0.45471936f, -0.46053877f, -0.46633846f,
-0.47211814f, -0.47787762f, -0.48361665f, -0.48933494f, -0.49503228f,
-0.50070840f, -0.50636309f, -0.51199609f, -0.51760709f, -0.52319598f,
-0.52876246f, -0.53430629f, -0.53982723f, -0.54532504f, -0.55079949f,
-0.55625033f, -0.56167740f, -0.56708032f, -0.57245898f, -0.57781315f,
-0.58314258f, -0.58844697f, -0.59372622f, -0.59897995f, -0.60420811f,
-0.60941035f, -0.61458647f, -0.61973625f, -0.62485951f, -0.62995601f,
-0.63502556f, -0.64006782f, -0.64508271f, -0.65007001f, -0.65502942f,
-0.65996075f, -0.66486382f, -0.66973841f, -0.67458433f, -0.67940134f,
-0.68418926f, -0.68894786f, -0.69367695f, -0.69837630f, -0.70304573f,
-0.70768511f, -0.71229410f, -0.71687263f, -0.72142041f, -0.72593731f,
-0.73042315f, -0.73487765f, -0.73930067f, -0.74369204f, -0.74805158f,
-0.75237900f, -0.75667429f, -0.76093709f, -0.76516730f, -0.76936477f,
-0.77352923f, -0.77766061f, -0.78175867f, -0.78582323f, -0.78985411f,
-0.79385114f, -0.79781419f, -0.80174309f, -0.80563760f, -0.80949765f,
-0.81332302f, -0.81711352f, -0.82086903f, -0.82458937f, -0.82827437f,
-0.83192390f, -0.83553779f, -0.83911592f, -0.84265804f, -0.84616417f,
-0.84963393f, -0.85306740f, -0.85646427f, -0.85982448f, -0.86314780f,
-0.86643422f, -0.86968350f, -0.87289548f, -0.87607014f, -0.87920725f,
-0.88230664f, -0.88536829f, -0.88839203f, -0.89137769f, -0.89432514f,
-0.89723432f, -0.90010506f, -0.90293723f, -0.90573072f, -0.90848541f,
-0.91120118f, -0.91387796f, -0.91651553f, -0.91911387f, -0.92167282f,
-0.92419231f, -0.92667222f, -0.92911243f, -0.93151283f, -0.93387336f,
-0.93619382f, -0.93847424f, -0.94071442f, -0.94291431f, -0.94507378f,
-0.94719279f, -0.94927126f, -0.95130903f, -0.95330608f, -0.95526224f,
-0.95717752f, -0.95905179f, -0.96088499f, -0.96267700f, -0.96442777f,
-0.96613729f, -0.96780539f, -0.96943200f, -0.97101706f, -0.97256058f,
-0.97406244f, -0.97552258f, -0.97694093f, -0.97831738f, -0.97965199f,
-0.98094457f, -0.98219514f, -0.98340368f, -0.98457009f, -0.98569429f,
-0.98677629f, -0.98781598f, -0.98881340f, -0.98976845f, -0.99068111f,
-0.99155134f, -0.99237907f, -0.99316430f, -0.99390697f, -0.99460709f,
-0.99526459f, -0.99587947f, -0.99645168f, -0.99698120f, -0.99746799f,
-0.99791211f, -0.99831343f, -0.99867201f, -0.99898779f, -0.99926084f,
-0.99949104f, -0.99967843f, -0.99982297f, -0.99992472f, -0.99998361f,
0.99999869f, 0.99989158f, 0.99961317f, 0.99916345f, 0.99854255f,
0.99775058f, 0.99678761f, 0.99565387f, 0.99434954f, 0.99287480f,
0.99122995f, 0.98941529f, 0.98743105f, 0.98527765f, 0.98295540f,
0.98046476f, 0.97780609f, 0.97497988f, 0.97198665f, 0.96882683f,
0.96550101f, 0.96200979f, 0.95835376f, 0.95453346f, 0.95054960f,
0.94640291f, 0.94209403f, 0.93762374f, 0.93299282f, 0.92820197f,
0.92325211f, 0.91814411f, 0.91287869f, 0.90745693f, 0.90187967f,
0.89614785f, 0.89026248f, 0.88422459f, 0.87803519f, 0.87169534f,
0.86520612f, 0.85856867f, 0.85178405f, 0.84485358f, 0.83777827f,
0.83055943f, 0.82319832f, 0.81569612f, 0.80805415f, 0.80027372f,
0.79235619f, 0.78430289f, 0.77611518f, 0.76779449f, 0.75934225f,
0.75075996f, 0.74204898f, 0.73321080f, 0.72424710f, 0.71515924f,
0.70594883f, 0.69661748f, 0.68716675f, 0.67759830f, 0.66791373f,
0.65811473f, 0.64820296f, 0.63818014f, 0.62804794f, 0.61780810f,
0.60746247f, 0.59701276f, 0.58646071f, 0.57580817f, 0.56505698f,
0.55420899f, 0.54326600f, 0.53222996f, 0.52110273f, 0.50988621f,
0.49858227f, 0.48719296f, 0.47572014f, 0.46416581f, 0.45253196f,
0.44082057f, 0.42903364f, 0.41717321f, 0.40524128f, 0.39323992f,
0.38117120f, 0.36903715f, 0.35683987f, 0.34458145f, 0.33226398f,
0.31988961f, 0.30746040f, 0.29497850f, 0.28244606f, 0.26986524f,
0.25723818f, 0.24456702f, 0.23185398f, 0.21910121f, 0.20631088f,
0.19348522f, 0.18062639f, 0.16773662f, 0.15481812f, 0.14187308f,
0.12890373f, 0.11591230f, 0.10290100f, 0.089872077f, 0.076827750f,
0.063770257f, 0.050701842f, 0.037624735f, 0.024541186f, 0.011453429f,
-0.0016362892f, -0.014725727f, -0.027812643f, -0.040894791f, -0.053969935f,
-0.067035832f, -0.080090240f, -0.093130924f, -0.10615565f, -0.11916219f,
-0.13214831f, -0.14511178f, -0.15805040f, -0.17096193f, -0.18384418f,
-0.19669491f, -0.20951195f, -0.22229309f, -0.23503613f, -0.24773891f,
-0.26039925f, -0.27301496f, -0.28558388f, -0.29810387f, -0.31057280f,
-0.32298848f, -0.33534884f, -0.34765175f, -0.35989508f, -0.37207675f,
-0.38419467f, -0.39624676f, -0.40823093f, -0.42014518f, -0.43198743f,
-0.44375566f, -0.45544785f, -0.46706200f, -0.47859612f, -0.49004826f,
-0.50141639f, -0.51269865f, -0.52389306f, -0.53499764f, -0.54601061f,
-0.55693001f, -0.56775403f, -0.57848072f, -0.58910829f, -0.59963489f,
-0.61005878f, -0.62037814f, -0.63059121f, -0.64069623f, -0.65069145f,
-0.66057515f, -0.67034572f, -0.68000144f, -0.68954057f, -0.69896162f,
-0.70826286f, -0.71744281f, -0.72649974f, -0.73543227f, -0.74423873f,
-0.75291771f, -0.76146764f, -0.76988715f, -0.77817470f, -0.78632891f,
-0.79434842f, -0.80223179f, -0.80997771f, -0.81758487f, -0.82505190f,
-0.83237761f, -0.83956063f, -0.84659988f, -0.85349399f, -0.86024189f,
-0.86684239f, -0.87329435f, -0.87959671f, -0.88574833f, -0.89174819f,
-0.89759529f, -0.90328854f, -0.90882701f, -0.91420978f, -0.91943592f,
-0.92450452f, -0.92941469f, -0.93416560f, -0.93875647f, -0.94318646f,
-0.94745487f, -0.95156091f, -0.95550388f, -0.95928317f, -0.96289814f,
-0.96634805f, -0.96963239f, -0.97275060f, -0.97570217f, -0.97848648f,
-0.98110318f, -0.98355180f, -0.98583186f, -0.98794299f, -0.98988485f,
-0.99165714f, -0.99325943f, -0.99469161f, -0.99595332f, -0.99704438f,
-0.99796462f, -0.99871385f, -0.99929196f, -0.99969882f, -0.99993443f,
0.99999464f, 0.99956632f, 0.99845290f, 0.99665523f, 0.99417448f,
0.99101239f, 0.98717111f, 0.98265326f, 0.97746199f, 0.97160077f,
0.96507365f, 0.95788515f, 0.95004016f, 0.94154406f, 0.93240267f,
0.92262226f, 0.91220951f, 0.90117162f, 0.88951606f, 0.87725091f,
0.86438453f, 0.85092574f, 0.83688372f, 0.82226819f, 0.80708915f,
0.79135692f, 0.77508235f, 0.75827658f, 0.74095112f, 0.72311783f,
0.70478898f, 0.68597710f, 0.66669506f, 0.64695615f, 0.62677377f,
0.60616189f, 0.58513457f, 0.56370622f, 0.54189157f, 0.51970547f,
0.49716324f, 0.47428027f, 0.45107225f, 0.42755505f, 0.40374488f,
0.37965798f, 0.35531086f, 0.33072025f, 0.30590299f, 0.28087607f,
0.25565663f, 0.23026201f, 0.20470956f, 0.17901683f, 0.15320139f,
0.12728097f, 0.10127331f, 0.075196236f, 0.049067631f, 0.022905400f,
-0.0032725304f, -0.029448219f, -0.055603724f, -0.081721120f, -0.10778251f,
-0.13377003f, -0.15966587f, -0.18545228f, -0.21111161f, -0.23662624f,
-0.26197869f, -0.28715160f, -0.31212771f, -0.33688989f, -0.36142120f,
-0.38570482f, -0.40972409f, -0.43346253f, -0.45690393f, -0.48003218f,
-0.50283146f, -0.52528608f, -0.54738069f, -0.56910020f, -0.59042966f,
-0.61135447f, -0.63186026f, -0.65193301f, -0.67155898f, -0.69072473f,
-0.70941705f, -0.72762316f, -0.74533063f, -0.76252723f, -0.77920127f,
-0.79534131f, -0.81093621f, -0.82597536f, -0.84044844f, -0.85434550f,
-0.86765707f, -0.88037395f, -0.89248747f, -0.90398932f, -0.91487163f,
-0.92512697f, -0.93474823f, -0.94372886f, -0.95206273f, -0.95974404f,
-0.96676767f, -0.97312868f, -0.97882277f, -0.98384601f, -0.98819500f,
-0.99186671f, -0.99485862f, -0.99716878f, -0.99879545f, -0.99973762f,
};
#endif
static const CELTMode mode48000_960_120 = {
48000, /* Fs */
120, /* overlap */
21, /* nbEBands */
21, /* effEBands */
{0.85000610f, 0.0000000f, 1.0000000f, 1.0000000f, }, /* preemph */
eband5ms, /* eBands */
3, /* maxLM */
8, /* nbShortMdcts */
120, /* shortMdctSize */
11, /* nbAllocVectors */
band_allocation, /* allocVectors */
logN400, /* logN */
window120, /* window */
{1920, 3, {&fft_state48000_960_0, &fft_state48000_960_1, &fft_state48000_960_2, &fft_state48000_960_3, }, mdct_twiddles960}, /* mdct */
{392, cache_index50, cache_bits50, cache_caps50}, /* cache */
};
/* List of all the available modes */
#define TOTAL_MODES 1
static const CELTMode * const static_mode_list[TOTAL_MODES] = {
&mode48000_960_120,
};

View File

@@ -0,0 +1,442 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "mathops.h"
#include "cwrs.h"
#include "vq.h"
#include "arch.h"
#include "os_support.h"
#include "bands.h"
#include "rate.h"
#include "pitch.h"
#if defined(MIPSr1_ASM)
#include "mips/vq_mipsr1.h"
#endif
#ifndef OVERRIDE_vq_exp_rotation1
static void exp_rotation1(celt_norm *X, int len, int stride, opus_val16 c, opus_val16 s)
{
int i;
opus_val16 ms;
celt_norm *Xptr;
Xptr = X;
ms = NEG16(s);
for (i=0;i<len-stride;i++)
{
celt_norm x1, x2;
x1 = Xptr[0];
x2 = Xptr[stride];
Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15));
*Xptr++ = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
}
Xptr = &X[len-2*stride-1];
for (i=len-2*stride-1;i>=0;i--)
{
celt_norm x1, x2;
x1 = Xptr[0];
x2 = Xptr[stride];
Xptr[stride] = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x2), s, x1), 15));
*Xptr-- = EXTRACT16(PSHR32(MAC16_16(MULT16_16(c, x1), ms, x2), 15));
}
}
#endif /* OVERRIDE_vq_exp_rotation1 */
void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread)
{
static const int SPREAD_FACTOR[3]={15,10,5};
int i;
opus_val16 c, s;
opus_val16 gain, theta;
int stride2=0;
int factor;
if (2*K>=len || spread==SPREAD_NONE)
return;
factor = SPREAD_FACTOR[spread-1];
gain = celt_div((opus_val32)MULT16_16(Q15_ONE,len),(opus_val32)(len+factor*K));
theta = HALF16(MULT16_16_Q15(gain,gain));
c = celt_cos_norm(EXTEND32(theta));
s = celt_cos_norm(EXTEND32(SUB16(Q15ONE,theta))); /* sin(theta) */
if (len>=8*stride)
{
stride2 = 1;
/* This is just a simple (equivalent) way of computing sqrt(len/stride) with rounding.
It's basically incrementing long as (stride2+0.5)^2 < len/stride. */
while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
stride2++;
}
/*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
extract_collapse_mask().*/
len = celt_udiv(len, stride);
for (i=0;i<stride;i++)
{
if (dir < 0)
{
if (stride2)
exp_rotation1(X+i*len, len, stride2, s, c);
exp_rotation1(X+i*len, len, 1, c, s);
} else {
exp_rotation1(X+i*len, len, 1, c, -s);
if (stride2)
exp_rotation1(X+i*len, len, stride2, s, -c);
}
}
}
/** Takes the pitch vector and the decoded residual vector, computes the gain
that will give ||p+g*y||=1 and mixes the residual with the pitch. */
static void normalise_residual(int * OPUS_RESTRICT iy, celt_norm * OPUS_RESTRICT X,
int N, opus_val32 Ryy, opus_val16 gain)
{
int i;
#ifdef FIXED_POINT
int k;
#endif
opus_val32 t;
opus_val16 g;
#ifdef FIXED_POINT
k = celt_ilog2(Ryy)>>1;
#endif
t = VSHR32(Ryy, 2*(k-7));
g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
i=0;
do
X[i] = EXTRACT16(PSHR32(MULT16_16(g, iy[i]), k+1));
while (++i < N);
}
static unsigned extract_collapse_mask(int *iy, int N, int B)
{
unsigned collapse_mask;
int N0;
int i;
if (B<=1)
return 1;
/*NOTE: As a minor optimization, we could be passing around log2(B), not B, for both this and for
exp_rotation().*/
N0 = celt_udiv(N, B);
collapse_mask = 0;
i=0; do {
int j;
unsigned tmp=0;
j=0; do {
tmp |= iy[i*N0+j];
} while (++j<N0);
collapse_mask |= (tmp!=0)<<i;
} while (++i<B);
return collapse_mask;
}
opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch)
{
VARDECL(celt_norm, y);
VARDECL(int, signx);
int i, j;
int pulsesLeft;
opus_val32 sum;
opus_val32 xy;
opus_val16 yy;
SAVE_STACK;
(void)arch;
ALLOC(y, N, celt_norm);
ALLOC(signx, N, int);
/* Get rid of the sign */
sum = 0;
j=0; do {
signx[j] = X[j]<0;
/* OPT: Make sure the compiler doesn't use a branch on ABS16(). */
X[j] = ABS16(X[j]);
iy[j] = 0;
y[j] = 0;
} while (++j<N);
xy = yy = 0;
pulsesLeft = K;
/* Do a pre-search by projecting on the pyramid */
if (K > (N>>1))
{
opus_val16 rcp;
j=0; do {
sum += X[j];
} while (++j<N);
/* If X is too small, just replace it with a pulse at 0 */
#ifdef FIXED_POINT
if (sum <= K)
#else
/* Prevents infinities and NaNs from causing too many pulses
to be allocated. 64 is an approximation of infinity here. */
if (!(sum > EPSILON && sum < 64))
#endif
{
X[0] = QCONST16(1.f,14);
j=1; do
X[j]=0;
while (++j<N);
sum = QCONST16(1.f,14);
}
#ifdef FIXED_POINT
rcp = EXTRACT16(MULT16_32_Q16(K, celt_rcp(sum)));
#else
/* Using K+e with e < 1 guarantees we cannot get more than K pulses. */
rcp = EXTRACT16(MULT16_32_Q16(K+0.8f, celt_rcp(sum)));
#endif
j=0; do {
#ifdef FIXED_POINT
/* It's really important to round *towards zero* here */
iy[j] = MULT16_16_Q15(X[j],rcp);
#else
iy[j] = (int)floor(rcp*X[j]);
#endif
y[j] = (celt_norm)iy[j];
yy = MAC16_16(yy, y[j],y[j]);
xy = MAC16_16(xy, X[j],y[j]);
y[j] *= 2;
pulsesLeft -= iy[j];
} while (++j<N);
}
celt_sig_assert(pulsesLeft>=0);
/* This should never happen, but just in case it does (e.g. on silence)
we fill the first bin with pulses. */
#ifdef FIXED_POINT_DEBUG
celt_sig_assert(pulsesLeft<=N+3);
#endif
if (pulsesLeft > N+3)
{
opus_val16 tmp = (opus_val16)pulsesLeft;
yy = MAC16_16(yy, tmp, tmp);
yy = MAC16_16(yy, tmp, y[0]);
iy[0] += pulsesLeft;
pulsesLeft=0;
}
for (i=0;i<pulsesLeft;i++)
{
opus_val16 Rxy, Ryy;
int best_id;
opus_val32 best_num;
opus_val16 best_den;
#ifdef FIXED_POINT
int rshift;
#endif
#ifdef FIXED_POINT
rshift = 1+celt_ilog2(K-pulsesLeft+i+1);
#endif
best_id = 0;
/* The squared magnitude term gets added anyway, so we might as well
add it outside the loop */
yy = ADD16(yy, 1);
/* Calculations for position 0 are out of the loop, in part to reduce
mispredicted branches (since the if condition is usually false)
in the loop. */
/* Temporary sums of the new pulse(s) */
Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[0])),rshift));
/* We're multiplying y[j] by two so we don't have to do it here */
Ryy = ADD16(yy, y[0]);
/* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
Rxy is positive because the sign is pre-computed) */
Rxy = MULT16_16_Q15(Rxy,Rxy);
best_den = Ryy;
best_num = Rxy;
j=1;
do {
/* Temporary sums of the new pulse(s) */
Rxy = EXTRACT16(SHR32(ADD32(xy, EXTEND32(X[j])),rshift));
/* We're multiplying y[j] by two so we don't have to do it here */
Ryy = ADD16(yy, y[j]);
/* Approximate score: we maximise Rxy/sqrt(Ryy) (we're guaranteed that
Rxy is positive because the sign is pre-computed) */
Rxy = MULT16_16_Q15(Rxy,Rxy);
/* The idea is to check for num/den >= best_num/best_den, but that way
we can do it without any division */
/* OPT: It's not clear whether a cmov is faster than a branch here
since the condition is more often false than true and using
a cmov introduces data dependencies across iterations. The optimal
choice may be architecture-dependent. */
if (opus_unlikely(MULT16_16(best_den, Rxy) > MULT16_16(Ryy, best_num)))
{
best_den = Ryy;
best_num = Rxy;
best_id = j;
}
} while (++j<N);
/* Updating the sums of the new pulse(s) */
xy = ADD32(xy, EXTEND32(X[best_id]));
/* We're multiplying y[j] by two so we don't have to do it here */
yy = ADD16(yy, y[best_id]);
/* Only now that we've made the final choice, update y/iy */
/* Multiplying y[j] by 2 so we don't have to do it everywhere else */
y[best_id] += 2;
iy[best_id]++;
}
/* Put the original sign back */
j=0;
do {
/*iy[j] = signx[j] ? -iy[j] : iy[j];*/
/* OPT: The is more likely to be compiled without a branch than the code above
but has the same performance otherwise. */
iy[j] = (iy[j]^-signx[j]) + signx[j];
} while (++j<N);
RESTORE_STACK;
return yy;
}
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
opus_val16 gain, int resynth, int arch)
{
VARDECL(int, iy);
opus_val16 yy;
unsigned collapse_mask;
SAVE_STACK;
celt_assert2(K>0, "alg_quant() needs at least one pulse");
celt_assert2(N>1, "alg_quant() needs at least two dimensions");
/* Covers vectorization by up to 4. */
ALLOC(iy, N+3, int);
exp_rotation(X, N, 1, B, K, spread);
yy = op_pvq_search(X, iy, K, N, arch);
encode_pulses(iy, N, K, enc);
if (resynth)
{
normalise_residual(iy, X, N, yy, gain);
exp_rotation(X, N, -1, B, K, spread);
}
collapse_mask = extract_collapse_mask(iy, N, B);
RESTORE_STACK;
return collapse_mask;
}
/** Decode pulse vector and combine the result with the pitch vector to produce
the final normalised signal in the current band. */
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
ec_dec *dec, opus_val16 gain)
{
opus_val32 Ryy;
unsigned collapse_mask;
VARDECL(int, iy);
SAVE_STACK;
celt_assert2(K>0, "alg_unquant() needs at least one pulse");
celt_assert2(N>1, "alg_unquant() needs at least two dimensions");
ALLOC(iy, N, int);
Ryy = decode_pulses(iy, N, K, dec);
normalise_residual(iy, X, N, Ryy, gain);
exp_rotation(X, N, -1, B, K, spread);
collapse_mask = extract_collapse_mask(iy, N, B);
RESTORE_STACK;
return collapse_mask;
}
#ifndef OVERRIDE_renormalise_vector
void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch)
{
int i;
#ifdef FIXED_POINT
int k;
#endif
opus_val32 E;
opus_val16 g;
opus_val32 t;
celt_norm *xptr;
E = EPSILON + celt_inner_prod(X, X, N, arch);
#ifdef FIXED_POINT
k = celt_ilog2(E)>>1;
#endif
t = VSHR32(E, 2*(k-7));
g = MULT16_16_P15(celt_rsqrt_norm(t),gain);
xptr = X;
for (i=0;i<N;i++)
{
*xptr = EXTRACT16(PSHR32(MULT16_16(g, *xptr), k+1));
xptr++;
}
/*return celt_sqrt(E);*/
}
#endif /* OVERRIDE_renormalise_vector */
int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch)
{
int i;
int itheta;
opus_val16 mid, side;
opus_val32 Emid, Eside;
Emid = Eside = EPSILON;
if (stereo)
{
for (i=0;i<N;i++)
{
celt_norm m, s;
m = ADD16(SHR16(X[i],1),SHR16(Y[i],1));
s = SUB16(SHR16(X[i],1),SHR16(Y[i],1));
Emid = MAC16_16(Emid, m, m);
Eside = MAC16_16(Eside, s, s);
}
} else {
Emid += celt_inner_prod(X, X, N, arch);
Eside += celt_inner_prod(Y, Y, N, arch);
}
mid = celt_sqrt(Emid);
side = celt_sqrt(Eside);
#ifdef FIXED_POINT
/* 0.63662 = 2/pi */
itheta = MULT16_16_Q15(QCONST16(0.63662f,15),celt_atan2p(side, mid));
#else
itheta = (int)floor(.5f+16384*0.63662f*fast_atan2f(side,mid));
#endif
return itheta;
}

View File

@@ -0,0 +1,79 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Written by Jean-Marc Valin */
/**
@file vq.h
@brief Vector quantisation of the residual
*/
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef VQ_H
#define VQ_H
#include "entenc.h"
#include "entdec.h"
#include "modes.h"
#if (defined(OPUS_X86_MAY_HAVE_SSE2) && !defined(FIXED_POINT))
#include "x86/vq_sse.h"
#endif
void exp_rotation(celt_norm *X, int len, int dir, int stride, int K, int spread);
opus_val16 op_pvq_search_c(celt_norm *X, int *iy, int K, int N, int arch);
#if !defined(OVERRIDE_OP_PVQ_SEARCH)
#define op_pvq_search(x, iy, K, N, arch) \
(op_pvq_search_c(x, iy, K, N, arch))
#endif
/** Algebraic pulse-vector quantiser. The signal x is replaced by the sum of
* the pitch and a combination of pulses such that its norm is still equal
* to 1. This is the function that will typically require the most CPU.
* @param X Residual signal to quantise/encode (returns quantised version)
* @param N Number of samples to encode
* @param K Number of pulses to use
* @param enc Entropy encoder state
* @ret A mask indicating which blocks in the band received pulses
*/
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B, ec_enc *enc,
opus_val16 gain, int resynth, int arch);
/** Algebraic pulse decoder
* @param X Decoded normalised spectrum (returned)
* @param N Number of samples to decode
* @param K Number of pulses to use
* @param dec Entropy decoder state
* @ret A mask indicating which blocks in the band received pulses
*/
unsigned alg_unquant(celt_norm *X, int N, int K, int spread, int B,
ec_dec *dec, opus_val16 gain);
void renormalise_vector(celt_norm *X, int N, opus_val16 gain, int arch);
int stereo_itheta(const celt_norm *X, const celt_norm *Y, int stereo, int N, int arch);
#endif /* VQ_H */

View File

@@ -0,0 +1,210 @@
/* config.h. Generated from config.h.in by configure. */
/* config.h.in. Generated from configure.ac by autoheader. */
/* Get CPU Info by asm method */
/* #undef CPU_INFO_BY_ASM */
/* Get CPU Info by c method */
/* #undef CPU_INFO_BY_C */
/* Custom modes */
/* #undef CUSTOM_MODES */
/* Do not build the float API */
#define DISABLE_FLOAT_API 1
/* Disable bitstream fixes from RFC 8251 */
/* #undef DISABLE_UPDATE_DRAFT */
/* Assertions */
/* #undef ENABLE_ASSERTIONS */
/* Hardening */
/* #undef ENABLE_HARDENING */
/* Debug fixed-point implementation */
/* #undef FIXED_DEBUG */
/* Compile as fixed-point (for machines without a fast enough FPU) */
#define FIXED_POINT 1
/* Float approximations */
/* #undef FLOAT_APPROX */
/* Fuzzing */
/* #undef FUZZING */
/* Define to 1 if you have the <alloca.h> header file. */
/* #undef HAVE_ALLOCA_H */
/* NE10 library is installed on host. Make sure it is on target! */
/* #undef HAVE_ARM_NE10 */
/* Define to 1 if you have the <dlfcn.h> header file. */
#define HAVE_DLFCN_H 0
/* Define to 1 if you have the <inttypes.h> header file. */
#define HAVE_INTTYPES_H 1
/* Define to 1 if you have the `lrint' function. */
#define HAVE_LRINT 0
/* Define to 1 if you have the `lrintf' function. */
#define HAVE_LRINTF 0
/* Define to 1 if you have the <memory.h> header file. */
#define HAVE_MEMORY_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#define HAVE_STDINT_H 1
/* Define to 1 if you have the <stdlib.h> header file. */
#define HAVE_STDLIB_H 1
/* Define to 1 if you have the <strings.h> header file. */
#define HAVE_STRINGS_H 1
/* Define to 1 if you have the <string.h> header file. */
#define HAVE_STRING_H 1
/* Define to 1 if you have the <sys/stat.h> header file. */
#define HAVE_SYS_STAT_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#define HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#define HAVE_UNISTD_H 0
/* Define to 1 if you have the `__malloc_hook' function. */
#define HAVE___MALLOC_HOOK 1
/* Define to the sub-directory where libtool stores uninstalled libraries. */
#define LT_OBJDIR ".libs/"
/* Make use of ARM asm optimization */
/* #undef OPUS_ARM_ASM */
/* Use generic ARMv4 inline asm optimizations */
/* #undef OPUS_ARM_INLINE_ASM */
/* Use ARMv5E inline asm optimizations */
/* #undef OPUS_ARM_INLINE_EDSP */
/* Use ARMv6 inline asm optimizations */
/* #undef OPUS_ARM_INLINE_MEDIA */
/* Use ARM NEON inline asm optimizations */
/* #undef OPUS_ARM_INLINE_NEON */
/* Define if assembler supports EDSP instructions */
/* #undef OPUS_ARM_MAY_HAVE_EDSP */
/* Define if assembler supports ARMv6 media instructions */
/* #undef OPUS_ARM_MAY_HAVE_MEDIA */
/* Define if compiler supports NEON instructions */
/* #undef OPUS_ARM_MAY_HAVE_NEON */
/* Compiler supports ARMv7/Aarch64 Neon Intrinsics */
/* #undef OPUS_ARM_MAY_HAVE_NEON_INTR */
/* Define if binary requires Aarch64 Neon Intrinsics */
/* #undef OPUS_ARM_PRESUME_AARCH64_NEON_INTR */
/* Define if binary requires EDSP instruction support */
/* #undef OPUS_ARM_PRESUME_EDSP */
/* Define if binary requires ARMv6 media instruction support */
/* #undef OPUS_ARM_PRESUME_MEDIA */
/* Define if binary requires NEON instruction support */
/* #undef OPUS_ARM_PRESUME_NEON */
/* Define if binary requires NEON intrinsics support */
/* #undef OPUS_ARM_PRESUME_NEON_INTR */
/* This is a build of OPUS */
#define OPUS_BUILD /**/
/* Run bit-exactness checks between optimized and c implementations */
/* #undef OPUS_CHECK_ASM */
/* Use run-time CPU capabilities detection */
/* #undef OPUS_HAVE_RTCD */
/* Compiler supports X86 AVX Intrinsics */
/* #undef OPUS_X86_MAY_HAVE_AVX */
/* Compiler supports X86 SSE Intrinsics */
/* #undef OPUS_X86_MAY_HAVE_SSE */
/* Compiler supports X86 SSE2 Intrinsics */
/* #undef OPUS_X86_MAY_HAVE_SSE2 */
/* Compiler supports X86 SSE4.1 Intrinsics */
/* #undef OPUS_X86_MAY_HAVE_SSE4_1 */
/* Define if binary requires AVX intrinsics support */
/* #undef OPUS_X86_PRESUME_AVX */
/* Define if binary requires SSE intrinsics support */
/* #undef OPUS_X86_PRESUME_SSE */
/* Define if binary requires SSE2 intrinsics support */
/* #undef OPUS_X86_PRESUME_SSE2 */
/* Define if binary requires SSE4.1 intrinsics support */
/* #undef OPUS_X86_PRESUME_SSE4_1 */
/* Define to the address where bug reports for this package should be sent. */
#define PACKAGE_BUGREPORT "opus@xiph.org"
/* Define to the full name of this package. */
#define PACKAGE_NAME "opus"
/* Define to the full name and version of this package. */
#define PACKAGE_STRING "opus 1.3.1"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "opus"
/* Define to the home page for this package. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.3.1"
/* Define to 1 if you have the ANSI C header files. */
#define STDC_HEADERS 1
/* Make use of alloca */
/* #undef USE_ALLOCA */
/* Use C99 variable-size arrays */
#define VAR_ARRAYS 1
/* Define to empty if `const' does not conform to ANSI C. */
/* #undef const */
/* Define to `__inline__' or `__inline' if that's what the C compiler
calls it, or to nothing if 'inline' is not supported under any name. */
#ifndef __cplusplus
/* #undef inline */
#endif
/* Define to the equivalent of the C99 'restrict' keyword, or to
nothing if this is not supported. Do not define if restrict is
supported directly. */
#define restrict __restrict
/* Work around a bug in Sun C++: it does not support _Restrict or
__restrict__, even though the corresponding Sun C compiler ends up with
"#define restrict _Restrict" or "#define restrict __restrict__" in the
previous line. Perhaps some future version of Sun C++ will work with
restrict; if so, hopefully it defines __RESTRICT like Sun C does. */
#if defined __SUNPRO_CC && !defined __RESTRICT
# define _Restrict
# define __restrict__
#endif
#include <stdlib.h>

View File

@@ -0,0 +1,378 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "celt/arch.h"
#include "celt/float_cast.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "mapping_matrix.h"
#define MATRIX_INDEX(nb_rows, row, col) (nb_rows * col + row)
opus_int32 mapping_matrix_get_size(int rows, int cols)
{
opus_int32 size;
/* Mapping Matrix must only support up to 255 channels in or out.
* Additionally, the total cell count must be <= 65004 octets in order
* for the matrix to be stored in an OGG header.
*/
if (rows > 255 || cols > 255)
return 0;
size = rows * (opus_int32)cols * sizeof(opus_int16);
if (size > 65004)
return 0;
return align(sizeof(MappingMatrix)) + align(size);
}
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix)
{
/* void* cast avoids clang -Wcast-align warning */
return (opus_int16*)(void*)((char*)matrix + align(sizeof(MappingMatrix)));
}
void mapping_matrix_init(MappingMatrix * const matrix,
int rows, int cols, int gain, const opus_int16 *data, opus_int32 data_size)
{
int i;
opus_int16 *ptr;
#if !defined(ENABLE_ASSERTIONS)
(void)data_size;
#endif
celt_assert(align(data_size) == align(rows * cols * sizeof(opus_int16)));
matrix->rows = rows;
matrix->cols = cols;
matrix->gain = gain;
ptr = mapping_matrix_get_data(matrix);
for (i = 0; i < rows * cols; i++)
{
ptr[i] = data[i];
}
}
#ifndef DISABLE_FLOAT_API
void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
float tmp = 0;
for (col = 0; col < input_rows; col++)
{
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
}
#if defined(FIXED_POINT)
output[output_rows * i] = FLOAT2INT16((1/32768.f)*tmp);
#else
output[output_rows * i] = (1/32768.f)*tmp;
#endif
}
}
void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
float *output,
int output_rows,
int frame_size
)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
float input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
#if defined(FIXED_POINT)
input_sample = (1/32768.f)*input[input_rows * i];
#else
input_sample = input[input_rows * i];
#endif
for (row = 0; row < output_rows; row++)
{
float tmp =
(1/32768.f)*matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += tmp;
}
}
}
#endif /* DISABLE_FLOAT_API */
void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, col;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
opus_val32 tmp = 0;
for (col = 0; col < input_rows; col++)
{
#if defined(FIXED_POINT)
tmp +=
((opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
(opus_int32)input[MATRIX_INDEX(input_rows, col, i)]) >> 8;
#else
tmp +=
matrix_data[MATRIX_INDEX(matrix->rows, output_row, col)] *
input[MATRIX_INDEX(input_rows, col, i)];
#endif
}
#if defined(FIXED_POINT)
output[output_rows * i] = (opus_int16)((tmp + 64) >> 7);
#else
output[output_rows * i] = (1/(32768.f*32768.f))*tmp;
#endif
}
}
void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
opus_int16 *output,
int output_rows,
int frame_size)
{
/* Matrix data is ordered col-wise. */
opus_int16* matrix_data;
int i, row;
opus_int32 input_sample;
celt_assert(input_rows <= matrix->cols && output_rows <= matrix->rows);
matrix_data = mapping_matrix_get_data(matrix);
for (i = 0; i < frame_size; i++)
{
#if defined(FIXED_POINT)
input_sample = (opus_int32)input[input_rows * i];
#else
input_sample = (opus_int32)FLOAT2INT16(input[input_rows * i]);
#endif
for (row = 0; row < output_rows; row++)
{
opus_int32 tmp =
(opus_int32)matrix_data[MATRIX_INDEX(matrix->rows, row, input_row)] *
input_sample;
output[MATRIX_INDEX(output_rows, row, i)] += (tmp + 16384) >> 15;
}
}
}
const MappingMatrix mapping_matrix_foa_mixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_mixing_data[36] = {
16384, 0, -16384, 23170, 0, 0, 16384, 23170,
16384, 0, 0, 0, 16384, 0, -16384, -23170,
0, 0, 16384, -23170, 16384, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_soa_mixing = { 11, 11, 0 };
const opus_int16 mapping_matrix_soa_mixing_data[121] = {
10923, 7723, 13377, -13377, 11585, 9459, 7723, -16384,
-6689, 0, 0, 10923, 7723, 13377, 13377, -11585,
9459, 7723, 16384, -6689, 0, 0, 10923, -15447,
13377, 0, 0, -18919, 7723, 0, 13377, 0,
0, 10923, 7723, -13377, -13377, 11585, -9459, 7723,
16384, -6689, 0, 0, 10923, -7723, 0, 13377,
-16384, 0, -15447, 0, 9459, 0, 0, 10923,
-7723, 0, -13377, 16384, 0, -15447, 0, 9459,
0, 0, 10923, 15447, 0, 0, 0, 0,
-15447, 0, -18919, 0, 0, 10923, 7723, -13377,
13377, -11585, -9459, 7723, -16384, -6689, 0, 0,
10923, -15447, -13377, 0, 0, 18919, 7723, 0,
13377, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767
};
const MappingMatrix mapping_matrix_toa_mixing = { 18, 18, 0 };
const opus_int16 mapping_matrix_toa_mixing_data[324] = {
8208, 0, -881, 14369, 0, 0, -8192, -4163,
13218, 0, 0, 0, 11095, -8836, -6218, 14833,
0, 0, 8208, -10161, 881, 10161, -13218, -2944,
-8192, 2944, 0, -10488, -6218, 6248, -11095, -6248,
0, -10488, 0, 0, 8208, 10161, 881, -10161,
-13218, 2944, -8192, -2944, 0, 10488, -6218, -6248,
-11095, 6248, 0, 10488, 0, 0, 8176, 5566,
-11552, 5566, 9681, -11205, 8192, -11205, 0, 4920,
-15158, 9756, -3334, 9756, 0, -4920, 0, 0,
8176, 7871, 11552, 0, 0, 15846, 8192, 0,
-9681, -6958, 0, 13797, 3334, 0, -15158, 0,
0, 0, 8176, 0, 11552, 7871, 0, 0,
8192, 15846, 9681, 0, 0, 0, 3334, 13797,
15158, 6958, 0, 0, 8176, 5566, -11552, -5566,
-9681, -11205, 8192, 11205, 0, 4920, 15158, 9756,
-3334, -9756, 0, 4920, 0, 0, 8208, 14369,
-881, 0, 0, -4163, -8192, 0, -13218, -14833,
0, -8836, 11095, 0, 6218, 0, 0, 0,
8208, 10161, 881, 10161, 13218, 2944, -8192, 2944,
0, 10488, 6218, -6248, -11095, -6248, 0, -10488,
0, 0, 8208, -14369, -881, 0, 0, 4163,
-8192, 0, -13218, 14833, 0, 8836, 11095, 0,
6218, 0, 0, 0, 8208, 0, -881, -14369,
0, 0, -8192, 4163, 13218, 0, 0, 0,
11095, 8836, -6218, -14833, 0, 0, 8176, -5566,
-11552, 5566, -9681, 11205, 8192, -11205, 0, -4920,
15158, -9756, -3334, 9756, 0, -4920, 0, 0,
8176, 0, 11552, -7871, 0, 0, 8192, -15846,
9681, 0, 0, 0, 3334, -13797, 15158, -6958,
0, 0, 8176, -7871, 11552, 0, 0, -15846,
8192, 0, -9681, 6958, 0, -13797, 3334, 0,
-15158, 0, 0, 0, 8176, -5566, -11552, -5566,
9681, 11205, 8192, 11205, 0, -4920, -15158, -9756,
-3334, -9756, 0, 4920, 0, 0, 8208, -10161,
881, -10161, 13218, -2944, -8192, -2944, 0, -10488,
6218, 6248, -11095, 6248, 0, 10488, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_foa_demixing = { 6, 6, 0 };
const opus_int16 mapping_matrix_foa_demixing_data[36] = {
16384, 16384, 16384, 16384, 0, 0, 0, 23170,
0, -23170, 0, 0, -16384, 16384, -16384, 16384,
0, 0, 23170, 0, -23170, 0, 0, 0,
0, 0, 0, 0, 32767, 0, 0, 0,
0, 0, 0, 32767
};
const MappingMatrix mapping_matrix_soa_demixing = { 11, 11, 3050 };
const opus_int16 mapping_matrix_soa_demixing_data[121] = {
2771, 2771, 2771, 2771, 2771, 2771, 2771, 2771,
2771, 0, 0, 10033, 10033, -20066, 10033, 14189,
14189, -28378, 10033, -20066, 0, 0, 3393, 3393,
3393, -3393, 0, 0, 0, -3393, -3393, 0,
0, -17378, 17378, 0, -17378, -24576, 24576, 0,
17378, 0, 0, 0, -14189, 14189, 0, -14189,
-28378, 28378, 0, 14189, 0, 0, 0, 2399,
2399, -4799, -2399, 0, 0, 0, -2399, 4799,
0, 0, 1959, 1959, 1959, 1959, -3918, -3918,
-3918, 1959, 1959, 0, 0, -4156, 4156, 0,
4156, 0, 0, 0, -4156, 0, 0, 0,
8192, 8192, -16384, 8192, 16384, 16384, -32768, 8192,
-16384, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 8312, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
8312
};
const MappingMatrix mapping_matrix_toa_demixing = { 18, 18, 0 };
const opus_int16 mapping_matrix_toa_demixing_data[324] = {
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
8192, 8192, 8192, 8192, 8192, 8192, 8192, 8192,
0, 0, 0, -9779, 9779, 6263, 8857, 0,
6263, 13829, 9779, -13829, 0, -6263, 0, -8857,
-6263, -9779, 0, 0, -3413, 3413, 3413, -11359,
11359, 11359, -11359, -3413, 3413, -3413, -3413, -11359,
11359, 11359, -11359, 3413, 0, 0, 13829, 9779,
-9779, 6263, 0, 8857, -6263, 0, 9779, 0,
-13829, 6263, -8857, 0, -6263, -9779, 0, 0,
0, -15617, -15617, 6406, 0, 0, -6406, 0,
15617, 0, 0, -6406, 0, 0, 6406, 15617,
0, 0, 0, -5003, 5003, -10664, 15081, 0,
-10664, -7075, 5003, 7075, 0, 10664, 0, -15081,
10664, -5003, 0, 0, -8176, -8176, -8176, 8208,
8208, 8208, 8208, -8176, -8176, -8176, -8176, 8208,
8208, 8208, 8208, -8176, 0, 0, -7075, 5003,
-5003, -10664, 0, 15081, 10664, 0, 5003, 0,
7075, -10664, -15081, 0, 10664, -5003, 0, 0,
15617, 0, 0, 0, -6406, 6406, 0, -15617,
0, -15617, 15617, 0, 6406, -6406, 0, 0,
0, 0, 0, -11393, 11393, 2993, -4233, 0,
2993, -16112, 11393, 16112, 0, -2993, 0, 4233,
-2993, -11393, 0, 0, 0, -9974, -9974, -13617,
0, 0, 13617, 0, 9974, 0, 0, 13617,
0, 0, -13617, 9974, 0, 0, 0, 5579,
-5579, 10185, 14403, 0, 10185, -7890, -5579, 7890,
0, -10185, 0, -14403, -10185, 5579, 0, 0,
11826, -11826, -11826, -901, 901, 901, -901, 11826,
-11826, 11826, 11826, -901, 901, 901, -901, -11826,
0, 0, -7890, -5579, 5579, 10185, 0, 14403,
-10185, 0, -5579, 0, 7890, 10185, -14403, 0,
-10185, 5579, 0, 0, -9974, 0, 0, 0,
-13617, 13617, 0, 9974, 0, 9974, -9974, 0,
13617, -13617, 0, 0, 0, 0, 16112, -11393,
11393, -2993, 0, 4233, 2993, 0, -11393, 0,
-16112, -2993, -4233, 0, 2993, 11393, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
32767, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 32767
};

View File

@@ -0,0 +1,133 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/**
* @file mapping_matrix.h
* @brief Opus reference implementation mapping matrix API
*/
#ifndef MAPPING_MATRIX_H
#define MAPPING_MATRIX_H
#include "opus_types.h"
#include "opus_projection.h"
#ifdef __cplusplus
extern "C" {
#endif
typedef struct MappingMatrix
{
int rows; /* number of channels outputted from matrix. */
int cols; /* number of channels inputted to matrix. */
int gain; /* in dB. S7.8-format. */
/* Matrix cell data goes here using col-wise ordering. */
} MappingMatrix;
opus_int32 mapping_matrix_get_size(int rows, int cols);
opus_int16 *mapping_matrix_get_data(const MappingMatrix *matrix);
void mapping_matrix_init(
MappingMatrix * const matrix,
int rows,
int cols,
int gain,
const opus_int16 *data,
opus_int32 data_size
);
#ifndef DISABLE_FLOAT_API
void mapping_matrix_multiply_channel_in_float(
const MappingMatrix *matrix,
const float *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_float(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
float *output,
int output_rows,
int frame_size
);
#endif /* DISABLE_FLOAT_API */
void mapping_matrix_multiply_channel_in_short(
const MappingMatrix *matrix,
const opus_int16 *input,
int input_rows,
opus_val16 *output,
int output_row,
int output_rows,
int frame_size
);
void mapping_matrix_multiply_channel_out_short(
const MappingMatrix *matrix,
const opus_val16 *input,
int input_row,
int input_rows,
opus_int16 *output,
int output_rows,
int frame_size
);
/* Pre-computed mixing and demixing matrices for 1st to 3rd-order ambisonics.
* foa: first-order ambisonics
* soa: second-order ambisonics
* toa: third-order ambisonics
*/
extern const MappingMatrix mapping_matrix_foa_mixing;
extern const opus_int16 mapping_matrix_foa_mixing_data[36];
extern const MappingMatrix mapping_matrix_soa_mixing;
extern const opus_int16 mapping_matrix_soa_mixing_data[121];
extern const MappingMatrix mapping_matrix_toa_mixing;
extern const opus_int16 mapping_matrix_toa_mixing_data[324];
extern const MappingMatrix mapping_matrix_foa_demixing;
extern const opus_int16 mapping_matrix_foa_demixing_data[36];
extern const MappingMatrix mapping_matrix_soa_demixing;
extern const opus_int16 mapping_matrix_soa_demixing_data[121];
extern const MappingMatrix mapping_matrix_toa_demixing;
extern const opus_int16 mapping_matrix_toa_demixing_data[324];
#ifdef __cplusplus
}
#endif
#endif /* MAPPING_MATRIX_H */

View File

@@ -0,0 +1,60 @@
/* Copyright (c) 2017 Jean-Marc Valin */
/*
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.
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.
*/
#ifndef _MLP_H_
#define _MLP_H_
#include "opus_types.h"
#define WEIGHTS_SCALE (1.f/128)
#define MAX_NEURONS 32
typedef struct {
const opus_int8 *bias;
const opus_int8 *input_weights;
int nb_inputs;
int nb_neurons;
int sigmoid;
} DenseLayer;
typedef struct {
const opus_int8 *bias;
const opus_int8 *input_weights;
const opus_int8 *recurrent_weights;
int nb_inputs;
int nb_neurons;
} GRULayer;
extern const DenseLayer layer0;
extern const GRULayer layer1;
extern const DenseLayer layer2;
void compute_dense(const DenseLayer *layer, float *output, const float *input);
void compute_gru(const GRULayer *gru, float *state, const float *input);
#endif /* _MLP_H_ */

View File

@@ -0,0 +1,356 @@
/* Copyright (c) 2011 Xiph.Org Foundation, Skype Limited
Written by Jean-Marc Valin and Koen Vos */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "opus.h"
#include "opus_private.h"
#ifndef DISABLE_FLOAT_API
OPUS_EXPORT void opus_pcm_soft_clip(float *_x, int N, int C, float *declip_mem)
{
int c;
int i;
float *x;
if (C<1 || N<1 || !_x || !declip_mem) return;
/* First thing: saturate everything to +/- 2 which is the highest level our
non-linearity can handle. At the point where the signal reaches +/-2,
the derivative will be zero anyway, so this doesn't introduce any
discontinuity in the derivative. */
for (i=0;i<N*C;i++)
_x[i] = MAX16(-2.f, MIN16(2.f, _x[i]));
for (c=0;c<C;c++)
{
float a;
float x0;
int curr;
x = _x+c;
a = declip_mem[c];
/* Continue applying the non-linearity from the previous frame to avoid
any discontinuity. */
for (i=0;i<N;i++)
{
if (x[i*C]*a>=0)
break;
x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
}
curr=0;
x0 = x[0];
while(1)
{
int start, end;
float maxval;
int special=0;
int peak_pos;
for (i=curr;i<N;i++)
{
if (x[i*C]>1 || x[i*C]<-1)
break;
}
if (i==N)
{
a=0;
break;
}
peak_pos = i;
start=end=i;
maxval=ABS16(x[i*C]);
/* Look for first zero crossing before clipping */
while (start>0 && x[i*C]*x[(start-1)*C]>=0)
start--;
/* Look for first zero crossing after clipping */
while (end<N && x[i*C]*x[end*C]>=0)
{
/* Look for other peaks until the next zero-crossing. */
if (ABS16(x[end*C])>maxval)
{
maxval = ABS16(x[end*C]);
peak_pos = end;
}
end++;
}
/* Detect the special case where we clip before the first zero crossing */
special = (start==0 && x[i*C]*x[0]>=0);
/* Compute a such that maxval + a*maxval^2 = 1 */
a=(maxval-1)/(maxval*maxval);
/* Slightly boost "a" by 2^-22. This is just enough to ensure -ffast-math
does not cause output values larger than +/-1, but small enough not
to matter even for 24-bit output. */
a += a*2.4e-7f;
if (x[i*C]>0)
a = -a;
/* Apply soft clipping */
for (i=start;i<end;i++)
x[i*C] = x[i*C]+a*x[i*C]*x[i*C];
if (special && peak_pos>=2)
{
/* Add a linear ramp from the first sample to the signal peak.
This avoids a discontinuity at the beginning of the frame. */
float delta;
float offset = x0-x[0];
delta = offset / peak_pos;
for (i=curr;i<peak_pos;i++)
{
offset -= delta;
x[i*C] += offset;
x[i*C] = MAX16(-1.f, MIN16(1.f, x[i*C]));
}
}
curr = end;
if (curr==N)
break;
}
declip_mem[c] = a;
}
}
#endif
int encode_size(int size, unsigned char *data)
{
if (size < 252)
{
data[0] = size;
return 1;
} else {
data[0] = 252+(size&0x3);
data[1] = (size-(int)data[0])>>2;
return 2;
}
}
static int parse_size(const unsigned char *data, opus_int32 len, opus_int16 *size)
{
if (len<1)
{
*size = -1;
return -1;
} else if (data[0]<252)
{
*size = data[0];
return 1;
} else if (len<2)
{
*size = -1;
return -1;
} else {
*size = 4*data[1] + data[0];
return 2;
}
}
int opus_packet_get_samples_per_frame(const unsigned char *data,
opus_int32 Fs)
{
int audiosize;
if (data[0]&0x80)
{
audiosize = ((data[0]>>3)&0x3);
audiosize = (Fs<<audiosize)/400;
} else if ((data[0]&0x60) == 0x60)
{
audiosize = (data[0]&0x08) ? Fs/50 : Fs/100;
} else {
audiosize = ((data[0]>>3)&0x3);
if (audiosize == 3)
audiosize = Fs*60/1000;
else
audiosize = (Fs<<audiosize)/100;
}
return audiosize;
}
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, opus_int32 *packet_offset)
{
int i, bytes;
int count;
int cbr;
unsigned char ch, toc;
int framesize;
opus_int32 last_size;
opus_int32 pad = 0;
const unsigned char *data0 = data;
if (size==NULL || len<0)
return OPUS_BAD_ARG;
if (len==0)
return OPUS_INVALID_PACKET;
framesize = opus_packet_get_samples_per_frame(data, 48000);
cbr = 0;
toc = *data++;
len--;
last_size = len;
switch (toc&0x3)
{
/* One frame */
case 0:
count=1;
break;
/* Two CBR frames */
case 1:
count=2;
cbr = 1;
if (!self_delimited)
{
if (len&0x1)
return OPUS_INVALID_PACKET;
last_size = len/2;
/* If last_size doesn't fit in size[0], we'll catch it later */
size[0] = (opus_int16)last_size;
}
break;
/* Two VBR frames */
case 2:
count = 2;
bytes = parse_size(data, len, size);
len -= bytes;
if (size[0]<0 || size[0] > len)
return OPUS_INVALID_PACKET;
data += bytes;
last_size = len-size[0];
break;
/* Multiple CBR/VBR frames (from 0 to 120 ms) */
default: /*case 3:*/
if (len<1)
return OPUS_INVALID_PACKET;
/* Number of frames encoded in bits 0 to 5 */
ch = *data++;
count = ch&0x3F;
if (count <= 0 || framesize*(opus_int32)count > 5760)
return OPUS_INVALID_PACKET;
len--;
/* Padding flag is bit 6 */
if (ch&0x40)
{
int p;
do {
int tmp;
if (len<=0)
return OPUS_INVALID_PACKET;
p = *data++;
len--;
tmp = p==255 ? 254: p;
len -= tmp;
pad += tmp;
} while (p==255);
}
if (len<0)
return OPUS_INVALID_PACKET;
/* VBR flag is bit 7 */
cbr = !(ch&0x80);
if (!cbr)
{
/* VBR case */
last_size = len;
for (i=0;i<count-1;i++)
{
bytes = parse_size(data, len, size+i);
len -= bytes;
if (size[i]<0 || size[i] > len)
return OPUS_INVALID_PACKET;
data += bytes;
last_size -= bytes+size[i];
}
if (last_size<0)
return OPUS_INVALID_PACKET;
} else if (!self_delimited)
{
/* CBR case */
last_size = len/count;
if (last_size*count!=len)
return OPUS_INVALID_PACKET;
for (i=0;i<count-1;i++)
size[i] = (opus_int16)last_size;
}
break;
}
/* Self-delimited framing has an extra size for the last frame. */
if (self_delimited)
{
bytes = parse_size(data, len, size+count-1);
len -= bytes;
if (size[count-1]<0 || size[count-1] > len)
return OPUS_INVALID_PACKET;
data += bytes;
/* For CBR packets, apply the size to all the frames. */
if (cbr)
{
if (size[count-1]*count > len)
return OPUS_INVALID_PACKET;
for (i=0;i<count-1;i++)
size[i] = size[count-1];
} else if (bytes+size[count-1] > last_size)
return OPUS_INVALID_PACKET;
} else
{
/* Because it's not encoded explicitly, it's possible the size of the
last packet (or all the packets, for the CBR case) is larger than
1275. Reject them here.*/
if (last_size > 1275)
return OPUS_INVALID_PACKET;
size[count-1] = (opus_int16)last_size;
}
if (payload_offset)
*payload_offset = (int)(data-data0);
for (i=0;i<count;i++)
{
if (frames)
frames[i] = data;
data += size[i];
}
if (packet_offset)
*packet_offset = pad+(opus_int32)(data-data0);
if (out_toc)
*out_toc = toc;
return count;
}
int opus_packet_parse(const unsigned char *data, opus_int32 len,
unsigned char *out_toc, const unsigned char *frames[48],
opus_int16 size[48], int *payload_offset)
{
return opus_packet_parse_impl(data, len, 0, out_toc,
frames, size, payload_offset, NULL);
}

View File

@@ -0,0 +1,981 @@
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
Written by Jean-Marc Valin and Koen Vos */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/**
* @file opus.h
* @brief Opus reference implementation API
*/
#ifndef OPUS_H
#define OPUS_H
#include "opus_types.h"
#include "opus_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @mainpage Opus
*
* The Opus codec is designed for interactive speech and audio transmission over the Internet.
* It is designed by the IETF Codec Working Group and incorporates technology from
* Skype's SILK codec and Xiph.Org's CELT codec.
*
* The Opus codec is designed to handle a wide range of interactive audio applications,
* including Voice over IP, videoconferencing, in-game chat, and even remote live music
* performances. It can scale from low bit-rate narrowband speech to very high quality
* stereo music. Its main features are:
* @li Sampling rates from 8 to 48 kHz
* @li Bit-rates from 6 kb/s to 510 kb/s
* @li Support for both constant bit-rate (CBR) and variable bit-rate (VBR)
* @li Audio bandwidth from narrowband to full-band
* @li Support for speech and music
* @li Support for mono and stereo
* @li Support for multichannel (up to 255 channels)
* @li Frame sizes from 2.5 ms to 60 ms
* @li Good loss robustness and packet loss concealment (PLC)
* @li Floating point and fixed-point implementation
*
* Documentation sections:
* @li @ref opus_encoder
* @li @ref opus_decoder
* @li @ref opus_repacketizer
* @li @ref opus_multistream
* @li @ref opus_libinfo
* @li @ref opus_custom
*/
/** @defgroup opus_encoder Opus Encoder
* @{
*
* @brief This page describes the process and functions used to encode Opus.
*
* Since Opus is a stateful codec, the encoding process starts with creating an encoder
* state. This can be done with:
*
* @code
* int error;
* OpusEncoder *enc;
* enc = opus_encoder_create(Fs, channels, application, &error);
* @endcode
*
* From this point, @c enc can be used for encoding an audio stream. An encoder state
* @b must @b not be used for more than one stream at the same time. Similarly, the encoder
* state @b must @b not be re-initialized for each frame.
*
* While opus_encoder_create() allocates memory for the state, it's also possible
* to initialize pre-allocated memory:
*
* @code
* int size;
* int error;
* OpusEncoder *enc;
* size = opus_encoder_get_size(channels);
* enc = malloc(size);
* error = opus_encoder_init(enc, Fs, channels, application);
* @endcode
*
* where opus_encoder_get_size() returns the required size for the encoder state. Note that
* future versions of this code may change the size, so no assuptions should be made about it.
*
* The encoder state is always continuous in memory and only a shallow copy is sufficient
* to copy it (e.g. memcpy())
*
* It is possible to change some of the encoder's settings using the opus_encoder_ctl()
* interface. All these settings already default to the recommended value, so they should
* only be changed when necessary. The most common settings one may want to change are:
*
* @code
* opus_encoder_ctl(enc, OPUS_SET_BITRATE(bitrate));
* opus_encoder_ctl(enc, OPUS_SET_COMPLEXITY(complexity));
* opus_encoder_ctl(enc, OPUS_SET_SIGNAL(signal_type));
* @endcode
*
* where
*
* @arg bitrate is in bits per second (b/s)
* @arg complexity is a value from 1 to 10, where 1 is the lowest complexity and 10 is the highest
* @arg signal_type is either OPUS_AUTO (default), OPUS_SIGNAL_VOICE, or OPUS_SIGNAL_MUSIC
*
* See @ref opus_encoderctls and @ref opus_genericctls for a complete list of parameters that can be set or queried. Most parameters can be set or changed at any time during a stream.
*
* To encode a frame, opus_encode() or opus_encode_float() must be called with exactly one frame (2.5, 5, 10, 20, 40 or 60 ms) of audio data:
* @code
* len = opus_encode(enc, audio_frame, frame_size, packet, max_packet);
* @endcode
*
* where
* <ul>
* <li>audio_frame is the audio data in opus_int16 (or float for opus_encode_float())</li>
* <li>frame_size is the duration of the frame in samples (per channel)</li>
* <li>packet is the byte array to which the compressed data is written</li>
* <li>max_packet is the maximum number of bytes that can be written in the packet (4000 bytes is recommended).
* Do not use max_packet to control VBR target bitrate, instead use the #OPUS_SET_BITRATE CTL.</li>
* </ul>
*
* opus_encode() and opus_encode_float() return the number of bytes actually written to the packet.
* The return value <b>can be negative</b>, which indicates that an error has occurred. If the return value
* is 2 bytes or less, then the packet does not need to be transmitted (DTX).
*
* Once the encoder state if no longer needed, it can be destroyed with
*
* @code
* opus_encoder_destroy(enc);
* @endcode
*
* If the encoder was created with opus_encoder_init() rather than opus_encoder_create(),
* then no action is required aside from potentially freeing the memory that was manually
* allocated for it (calling free(enc) for the example above)
*
*/
/** Opus encoder state.
* This contains the complete state of an Opus encoder.
* It is position independent and can be freely copied.
* @see opus_encoder_create,opus_encoder_init
*/
typedef struct OpusEncoder OpusEncoder;
/** Gets the size of an <code>OpusEncoder</code> structure.
* @param[in] channels <tt>int</tt>: Number of channels.
* This must be 1 or 2.
* @returns The size in bytes.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_encoder_get_size(int channels);
/**
*/
/** Allocates and initializes an encoder state.
* There are three coding modes:
*
* @ref OPUS_APPLICATION_VOIP gives best quality at a given bitrate for voice
* signals. It enhances the input signal by high-pass filtering and
* emphasizing formants and harmonics. Optionally it includes in-band
* forward error correction to protect against packet loss. Use this
* mode for typical VoIP applications. Because of the enhancement,
* even at high bitrates the output may sound different from the input.
*
* @ref OPUS_APPLICATION_AUDIO gives best quality at a given bitrate for most
* non-voice signals like music. Use this mode for music and mixed
* (music/voice) content, broadcast, and applications requiring less
* than 15 ms of coding delay.
*
* @ref OPUS_APPLICATION_RESTRICTED_LOWDELAY configures low-delay mode that
* disables the speech-optimized mode in exchange for slightly reduced delay.
* This mode can only be set on an newly initialized or freshly reset encoder
* because it changes the codec delay.
*
* This is useful when the caller knows that the speech-optimized modes will not be needed (use with caution).
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
* @param [in] application <tt>int</tt>: Coding mode (@ref OPUS_APPLICATION_VOIP/@ref OPUS_APPLICATION_AUDIO/@ref OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @param [out] error <tt>int*</tt>: @ref opus_errorcodes
* @note Regardless of the sampling rate and number channels selected, the Opus encoder
* can switch to a lower audio bandwidth or number of channels if the bitrate
* selected is too low. This also means that it is safe to always use 48 kHz stereo input
* and let the encoder optimize the encoding.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusEncoder *opus_encoder_create(
opus_int32 Fs,
int channels,
int application,
int *error
);
/** Initializes a previously allocated encoder state
* The memory pointed to by st must be at least the size returned by opus_encoder_get_size().
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_encoder_create(),opus_encoder_get_size()
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate of input signal (Hz)
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) in input signal
* @param [in] application <tt>int</tt>: Coding mode (OPUS_APPLICATION_VOIP/OPUS_APPLICATION_AUDIO/OPUS_APPLICATION_RESTRICTED_LOWDELAY)
* @retval #OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_encoder_init(
OpusEncoder *st,
opus_int32 Fs,
int channels,
int application
) OPUS_ARG_NONNULL(1);
/** Encodes an Opus frame.
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
* @param [in] pcm <tt>opus_int16*</tt>: Input signal (interleaved if 2 channels). length is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
* input signal.
* This must be an Opus frame size for
* the encoder's sampling rate.
* For example, at 48 kHz the permitted
* values are 120, 240, 480, 960, 1920,
* and 2880.
* Passing in a duration of less than
* 10 ms (480 samples at 48 kHz) will
* prevent the encoder from using the LPC
* or hybrid modes.
* @param [out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode(
OpusEncoder *st,
const opus_int16 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes an Opus frame from floating point input.
* @param [in] st <tt>OpusEncoder*</tt>: Encoder state
* @param [in] pcm <tt>float*</tt>: Input in float format (interleaved if 2 channels), with a normal range of +/-1.0.
* Samples with a range beyond +/-1.0 are supported but will
* be clipped by decoders using the integer API and should
* only be used if it is known that the far end supports
* extended dynamic range.
* length is frame_size*channels*sizeof(float)
* @param [in] frame_size <tt>int</tt>: Number of samples per channel in the
* input signal.
* This must be an Opus frame size for
* the encoder's sampling rate.
* For example, at 48 kHz the permitted
* values are 120, 240, 480, 960, 1920,
* and 2880.
* Passing in a duration of less than
* 10 ms (480 samples at 48 kHz) will
* prevent the encoder from using the LPC
* or hybrid modes.
* @param [out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_encode_float(
OpusEncoder *st,
const float *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Frees an <code>OpusEncoder</code> allocated by opus_encoder_create().
* @param[in] st <tt>OpusEncoder*</tt>: State to be freed.
*/
OPUS_EXPORT void opus_encoder_destroy(OpusEncoder *st);
/** Perform a CTL function on an Opus encoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @param st <tt>OpusEncoder*</tt>: Encoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls or
* @ref opus_encoderctls.
* @see opus_genericctls
* @see opus_encoderctls
*/
OPUS_EXPORT int opus_encoder_ctl(OpusEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
/** @defgroup opus_decoder Opus Decoder
* @{
*
* @brief This page describes the process and functions used to decode Opus.
*
* The decoding process also starts with creating a decoder
* state. This can be done with:
* @code
* int error;
* OpusDecoder *dec;
* dec = opus_decoder_create(Fs, channels, &error);
* @endcode
* where
* @li Fs is the sampling rate and must be 8000, 12000, 16000, 24000, or 48000
* @li channels is the number of channels (1 or 2)
* @li error will hold the error code in case of failure (or #OPUS_OK on success)
* @li the return value is a newly created decoder state to be used for decoding
*
* While opus_decoder_create() allocates memory for the state, it's also possible
* to initialize pre-allocated memory:
* @code
* int size;
* int error;
* OpusDecoder *dec;
* size = opus_decoder_get_size(channels);
* dec = malloc(size);
* error = opus_decoder_init(dec, Fs, channels);
* @endcode
* where opus_decoder_get_size() returns the required size for the decoder state. Note that
* future versions of this code may change the size, so no assuptions should be made about it.
*
* The decoder state is always continuous in memory and only a shallow copy is sufficient
* to copy it (e.g. memcpy())
*
* To decode a frame, opus_decode() or opus_decode_float() must be called with a packet of compressed audio data:
* @code
* frame_size = opus_decode(dec, packet, len, decoded, max_size, 0);
* @endcode
* where
*
* @li packet is the byte array containing the compressed data
* @li len is the exact number of bytes contained in the packet
* @li decoded is the decoded audio data in opus_int16 (or float for opus_decode_float())
* @li max_size is the max duration of the frame in samples (per channel) that can fit into the decoded_frame array
*
* opus_decode() and opus_decode_float() return the number of samples (per channel) decoded from the packet.
* If that value is negative, then an error has occurred. This can occur if the packet is corrupted or if the audio
* buffer is too small to hold the decoded audio.
*
* Opus is a stateful codec with overlapping blocks and as a result Opus
* packets are not coded independently of each other. Packets must be
* passed into the decoder serially and in the correct order for a correct
* decode. Lost packets can be replaced with loss concealment by calling
* the decoder with a null pointer and zero length for the missing packet.
*
* A single codec state may only be accessed from a single thread at
* a time and any required locking must be performed by the caller. Separate
* streams must be decoded with separate decoder states and can be decoded
* in parallel unless the library was compiled with NONTHREADSAFE_PSEUDOSTACK
* defined.
*
*/
/** Opus decoder state.
* This contains the complete state of an Opus decoder.
* It is position independent and can be freely copied.
* @see opus_decoder_create,opus_decoder_init
*/
typedef struct OpusDecoder OpusDecoder;
/** Gets the size of an <code>OpusDecoder</code> structure.
* @param [in] channels <tt>int</tt>: Number of channels.
* This must be 1 or 2.
* @returns The size in bytes.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_size(int channels);
/** Allocates and initializes a decoder state.
* @param [in] Fs <tt>opus_int32</tt>: Sample rate to decode at (Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
* @param [out] error <tt>int*</tt>: #OPUS_OK Success or @ref opus_errorcodes
*
* Internally Opus stores data at 48000 Hz, so that should be the default
* value for Fs. However, the decoder can efficiently decode to buffers
* at 8, 12, 16, and 24 kHz so if for some reason the caller cannot use
* data at the full sample rate, or knows the compressed data doesn't
* use the full frequency range, it can request decoding at a reduced
* rate. Likewise, the decoder is capable of filling in either mono or
* interleaved stereo pcm buffers, at the caller's request.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusDecoder *opus_decoder_create(
opus_int32 Fs,
int channels,
int *error
);
/** Initializes a previously allocated decoder state.
* The state must be at least the size returned by opus_decoder_get_size().
* This is intended for applications which use their own allocator instead of malloc. @see opus_decoder_create,opus_decoder_get_size
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state.
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate to decode to (Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param [in] channels <tt>int</tt>: Number of channels (1 or 2) to decode
* @retval #OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_EXPORT int opus_decoder_init(
OpusDecoder *st,
opus_int32 Fs,
int channels
) OPUS_ARG_NONNULL(1);
/** Decode an Opus packet.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload*
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
* decoded. If no such data is available, the frame is decoded as if it were lost.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode(
OpusDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int16 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an Opus packet with floating point output.
* @param [in] st <tt>OpusDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>opus_int32</tt>: Number of bytes in payload
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(float)
* @param [in] frame_size Number of samples per channel of available space in \a pcm.
* If this is less than the maximum packet duration (120ms; 5760 for 48kHz), this function will
* not be capable of decoding some packets. In the case of PLC (data==NULL) or FEC (decode_fec=1),
* then frame_size needs to be exactly the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the next incoming packet. For the PLC and
* FEC cases, frame_size <b>must</b> be a multiple of 2.5 ms.
* @param [in] decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band forward error correction data be
* decoded. If no such data is available the frame is decoded as if it were lost.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decode_float(
OpusDecoder *st,
const unsigned char *data,
opus_int32 len,
float *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus decoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @param st <tt>OpusDecoder*</tt>: Decoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls or
* @ref opus_decoderctls.
* @see opus_genericctls
* @see opus_decoderctls
*/
OPUS_EXPORT int opus_decoder_ctl(OpusDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
/** Frees an <code>OpusDecoder</code> allocated by opus_decoder_create().
* @param[in] st <tt>OpusDecoder*</tt>: State to be freed.
*/
OPUS_EXPORT void opus_decoder_destroy(OpusDecoder *st);
/** Parse an opus packet into one or more frames.
* Opus_decode will perform this operation internally so most applications do
* not need to use this function.
* This function does not copy the frames, the returned pointers are pointers into
* the input packet.
* @param [in] data <tt>char*</tt>: Opus packet to be parsed
* @param [in] len <tt>opus_int32</tt>: size of data
* @param [out] out_toc <tt>char*</tt>: TOC pointer
* @param [out] frames <tt>char*[48]</tt> encapsulated frames
* @param [out] size <tt>opus_int16[48]</tt> sizes of the encapsulated frames
* @param [out] payload_offset <tt>int*</tt>: returns the position of the payload within the packet (in bytes)
* @returns number of frames
*/
OPUS_EXPORT int opus_packet_parse(
const unsigned char *data,
opus_int32 len,
unsigned char *out_toc,
const unsigned char *frames[48],
opus_int16 size[48],
int *payload_offset
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5);
/** Gets the bandwidth of an Opus packet.
* @param [in] data <tt>char*</tt>: Opus packet
* @retval OPUS_BANDWIDTH_NARROWBAND Narrowband (4kHz bandpass)
* @retval OPUS_BANDWIDTH_MEDIUMBAND Mediumband (6kHz bandpass)
* @retval OPUS_BANDWIDTH_WIDEBAND Wideband (8kHz bandpass)
* @retval OPUS_BANDWIDTH_SUPERWIDEBAND Superwideband (12kHz bandpass)
* @retval OPUS_BANDWIDTH_FULLBAND Fullband (20kHz bandpass)
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_bandwidth(const unsigned char *data) OPUS_ARG_NONNULL(1);
/** Gets the number of samples per frame from an Opus packet.
* @param [in] data <tt>char*</tt>: Opus packet.
* This must contain at least one byte of
* data.
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
* This must be a multiple of 400, or
* inaccurate results will be returned.
* @returns Number of samples per frame.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_samples_per_frame(const unsigned char *data, opus_int32 Fs) OPUS_ARG_NONNULL(1);
/** Gets the number of channels from an Opus packet.
* @param [in] data <tt>char*</tt>: Opus packet
* @returns Number of channels
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_channels(const unsigned char *data) OPUS_ARG_NONNULL(1);
/** Gets the number of frames in an Opus packet.
* @param [in] packet <tt>char*</tt>: Opus packet
* @param [in] len <tt>opus_int32</tt>: Length of packet
* @returns Number of frames
* @retval OPUS_BAD_ARG Insufficient data was passed to the function
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_frames(const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1);
/** Gets the number of samples of an Opus packet.
* @param [in] packet <tt>char*</tt>: Opus packet
* @param [in] len <tt>opus_int32</tt>: Length of packet
* @param [in] Fs <tt>opus_int32</tt>: Sampling rate in Hz.
* This must be a multiple of 400, or
* inaccurate results will be returned.
* @returns Number of samples
* @retval OPUS_BAD_ARG Insufficient data was passed to the function
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_packet_get_nb_samples(const unsigned char packet[], opus_int32 len, opus_int32 Fs) OPUS_ARG_NONNULL(1);
/** Gets the number of samples of an Opus packet.
* @param [in] dec <tt>OpusDecoder*</tt>: Decoder state
* @param [in] packet <tt>char*</tt>: Opus packet
* @param [in] len <tt>opus_int32</tt>: Length of packet
* @returns Number of samples
* @retval OPUS_BAD_ARG Insufficient data was passed to the function
* @retval OPUS_INVALID_PACKET The compressed data passed is corrupted or of an unsupported type
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_decoder_get_nb_samples(const OpusDecoder *dec, const unsigned char packet[], opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
/** Applies soft-clipping to bring a float signal within the [-1,1] range. If
* the signal is already in that range, nothing is done. If there are values
* outside of [-1,1], then the signal is clipped as smoothly as possible to
* both fit in the range and avoid creating excessive distortion in the
* process.
* @param [in,out] pcm <tt>float*</tt>: Input PCM and modified PCM
* @param [in] frame_size <tt>int</tt> Number of samples per channel to process
* @param [in] channels <tt>int</tt>: Number of channels
* @param [in,out] softclip_mem <tt>float*</tt>: State memory for the soft clipping process (one float per channel, initialized to zero)
*/
OPUS_EXPORT void opus_pcm_soft_clip(float *pcm, int frame_size, int channels, float *softclip_mem);
/**@}*/
/** @defgroup opus_repacketizer Repacketizer
* @{
*
* The repacketizer can be used to merge multiple Opus packets into a single
* packet or alternatively to split Opus packets that have previously been
* merged. Splitting valid Opus packets is always guaranteed to succeed,
* whereas merging valid packets only succeeds if all frames have the same
* mode, bandwidth, and frame size, and when the total duration of the merged
* packet is no more than 120 ms. The 120 ms limit comes from the
* specification and limits decoder memory requirements at a point where
* framing overhead becomes negligible.
*
* The repacketizer currently only operates on elementary Opus
* streams. It will not manipualte multistream packets successfully, except in
* the degenerate case where they consist of data from a single stream.
*
* The repacketizing process starts with creating a repacketizer state, either
* by calling opus_repacketizer_create() or by allocating the memory yourself,
* e.g.,
* @code
* OpusRepacketizer *rp;
* rp = (OpusRepacketizer*)malloc(opus_repacketizer_get_size());
* if (rp != NULL)
* opus_repacketizer_init(rp);
* @endcode
*
* Then the application should submit packets with opus_repacketizer_cat(),
* extract new packets with opus_repacketizer_out() or
* opus_repacketizer_out_range(), and then reset the state for the next set of
* input packets via opus_repacketizer_init().
*
* For example, to split a sequence of packets into individual frames:
* @code
* unsigned char *data;
* int len;
* while (get_next_packet(&data, &len))
* {
* unsigned char out[1276];
* opus_int32 out_len;
* int nb_frames;
* int err;
* int i;
* err = opus_repacketizer_cat(rp, data, len);
* if (err != OPUS_OK)
* {
* release_packet(data);
* return err;
* }
* nb_frames = opus_repacketizer_get_nb_frames(rp);
* for (i = 0; i < nb_frames; i++)
* {
* out_len = opus_repacketizer_out_range(rp, i, i+1, out, sizeof(out));
* if (out_len < 0)
* {
* release_packet(data);
* return (int)out_len;
* }
* output_next_packet(out, out_len);
* }
* opus_repacketizer_init(rp);
* release_packet(data);
* }
* @endcode
*
* Alternatively, to combine a sequence of frames into packets that each
* contain up to <code>TARGET_DURATION_MS</code> milliseconds of data:
* @code
* // The maximum number of packets with duration TARGET_DURATION_MS occurs
* // when the frame size is 2.5 ms, for a total of (TARGET_DURATION_MS*2/5)
* // packets.
* unsigned char *data[(TARGET_DURATION_MS*2/5)+1];
* opus_int32 len[(TARGET_DURATION_MS*2/5)+1];
* int nb_packets;
* unsigned char out[1277*(TARGET_DURATION_MS*2/2)];
* opus_int32 out_len;
* int prev_toc;
* nb_packets = 0;
* while (get_next_packet(data+nb_packets, len+nb_packets))
* {
* int nb_frames;
* int err;
* nb_frames = opus_packet_get_nb_frames(data[nb_packets], len[nb_packets]);
* if (nb_frames < 1)
* {
* release_packets(data, nb_packets+1);
* return nb_frames;
* }
* nb_frames += opus_repacketizer_get_nb_frames(rp);
* // If adding the next packet would exceed our target, or it has an
* // incompatible TOC sequence, output the packets we already have before
* // submitting it.
* // N.B., The nb_packets > 0 check ensures we've submitted at least one
* // packet since the last call to opus_repacketizer_init(). Otherwise a
* // single packet longer than TARGET_DURATION_MS would cause us to try to
* // output an (invalid) empty packet. It also ensures that prev_toc has
* // been set to a valid value. Additionally, len[nb_packets] > 0 is
* // guaranteed by the call to opus_packet_get_nb_frames() above, so the
* // reference to data[nb_packets][0] should be valid.
* if (nb_packets > 0 && (
* ((prev_toc & 0xFC) != (data[nb_packets][0] & 0xFC)) ||
* opus_packet_get_samples_per_frame(data[nb_packets], 48000)*nb_frames >
* TARGET_DURATION_MS*48))
* {
* out_len = opus_repacketizer_out(rp, out, sizeof(out));
* if (out_len < 0)
* {
* release_packets(data, nb_packets+1);
* return (int)out_len;
* }
* output_next_packet(out, out_len);
* opus_repacketizer_init(rp);
* release_packets(data, nb_packets);
* data[0] = data[nb_packets];
* len[0] = len[nb_packets];
* nb_packets = 0;
* }
* err = opus_repacketizer_cat(rp, data[nb_packets], len[nb_packets]);
* if (err != OPUS_OK)
* {
* release_packets(data, nb_packets+1);
* return err;
* }
* prev_toc = data[nb_packets][0];
* nb_packets++;
* }
* // Output the final, partial packet.
* if (nb_packets > 0)
* {
* out_len = opus_repacketizer_out(rp, out, sizeof(out));
* release_packets(data, nb_packets);
* if (out_len < 0)
* return (int)out_len;
* output_next_packet(out, out_len);
* }
* @endcode
*
* An alternate way of merging packets is to simply call opus_repacketizer_cat()
* unconditionally until it fails. At that point, the merged packet can be
* obtained with opus_repacketizer_out() and the input packet for which
* opus_repacketizer_cat() needs to be re-added to a newly reinitialized
* repacketizer state.
*/
typedef struct OpusRepacketizer OpusRepacketizer;
/** Gets the size of an <code>OpusRepacketizer</code> structure.
* @returns The size in bytes.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_size(void);
/** (Re)initializes a previously allocated repacketizer state.
* The state must be at least the size returned by opus_repacketizer_get_size().
* This can be used for applications which use their own allocator instead of
* malloc().
* It must also be called to reset the queue of packets waiting to be
* repacketized, which is necessary if the maximum packet duration of 120 ms
* is reached or if you wish to submit packets with a different Opus
* configuration (coding mode, audio bandwidth, frame size, or channel count).
* Failure to do so will prevent a new packet from being added with
* opus_repacketizer_cat().
* @see opus_repacketizer_create
* @see opus_repacketizer_get_size
* @see opus_repacketizer_cat
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to
* (re)initialize.
* @returns A pointer to the same repacketizer state that was passed in.
*/
OPUS_EXPORT OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
/** Allocates memory and initializes the new repacketizer with
* opus_repacketizer_init().
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusRepacketizer *opus_repacketizer_create(void);
/** Frees an <code>OpusRepacketizer</code> allocated by
* opus_repacketizer_create().
* @param[in] rp <tt>OpusRepacketizer*</tt>: State to be freed.
*/
OPUS_EXPORT void opus_repacketizer_destroy(OpusRepacketizer *rp);
/** Add a packet to the current repacketizer state.
* This packet must match the configuration of any packets already submitted
* for repacketization since the last call to opus_repacketizer_init().
* This means that it must have the same coding mode, audio bandwidth, frame
* size, and channel count.
* This can be checked in advance by examining the top 6 bits of the first
* byte of the packet, and ensuring they match the top 6 bits of the first
* byte of any previously submitted packet.
* The total duration of audio in the repacketizer state also must not exceed
* 120 ms, the maximum duration of a single packet, after adding this packet.
*
* The contents of the current repacketizer state can be extracted into new
* packets using opus_repacketizer_out() or opus_repacketizer_out_range().
*
* In order to add a packet with a different configuration or to add more
* audio beyond 120 ms, you must clear the repacketizer state by calling
* opus_repacketizer_init().
* If a packet is too large to add to the current repacketizer state, no part
* of it is added, even if it contains multiple frames, some of which might
* fit.
* If you wish to be able to add parts of such packets, you should first use
* another repacketizer to split the packet into pieces and add them
* individually.
* @see opus_repacketizer_out_range
* @see opus_repacketizer_out
* @see opus_repacketizer_init
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state to which to
* add the packet.
* @param[in] data <tt>const unsigned char*</tt>: The packet data.
* The application must ensure
* this pointer remains valid
* until the next call to
* opus_repacketizer_init() or
* opus_repacketizer_destroy().
* @param len <tt>opus_int32</tt>: The number of bytes in the packet data.
* @returns An error code indicating whether or not the operation succeeded.
* @retval #OPUS_OK The packet's contents have been added to the repacketizer
* state.
* @retval #OPUS_INVALID_PACKET The packet did not have a valid TOC sequence,
* the packet's TOC sequence was not compatible
* with previously submitted packets (because
* the coding mode, audio bandwidth, frame size,
* or channel count did not match), or adding
* this packet would increase the total amount of
* audio stored in the repacketizer state to more
* than 120 ms.
*/
OPUS_EXPORT int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
/** Construct a new packet from data previously submitted to the repacketizer
* state via opus_repacketizer_cat().
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
* construct the new packet.
* @param begin <tt>int</tt>: The index of the first frame in the current
* repacketizer state to include in the output.
* @param end <tt>int</tt>: One past the index of the last frame in the
* current repacketizer state to include in the
* output.
* @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
* store the output packet.
* @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
* the output buffer. In order to guarantee
* success, this should be at least
* <code>1276</code> for a single frame,
* or for multiple frames,
* <code>1277*(end-begin)</code>.
* However, <code>1*(end-begin)</code> plus
* the size of all packet data submitted to
* the repacketizer since the last call to
* opus_repacketizer_init() or
* opus_repacketizer_create() is also
* sufficient, and possibly much smaller.
* @returns The total size of the output packet on success, or an error code
* on failure.
* @retval #OPUS_BAD_ARG <code>[begin,end)</code> was an invalid range of
* frames (begin < 0, begin >= end, or end >
* opus_repacketizer_get_nb_frames()).
* @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
* complete output packet.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Return the total number of frames contained in packet data submitted to
* the repacketizer state so far via opus_repacketizer_cat() since the last
* call to opus_repacketizer_init() or opus_repacketizer_create().
* This defines the valid range of packets that can be extracted with
* opus_repacketizer_out_range() or opus_repacketizer_out().
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state containing the
* frames.
* @returns The total number of frames contained in the packet data submitted
* to the repacketizer state.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp) OPUS_ARG_NONNULL(1);
/** Construct a new packet from data previously submitted to the repacketizer
* state via opus_repacketizer_cat().
* This is a convenience routine that returns all the data submitted so far
* in a single packet.
* It is equivalent to calling
* @code
* opus_repacketizer_out_range(rp, 0, opus_repacketizer_get_nb_frames(rp),
* data, maxlen)
* @endcode
* @param rp <tt>OpusRepacketizer*</tt>: The repacketizer state from which to
* construct the new packet.
* @param[out] data <tt>const unsigned char*</tt>: The buffer in which to
* store the output packet.
* @param maxlen <tt>opus_int32</tt>: The maximum number of bytes to store in
* the output buffer. In order to guarantee
* success, this should be at least
* <code>1277*opus_repacketizer_get_nb_frames(rp)</code>.
* However,
* <code>1*opus_repacketizer_get_nb_frames(rp)</code>
* plus the size of all packet data
* submitted to the repacketizer since the
* last call to opus_repacketizer_init() or
* opus_repacketizer_create() is also
* sufficient, and possibly much smaller.
* @returns The total size of the output packet on success, or an error code
* on failure.
* @retval #OPUS_BUFFER_TOO_SMALL \a maxlen was insufficient to contain the
* complete output packet.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen) OPUS_ARG_NONNULL(1);
/** Pads a given Opus packet to a larger size (possibly changing the TOC sequence).
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
* packet to pad.
* @param len <tt>opus_int32</tt>: The size of the packet.
* This must be at least 1.
* @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
* This must be at least as large as len.
* @returns an error code
* @retval #OPUS_OK \a on success.
* @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
*/
OPUS_EXPORT int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len);
/** Remove all padding from a given Opus packet and rewrite the TOC sequence to
* minimize space usage.
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
* packet to strip.
* @param len <tt>opus_int32</tt>: The size of the packet.
* This must be at least 1.
* @returns The new size of the output packet on success, or an error code
* on failure.
* @retval #OPUS_BAD_ARG \a len was less than 1.
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len);
/** Pads a given Opus multi-stream packet to a larger size (possibly changing the TOC sequence).
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
* packet to pad.
* @param len <tt>opus_int32</tt>: The size of the packet.
* This must be at least 1.
* @param new_len <tt>opus_int32</tt>: The desired size of the packet after padding.
* This must be at least 1.
* @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
* This must be at least as large as len.
* @returns an error code
* @retval #OPUS_OK \a on success.
* @retval #OPUS_BAD_ARG \a len was less than 1.
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
*/
OPUS_EXPORT int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams);
/** Remove all padding from a given Opus multi-stream packet and rewrite the TOC sequence to
* minimize space usage.
* @param[in,out] data <tt>const unsigned char*</tt>: The buffer containing the
* packet to strip.
* @param len <tt>opus_int32</tt>: The size of the packet.
* This must be at least 1.
* @param nb_streams <tt>opus_int32</tt>: The number of streams (not channels) in the packet.
* This must be at least 1.
* @returns The new size of the output packet on success, or an error code
* on failure.
* @retval #OPUS_BAD_ARG \a len was less than 1 or new_len was less than len.
* @retval #OPUS_INVALID_PACKET \a data did not contain a valid Opus packet.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_H */

View File

@@ -0,0 +1,16 @@
# Opus codec reference implementation pkg-config file
prefix=/usr/local
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
Name: Opus
Description: Opus IETF audio codec (fixed-point build)
URL: https://opus-codec.org/
Version: 1.3.1
Requires:
Conflicts:
Libs: -L${libdir} -lopus
Libs.private: -lm
Cflags: -I${includedir}/opus

View File

@@ -0,0 +1,342 @@
/* Copyright (c) 2007-2008 CSIRO
Copyright (c) 2007-2009 Xiph.Org Foundation
Copyright (c) 2008-2012 Gregory Maxwell
Written by Jean-Marc Valin and Gregory Maxwell */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/**
@file opus_custom.h
@brief Opus-Custom reference implementation API
*/
#ifndef OPUS_CUSTOM_H
#define OPUS_CUSTOM_H
#include "opus_defines.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifdef CUSTOM_MODES
# define OPUS_CUSTOM_EXPORT OPUS_EXPORT
# define OPUS_CUSTOM_EXPORT_STATIC OPUS_EXPORT
#else
# define OPUS_CUSTOM_EXPORT
# ifdef OPUS_BUILD
# define OPUS_CUSTOM_EXPORT_STATIC static OPUS_INLINE
# else
# define OPUS_CUSTOM_EXPORT_STATIC
# endif
#endif
/** @defgroup opus_custom Opus Custom
* @{
* Opus Custom is an optional part of the Opus specification and
* reference implementation which uses a distinct API from the regular
* API and supports frame sizes that are not normally supported.\ Use
* of Opus Custom is discouraged for all but very special applications
* for which a frame size different from 2.5, 5, 10, or 20 ms is needed
* (for either complexity or latency reasons) and where interoperability
* is less important.
*
* In addition to the interoperability limitations the use of Opus custom
* disables a substantial chunk of the codec and generally lowers the
* quality available at a given bitrate. Normally when an application needs
* a different frame size from the codec it should buffer to match the
* sizes but this adds a small amount of delay which may be important
* in some very low latency applications. Some transports (especially
* constant rate RF transports) may also work best with frames of
* particular durations.
*
* Libopus only supports custom modes if they are enabled at compile time.
*
* The Opus Custom API is similar to the regular API but the
* @ref opus_encoder_create and @ref opus_decoder_create calls take
* an additional mode parameter which is a structure produced by
* a call to @ref opus_custom_mode_create. Both the encoder and decoder
* must create a mode using the same sample rate (fs) and frame size
* (frame size) so these parameters must either be signaled out of band
* or fixed in a particular implementation.
*
* Similar to regular Opus the custom modes support on the fly frame size
* switching, but the sizes available depend on the particular frame size in
* use. For some initial frame sizes on a single on the fly size is available.
*/
/** Contains the state of an encoder. One encoder state is needed
for each stream. It is initialized once at the beginning of the
stream. Do *not* re-initialize the state for every frame.
@brief Encoder state
*/
typedef struct OpusCustomEncoder OpusCustomEncoder;
/** State of the decoder. One decoder state is needed for each stream.
It is initialized once at the beginning of the stream. Do *not*
re-initialize the state for every frame.
@brief Decoder state
*/
typedef struct OpusCustomDecoder OpusCustomDecoder;
/** The mode contains all the information necessary to create an
encoder. Both the encoder and decoder need to be initialized
with exactly the same mode, otherwise the output will be
corrupted.
@brief Mode configuration
*/
typedef struct OpusCustomMode OpusCustomMode;
/** Creates a new mode struct. This will be passed to an encoder or
* decoder. The mode MUST NOT BE DESTROYED until the encoders and
* decoders that use it are destroyed as well.
* @param [in] Fs <tt>int</tt>: Sampling rate (8000 to 96000 Hz)
* @param [in] frame_size <tt>int</tt>: Number of samples (per channel) to encode in each
* packet (64 - 1024, prime factorization must contain zero or more 2s, 3s, or 5s and no other primes)
* @param [out] error <tt>int*</tt>: Returned error code (if NULL, no error will be returned)
* @return A newly created mode
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomMode *opus_custom_mode_create(opus_int32 Fs, int frame_size, int *error);
/** Destroys a mode struct. Only call this after all encoders and
* decoders using this mode are destroyed as well.
* @param [in] mode <tt>OpusCustomMode*</tt>: Mode to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_mode_destroy(OpusCustomMode *mode);
#if !defined(OPUS_BUILD) || defined(CELT_ENCODER_C)
/* Encoder */
/** Gets the size of an OpusCustomEncoder structure.
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
* @param [in] channels <tt>int</tt>: Number of channels
* @returns size
*/
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_encoder_get_size(
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1);
# ifdef CUSTOM_MODES
/** Initializes a previously allocated encoder state
* The memory pointed to by st must be the size returned by opus_custom_encoder_get_size.
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_custom_encoder_create(),opus_custom_encoder_get_size()
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @return OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT int opus_custom_encoder_init(
OpusCustomEncoder *st,
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
# endif
#endif
/** Creates a new encoder state. Each stream needs its own encoder
* state (can't be shared across simultaneous streams).
* @param [in] mode <tt>OpusCustomMode*</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* decoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @param [out] error <tt>int*</tt>: Returns an error code
* @return Newly created encoder state.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomEncoder *opus_custom_encoder_create(
const OpusCustomMode *mode,
int channels,
int *error
) OPUS_ARG_NONNULL(1);
/** Destroys a an encoder state.
* @param[in] st <tt>OpusCustomEncoder*</tt>: State to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_encoder_destroy(OpusCustomEncoder *st);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>float*</tt>: PCM audio in float format, with a normal range of +/-1.0.
* Samples with a range beyond +/-1.0 are supported but will
* be clipped by decoders using the integer API and should
* only be used if it is known that the far end supports
* extended dynamic range. There must be exactly
* frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode_float(
OpusCustomEncoder *st,
const float *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a frame of audio.
* @param [in] st <tt>OpusCustomEncoder*</tt>: Encoder state
* @param [in] pcm <tt>opus_int16*</tt>: PCM audio in signed 16-bit format (native endian).
* There must be exactly frame_size samples per channel.
* @param [in] frame_size <tt>int</tt>: Number of samples per frame of input signal
* @param [out] compressed <tt>char *</tt>: The compressed data is written here. This may not alias pcm and must be at least maxCompressedBytes long.
* @param [in] maxCompressedBytes <tt>int</tt>: Maximum number of bytes to use for compressing the frame
* (can change from one frame to another)
* @return Number of bytes written to "compressed".
* If negative, an error has occurred (see error codes). It is IMPORTANT that
* the length returned be somehow transmitted to the decoder. Otherwise, no
* decoding is possible.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_encode(
OpusCustomEncoder *st,
const opus_int16 *pcm,
int frame_size,
unsigned char *compressed,
int maxCompressedBytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom encoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @see opus_encoderctls
*/
OPUS_CUSTOM_EXPORT int opus_custom_encoder_ctl(OpusCustomEncoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
#if !defined(OPUS_BUILD) || defined(CELT_DECODER_C)
/* Decoder */
/** Gets the size of an OpusCustomDecoder structure.
* @param [in] mode <tt>OpusCustomMode *</tt>: Mode configuration
* @param [in] channels <tt>int</tt>: Number of channels
* @returns size
*/
OPUS_CUSTOM_EXPORT_STATIC OPUS_WARN_UNUSED_RESULT int opus_custom_decoder_get_size(
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1);
/** Initializes a previously allocated decoder state
* The memory pointed to by st must be the size returned by opus_custom_decoder_get_size.
* This is intended for applications which use their own allocator instead of malloc.
* @see opus_custom_decoder_create(),opus_custom_decoder_get_size()
* To reset a previously initialized state use the OPUS_RESET_STATE CTL.
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] mode <tt>OpusCustomMode *</tt>: Contains all the information about the characteristics of
* the stream (must be the same characteristics as used for the
* encoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @return OPUS_OK Success or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT_STATIC int opus_custom_decoder_init(
OpusCustomDecoder *st,
const OpusCustomMode *mode,
int channels
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2);
#endif
/** Creates a new decoder state. Each stream needs its own decoder state (can't
* be shared across simultaneous streams).
* @param [in] mode <tt>OpusCustomMode</tt>: Contains all the information about the characteristics of the
* stream (must be the same characteristics as used for the encoder)
* @param [in] channels <tt>int</tt>: Number of channels
* @param [out] error <tt>int*</tt>: Returns an error code
* @return Newly created decoder state.
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT OpusCustomDecoder *opus_custom_decoder_create(
const OpusCustomMode *mode,
int channels,
int *error
) OPUS_ARG_NONNULL(1);
/** Destroys a an decoder state.
* @param[in] st <tt>OpusCustomDecoder*</tt>: State to be freed.
*/
OPUS_CUSTOM_EXPORT void opus_custom_decoder_destroy(OpusCustomDecoder *st);
/** Decode an opus custom frame with floating point output
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>float*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(float)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode_float(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
float *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode an opus custom frame
* @param [in] st <tt>OpusCustomDecoder*</tt>: Decoder state
* @param [in] data <tt>char*</tt>: Input payload. Use a NULL pointer to indicate packet loss
* @param [in] len <tt>int</tt>: Number of bytes in payload
* @param [out] pcm <tt>opus_int16*</tt>: Output signal (interleaved if 2 channels). length
* is frame_size*channels*sizeof(opus_int16)
* @param [in] frame_size Number of samples per channel of available space in *pcm.
* @returns Number of decoded samples or @ref opus_errorcodes
*/
OPUS_CUSTOM_EXPORT OPUS_WARN_UNUSED_RESULT int opus_custom_decode(
OpusCustomDecoder *st,
const unsigned char *data,
int len,
opus_int16 *pcm,
int frame_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on an Opus custom decoder.
*
* Generally the request and subsequent arguments are generated
* by a convenience macro.
* @see opus_genericctls
*/
OPUS_CUSTOM_EXPORT int opus_custom_decoder_ctl(OpusCustomDecoder * OPUS_RESTRICT st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_CUSTOM_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,799 @@
/* Copyright (c) 2010-2011 Xiph.Org Foundation, Skype Limited
Written by Jean-Marc Valin and Koen Vos */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/**
* @file opus_defines.h
* @brief Opus reference implementation constants
*/
#ifndef OPUS_DEFINES_H
#define OPUS_DEFINES_H
#include "opus_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @defgroup opus_errorcodes Error codes
* @{
*/
/** No error @hideinitializer*/
#define OPUS_OK 0
/** One or more invalid/out of range arguments @hideinitializer*/
#define OPUS_BAD_ARG -1
/** Not enough bytes allocated in the buffer @hideinitializer*/
#define OPUS_BUFFER_TOO_SMALL -2
/** An internal error was detected @hideinitializer*/
#define OPUS_INTERNAL_ERROR -3
/** The compressed data passed is corrupted @hideinitializer*/
#define OPUS_INVALID_PACKET -4
/** Invalid/unsupported request number @hideinitializer*/
#define OPUS_UNIMPLEMENTED -5
/** An encoder or decoder structure is invalid or already freed @hideinitializer*/
#define OPUS_INVALID_STATE -6
/** Memory allocation has failed @hideinitializer*/
#define OPUS_ALLOC_FAIL -7
/**@}*/
/** @cond OPUS_INTERNAL_DOC */
/**Export control for opus functions */
#ifndef OPUS_EXPORT
# if defined(WIN32)
# if defined(OPUS_BUILD) && defined(DLL_EXPORT)
# define OPUS_EXPORT __declspec(dllexport)
# else
# define OPUS_EXPORT
# endif
# elif defined(__GNUC__) && defined(OPUS_BUILD)
# define OPUS_EXPORT __attribute__ ((visibility ("default")))
# else
# define OPUS_EXPORT
# endif
#endif
# if !defined(OPUS_GNUC_PREREQ)
# if defined(__GNUC__)&&defined(__GNUC_MINOR__)
# define OPUS_GNUC_PREREQ(_maj,_min) \
((__GNUC__<<16)+__GNUC_MINOR__>=((_maj)<<16)+(_min))
# else
# define OPUS_GNUC_PREREQ(_maj,_min) 0
# endif
# endif
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if OPUS_GNUC_PREREQ(3,0)
# define OPUS_RESTRICT __restrict__
# elif (defined(_MSC_VER) && _MSC_VER >= 1400)
# define OPUS_RESTRICT __restrict
# else
# define OPUS_RESTRICT
# endif
#else
# define OPUS_RESTRICT restrict
#endif
#if (!defined(__STDC_VERSION__) || (__STDC_VERSION__ < 199901L) )
# if OPUS_GNUC_PREREQ(2,7)
# define OPUS_INLINE __inline__
# elif (defined(_MSC_VER))
# define OPUS_INLINE __inline
# else
# define OPUS_INLINE
# endif
#else
# define OPUS_INLINE inline
#endif
/**Warning attributes for opus functions
* NONNULL is not used in OPUS_BUILD to avoid the compiler optimizing out
* some paranoid null checks. */
#if defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
# define OPUS_WARN_UNUSED_RESULT __attribute__ ((__warn_unused_result__))
#else
# define OPUS_WARN_UNUSED_RESULT
#endif
#if !defined(OPUS_BUILD) && defined(__GNUC__) && OPUS_GNUC_PREREQ(3, 4)
# define OPUS_ARG_NONNULL(_x) __attribute__ ((__nonnull__(_x)))
#else
# define OPUS_ARG_NONNULL(_x)
#endif
/** These are the actual Encoder CTL ID numbers.
* They should not be used directly by applications.
* In general, SETs should be even and GETs should be odd.*/
#define OPUS_SET_APPLICATION_REQUEST 4000
#define OPUS_GET_APPLICATION_REQUEST 4001
#define OPUS_SET_BITRATE_REQUEST 4002
#define OPUS_GET_BITRATE_REQUEST 4003
#define OPUS_SET_MAX_BANDWIDTH_REQUEST 4004
#define OPUS_GET_MAX_BANDWIDTH_REQUEST 4005
#define OPUS_SET_VBR_REQUEST 4006
#define OPUS_GET_VBR_REQUEST 4007
#define OPUS_SET_BANDWIDTH_REQUEST 4008
#define OPUS_GET_BANDWIDTH_REQUEST 4009
#define OPUS_SET_COMPLEXITY_REQUEST 4010
#define OPUS_GET_COMPLEXITY_REQUEST 4011
#define OPUS_SET_INBAND_FEC_REQUEST 4012
#define OPUS_GET_INBAND_FEC_REQUEST 4013
#define OPUS_SET_PACKET_LOSS_PERC_REQUEST 4014
#define OPUS_GET_PACKET_LOSS_PERC_REQUEST 4015
#define OPUS_SET_DTX_REQUEST 4016
#define OPUS_GET_DTX_REQUEST 4017
#define OPUS_SET_VBR_CONSTRAINT_REQUEST 4020
#define OPUS_GET_VBR_CONSTRAINT_REQUEST 4021
#define OPUS_SET_FORCE_CHANNELS_REQUEST 4022
#define OPUS_GET_FORCE_CHANNELS_REQUEST 4023
#define OPUS_SET_SIGNAL_REQUEST 4024
#define OPUS_GET_SIGNAL_REQUEST 4025
#define OPUS_GET_LOOKAHEAD_REQUEST 4027
/* #define OPUS_RESET_STATE 4028 */
#define OPUS_GET_SAMPLE_RATE_REQUEST 4029
#define OPUS_GET_FINAL_RANGE_REQUEST 4031
#define OPUS_GET_PITCH_REQUEST 4033
#define OPUS_SET_GAIN_REQUEST 4034
#define OPUS_GET_GAIN_REQUEST 4045 /* Should have been 4035 */
#define OPUS_SET_LSB_DEPTH_REQUEST 4036
#define OPUS_GET_LSB_DEPTH_REQUEST 4037
#define OPUS_GET_LAST_PACKET_DURATION_REQUEST 4039
#define OPUS_SET_EXPERT_FRAME_DURATION_REQUEST 4040
#define OPUS_GET_EXPERT_FRAME_DURATION_REQUEST 4041
#define OPUS_SET_PREDICTION_DISABLED_REQUEST 4042
#define OPUS_GET_PREDICTION_DISABLED_REQUEST 4043
/* Don't use 4045, it's already taken by OPUS_GET_GAIN_REQUEST */
#define OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST 4046
#define OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST 4047
#define OPUS_GET_IN_DTX_REQUEST 4049
/** Defines for the presence of extended APIs. */
#define OPUS_HAVE_OPUS_PROJECTION_H
/* Macros to trigger compilation errors when the wrong types are provided to a CTL */
#define __opus_check_int(x) (((void)((x) == (opus_int32)0)), (opus_int32)(x))
#define __opus_check_int_ptr(ptr) ((ptr) + ((ptr) - (opus_int32*)(ptr)))
#define __opus_check_uint_ptr(ptr) ((ptr) + ((ptr) - (opus_uint32*)(ptr)))
#define __opus_check_val16_ptr(ptr) ((ptr) + ((ptr) - (opus_val16*)(ptr)))
/** @endcond */
/** @defgroup opus_ctlvalues Pre-defined values for CTL interface
* @see opus_genericctls, opus_encoderctls
* @{
*/
/* Values for the various encoder CTLs */
#define OPUS_AUTO -1000 /**<Auto/default setting @hideinitializer*/
#define OPUS_BITRATE_MAX -1 /**<Maximum bitrate @hideinitializer*/
/** Best for most VoIP/videoconference applications where listening quality and intelligibility matter most
* @hideinitializer */
#define OPUS_APPLICATION_VOIP 2048
/** Best for broadcast/high-fidelity application where the decoded audio should be as close as possible to the input
* @hideinitializer */
#define OPUS_APPLICATION_AUDIO 2049
/** Only use when lowest-achievable latency is what matters most. Voice-optimized modes cannot be used.
* @hideinitializer */
#define OPUS_APPLICATION_RESTRICTED_LOWDELAY 2051
#define OPUS_SIGNAL_VOICE 3001 /**< Signal being encoded is voice */
#define OPUS_SIGNAL_MUSIC 3002 /**< Signal being encoded is music */
#define OPUS_BANDWIDTH_NARROWBAND 1101 /**< 4 kHz bandpass @hideinitializer*/
#define OPUS_BANDWIDTH_MEDIUMBAND 1102 /**< 6 kHz bandpass @hideinitializer*/
#define OPUS_BANDWIDTH_WIDEBAND 1103 /**< 8 kHz bandpass @hideinitializer*/
#define OPUS_BANDWIDTH_SUPERWIDEBAND 1104 /**<12 kHz bandpass @hideinitializer*/
#define OPUS_BANDWIDTH_FULLBAND 1105 /**<20 kHz bandpass @hideinitializer*/
#define OPUS_FRAMESIZE_ARG 5000 /**< Select frame size from the argument (default) */
#define OPUS_FRAMESIZE_2_5_MS 5001 /**< Use 2.5 ms frames */
#define OPUS_FRAMESIZE_5_MS 5002 /**< Use 5 ms frames */
#define OPUS_FRAMESIZE_10_MS 5003 /**< Use 10 ms frames */
#define OPUS_FRAMESIZE_20_MS 5004 /**< Use 20 ms frames */
#define OPUS_FRAMESIZE_40_MS 5005 /**< Use 40 ms frames */
#define OPUS_FRAMESIZE_60_MS 5006 /**< Use 60 ms frames */
#define OPUS_FRAMESIZE_80_MS 5007 /**< Use 80 ms frames */
#define OPUS_FRAMESIZE_100_MS 5008 /**< Use 100 ms frames */
#define OPUS_FRAMESIZE_120_MS 5009 /**< Use 120 ms frames */
/**@}*/
/** @defgroup opus_encoderctls Encoder related CTLs
*
* These are convenience macros for use with the \c opus_encode_ctl
* interface. They are used to generate the appropriate series of
* arguments for that call, passing the correct type, size and so
* on as expected for each particular request.
*
* Some usage examples:
*
* @code
* int ret;
* ret = opus_encoder_ctl(enc_ctx, OPUS_SET_BANDWIDTH(OPUS_AUTO));
* if (ret != OPUS_OK) return ret;
*
* opus_int32 rate;
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&rate));
*
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
* @endcode
*
* @see opus_genericctls, opus_encoder
* @{
*/
/** Configures the encoder's computational complexity.
* The supported range is 0-10 inclusive with 10 representing the highest complexity.
* @see OPUS_GET_COMPLEXITY
* @param[in] x <tt>opus_int32</tt>: Allowed values: 0-10, inclusive.
*
* @hideinitializer */
#define OPUS_SET_COMPLEXITY(x) OPUS_SET_COMPLEXITY_REQUEST, __opus_check_int(x)
/** Gets the encoder's complexity configuration.
* @see OPUS_SET_COMPLEXITY
* @param[out] x <tt>opus_int32 *</tt>: Returns a value in the range 0-10,
* inclusive.
* @hideinitializer */
#define OPUS_GET_COMPLEXITY(x) OPUS_GET_COMPLEXITY_REQUEST, __opus_check_int_ptr(x)
/** Configures the bitrate in the encoder.
* Rates from 500 to 512000 bits per second are meaningful, as well as the
* special values #OPUS_AUTO and #OPUS_BITRATE_MAX.
* The value #OPUS_BITRATE_MAX can be used to cause the codec to use as much
* rate as it can, which is useful for controlling the rate by adjusting the
* output buffer size.
* @see OPUS_GET_BITRATE
* @param[in] x <tt>opus_int32</tt>: Bitrate in bits per second. The default
* is determined based on the number of
* channels and the input sampling rate.
* @hideinitializer */
#define OPUS_SET_BITRATE(x) OPUS_SET_BITRATE_REQUEST, __opus_check_int(x)
/** Gets the encoder's bitrate configuration.
* @see OPUS_SET_BITRATE
* @param[out] x <tt>opus_int32 *</tt>: Returns the bitrate in bits per second.
* The default is determined based on the
* number of channels and the input
* sampling rate.
* @hideinitializer */
#define OPUS_GET_BITRATE(x) OPUS_GET_BITRATE_REQUEST, __opus_check_int_ptr(x)
/** Enables or disables variable bitrate (VBR) in the encoder.
* The configured bitrate may not be met exactly because frames must
* be an integer number of bytes in length.
* @see OPUS_GET_VBR
* @see OPUS_SET_VBR_CONSTRAINT
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Hard CBR. For LPC/hybrid modes at very low bit-rate, this can
* cause noticeable quality degradation.</dd>
* <dt>1</dt><dd>VBR (default). The exact type of VBR is controlled by
* #OPUS_SET_VBR_CONSTRAINT.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_VBR(x) OPUS_SET_VBR_REQUEST, __opus_check_int(x)
/** Determine if variable bitrate (VBR) is enabled in the encoder.
* @see OPUS_SET_VBR
* @see OPUS_GET_VBR_CONSTRAINT
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>Hard CBR.</dd>
* <dt>1</dt><dd>VBR (default). The exact type of VBR may be retrieved via
* #OPUS_GET_VBR_CONSTRAINT.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_VBR(x) OPUS_GET_VBR_REQUEST, __opus_check_int_ptr(x)
/** Enables or disables constrained VBR in the encoder.
* This setting is ignored when the encoder is in CBR mode.
* @warning Only the MDCT mode of Opus currently heeds the constraint.
* Speech mode ignores it completely, hybrid mode may fail to obey it
* if the LPC layer uses more bitrate than the constraint would have
* permitted.
* @see OPUS_GET_VBR_CONSTRAINT
* @see OPUS_SET_VBR
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Unconstrained VBR.</dd>
* <dt>1</dt><dd>Constrained VBR (default). This creates a maximum of one
* frame of buffering delay assuming a transport with a
* serialization speed of the nominal bitrate.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_VBR_CONSTRAINT(x) OPUS_SET_VBR_CONSTRAINT_REQUEST, __opus_check_int(x)
/** Determine if constrained VBR is enabled in the encoder.
* @see OPUS_SET_VBR_CONSTRAINT
* @see OPUS_GET_VBR
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>Unconstrained VBR.</dd>
* <dt>1</dt><dd>Constrained VBR (default).</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_VBR_CONSTRAINT(x) OPUS_GET_VBR_CONSTRAINT_REQUEST, __opus_check_int_ptr(x)
/** Configures mono/stereo forcing in the encoder.
* This can force the encoder to produce packets encoded as either mono or
* stereo, regardless of the format of the input audio. This is useful when
* the caller knows that the input signal is currently a mono source embedded
* in a stereo stream.
* @see OPUS_GET_FORCE_CHANNELS
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
* <dt>1</dt> <dd>Forced mono</dd>
* <dt>2</dt> <dd>Forced stereo</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_FORCE_CHANNELS(x) OPUS_SET_FORCE_CHANNELS_REQUEST, __opus_check_int(x)
/** Gets the encoder's forced channel configuration.
* @see OPUS_SET_FORCE_CHANNELS
* @param[out] x <tt>opus_int32 *</tt>:
* <dl>
* <dt>#OPUS_AUTO</dt><dd>Not forced (default)</dd>
* <dt>1</dt> <dd>Forced mono</dd>
* <dt>2</dt> <dd>Forced stereo</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_FORCE_CHANNELS(x) OPUS_GET_FORCE_CHANNELS_REQUEST, __opus_check_int_ptr(x)
/** Configures the maximum bandpass that the encoder will select automatically.
* Applications should normally use this instead of #OPUS_SET_BANDWIDTH
* (leaving that set to the default, #OPUS_AUTO). This allows the
* application to set an upper bound based on the type of input it is
* providing, but still gives the encoder the freedom to reduce the bandpass
* when the bitrate becomes too low, for better overall quality.
* @see OPUS_GET_MAX_BANDWIDTH
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
* <dt>OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
* <dt>OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
* <dt>OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
* <dt>OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_MAX_BANDWIDTH(x) OPUS_SET_MAX_BANDWIDTH_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured maximum allowed bandpass.
* @see OPUS_SET_MAX_BANDWIDTH
* @param[out] x <tt>opus_int32 *</tt>: Allowed values:
* <dl>
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband (default)</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_MAX_BANDWIDTH(x) OPUS_GET_MAX_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
/** Sets the encoder's bandpass to a specific value.
* This prevents the encoder from automatically selecting the bandpass based
* on the available bitrate. If an application knows the bandpass of the input
* audio it is providing, it should normally use #OPUS_SET_MAX_BANDWIDTH
* instead, which still gives the encoder the freedom to reduce the bandpass
* when the bitrate becomes too low, for better overall quality.
* @see OPUS_GET_BANDWIDTH
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_BANDWIDTH(x) OPUS_SET_BANDWIDTH_REQUEST, __opus_check_int(x)
/** Configures the type of signal being encoded.
* This is a hint which helps the encoder's mode selection.
* @see OPUS_GET_SIGNAL
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_SIGNAL(x) OPUS_SET_SIGNAL_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured signal type.
* @see OPUS_SET_SIGNAL
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
* <dt>#OPUS_SIGNAL_VOICE</dt><dd>Bias thresholds towards choosing LPC or Hybrid modes.</dd>
* <dt>#OPUS_SIGNAL_MUSIC</dt><dd>Bias thresholds towards choosing MDCT modes.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_SIGNAL(x) OPUS_GET_SIGNAL_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's intended application.
* The initial value is a mandatory argument to the encoder_create function.
* @see OPUS_GET_APPLICATION
* @param[in] x <tt>opus_int32</tt>: Returns one of the following values:
* <dl>
* <dt>#OPUS_APPLICATION_VOIP</dt>
* <dd>Process signal for improved speech intelligibility.</dd>
* <dt>#OPUS_APPLICATION_AUDIO</dt>
* <dd>Favor faithfulness to the original input.</dd>
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
* <dd>Configure the minimum possible coding delay by disabling certain modes
* of operation.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_APPLICATION(x) OPUS_SET_APPLICATION_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured application.
* @see OPUS_SET_APPLICATION
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>#OPUS_APPLICATION_VOIP</dt>
* <dd>Process signal for improved speech intelligibility.</dd>
* <dt>#OPUS_APPLICATION_AUDIO</dt>
* <dd>Favor faithfulness to the original input.</dd>
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
* <dd>Configure the minimum possible coding delay by disabling certain modes
* of operation.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_APPLICATION(x) OPUS_GET_APPLICATION_REQUEST, __opus_check_int_ptr(x)
/** Gets the total samples of delay added by the entire codec.
* This can be queried by the encoder and then the provided number of samples can be
* skipped on from the start of the decoder's output to provide time aligned input
* and output. From the perspective of a decoding application the real data begins this many
* samples late.
*
* The decoder contribution to this delay is identical for all decoders, but the
* encoder portion of the delay may vary from implementation to implementation,
* version to version, or even depend on the encoder's initial configuration.
* Applications needing delay compensation should call this CTL rather than
* hard-coding a value.
* @param[out] x <tt>opus_int32 *</tt>: Number of lookahead samples
* @hideinitializer */
#define OPUS_GET_LOOKAHEAD(x) OPUS_GET_LOOKAHEAD_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's use of inband forward error correction (FEC).
* @note This is only applicable to the LPC layer
* @see OPUS_GET_INBAND_FEC
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Disable inband FEC (default).</dd>
* <dt>1</dt><dd>Enable inband FEC.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_INBAND_FEC(x) OPUS_SET_INBAND_FEC_REQUEST, __opus_check_int(x)
/** Gets encoder's configured use of inband forward error correction.
* @see OPUS_SET_INBAND_FEC
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>Inband FEC disabled (default).</dd>
* <dt>1</dt><dd>Inband FEC enabled.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_INBAND_FEC(x) OPUS_GET_INBAND_FEC_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's expected packet loss percentage.
* Higher values trigger progressively more loss resistant behavior in the encoder
* at the expense of quality at a given bitrate in the absence of packet loss, but
* greater quality under loss.
* @see OPUS_GET_PACKET_LOSS_PERC
* @param[in] x <tt>opus_int32</tt>: Loss percentage in the range 0-100, inclusive (default: 0).
* @hideinitializer */
#define OPUS_SET_PACKET_LOSS_PERC(x) OPUS_SET_PACKET_LOSS_PERC_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured packet loss percentage.
* @see OPUS_SET_PACKET_LOSS_PERC
* @param[out] x <tt>opus_int32 *</tt>: Returns the configured loss percentage
* in the range 0-100, inclusive (default: 0).
* @hideinitializer */
#define OPUS_GET_PACKET_LOSS_PERC(x) OPUS_GET_PACKET_LOSS_PERC_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's use of discontinuous transmission (DTX).
* @note This is only applicable to the LPC layer
* @see OPUS_GET_DTX
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Disable DTX (default).</dd>
* <dt>1</dt><dd>Enabled DTX.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_DTX(x) OPUS_SET_DTX_REQUEST, __opus_check_int(x)
/** Gets encoder's configured use of discontinuous transmission.
* @see OPUS_SET_DTX
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>DTX disabled (default).</dd>
* <dt>1</dt><dd>DTX enabled.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_DTX(x) OPUS_GET_DTX_REQUEST, __opus_check_int_ptr(x)
/** Configures the depth of signal being encoded.
*
* This is a hint which helps the encoder identify silence and near-silence.
* It represents the number of significant bits of linear intensity below
* which the signal contains ignorable quantization or other noise.
*
* For example, OPUS_SET_LSB_DEPTH(14) would be an appropriate setting
* for G.711 u-law input. OPUS_SET_LSB_DEPTH(16) would be appropriate
* for 16-bit linear pcm input with opus_encode_float().
*
* When using opus_encode() instead of opus_encode_float(), or when libopus
* is compiled for fixed-point, the encoder uses the minimum of the value
* set here and the value 16.
*
* @see OPUS_GET_LSB_DEPTH
* @param[in] x <tt>opus_int32</tt>: Input precision in bits, between 8 and 24
* (default: 24).
* @hideinitializer */
#define OPUS_SET_LSB_DEPTH(x) OPUS_SET_LSB_DEPTH_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured signal depth.
* @see OPUS_SET_LSB_DEPTH
* @param[out] x <tt>opus_int32 *</tt>: Input precision in bits, between 8 and
* 24 (default: 24).
* @hideinitializer */
#define OPUS_GET_LSB_DEPTH(x) OPUS_GET_LSB_DEPTH_REQUEST, __opus_check_int_ptr(x)
/** Configures the encoder's use of variable duration frames.
* When variable duration is enabled, the encoder is free to use a shorter frame
* size than the one requested in the opus_encode*() call.
* It is then the user's responsibility
* to verify how much audio was encoded by checking the ToC byte of the encoded
* packet. The part of the audio that was not encoded needs to be resent to the
* encoder for the next call. Do not use this option unless you <b>really</b>
* know what you are doing.
* @see OPUS_GET_EXPERT_FRAME_DURATION
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_EXPERT_FRAME_DURATION(x) OPUS_SET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured use of variable duration frames.
* @see OPUS_SET_EXPERT_FRAME_DURATION
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>OPUS_FRAMESIZE_ARG</dt><dd>Select frame size from the argument (default).</dd>
* <dt>OPUS_FRAMESIZE_2_5_MS</dt><dd>Use 2.5 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_5_MS</dt><dd>Use 5 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_10_MS</dt><dd>Use 10 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_20_MS</dt><dd>Use 20 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_40_MS</dt><dd>Use 40 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_60_MS</dt><dd>Use 60 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_80_MS</dt><dd>Use 80 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_100_MS</dt><dd>Use 100 ms frames.</dd>
* <dt>OPUS_FRAMESIZE_120_MS</dt><dd>Use 120 ms frames.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_EXPERT_FRAME_DURATION(x) OPUS_GET_EXPERT_FRAME_DURATION_REQUEST, __opus_check_int_ptr(x)
/** If set to 1, disables almost all use of prediction, making frames almost
* completely independent. This reduces quality.
* @see OPUS_GET_PREDICTION_DISABLED
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Enable prediction (default).</dd>
* <dt>1</dt><dd>Disable prediction.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_PREDICTION_DISABLED(x) OPUS_SET_PREDICTION_DISABLED_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured prediction status.
* @see OPUS_SET_PREDICTION_DISABLED
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>Prediction enabled (default).</dd>
* <dt>1</dt><dd>Prediction disabled.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_PREDICTION_DISABLED(x) OPUS_GET_PREDICTION_DISABLED_REQUEST, __opus_check_int_ptr(x)
/**@}*/
/** @defgroup opus_genericctls Generic CTLs
*
* These macros are used with the \c opus_decoder_ctl and
* \c opus_encoder_ctl calls to generate a particular
* request.
*
* When called on an \c OpusDecoder they apply to that
* particular decoder instance. When called on an
* \c OpusEncoder they apply to the corresponding setting
* on that encoder instance, if present.
*
* Some usage examples:
*
* @code
* int ret;
* opus_int32 pitch;
* ret = opus_decoder_ctl(dec_ctx, OPUS_GET_PITCH(&pitch));
* if (ret == OPUS_OK) return ret;
*
* opus_encoder_ctl(enc_ctx, OPUS_RESET_STATE);
* opus_decoder_ctl(dec_ctx, OPUS_RESET_STATE);
*
* opus_int32 enc_bw, dec_bw;
* opus_encoder_ctl(enc_ctx, OPUS_GET_BANDWIDTH(&enc_bw));
* opus_decoder_ctl(dec_ctx, OPUS_GET_BANDWIDTH(&dec_bw));
* if (enc_bw != dec_bw) {
* printf("packet bandwidth mismatch!\n");
* }
* @endcode
*
* @see opus_encoder, opus_decoder_ctl, opus_encoder_ctl, opus_decoderctls, opus_encoderctls
* @{
*/
/** Resets the codec state to be equivalent to a freshly initialized state.
* This should be called when switching streams in order to prevent
* the back to back decoding from giving different results from
* one at a time decoding.
* @hideinitializer */
#define OPUS_RESET_STATE 4028
/** Gets the final state of the codec's entropy coder.
* This is used for testing purposes,
* The encoder and decoder state should be identical after coding a payload
* (assuming no data corruption or software bugs)
*
* @param[out] x <tt>opus_uint32 *</tt>: Entropy coder state
*
* @hideinitializer */
#define OPUS_GET_FINAL_RANGE(x) OPUS_GET_FINAL_RANGE_REQUEST, __opus_check_uint_ptr(x)
/** Gets the encoder's configured bandpass or the decoder's last bandpass.
* @see OPUS_SET_BANDWIDTH
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>#OPUS_AUTO</dt> <dd>(default)</dd>
* <dt>#OPUS_BANDWIDTH_NARROWBAND</dt> <dd>4 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_MEDIUMBAND</dt> <dd>6 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_WIDEBAND</dt> <dd>8 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_SUPERWIDEBAND</dt><dd>12 kHz passband</dd>
* <dt>#OPUS_BANDWIDTH_FULLBAND</dt> <dd>20 kHz passband</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_BANDWIDTH(x) OPUS_GET_BANDWIDTH_REQUEST, __opus_check_int_ptr(x)
/** Gets the sampling rate the encoder or decoder was initialized with.
* This simply returns the <code>Fs</code> value passed to opus_encoder_init()
* or opus_decoder_init().
* @param[out] x <tt>opus_int32 *</tt>: Sampling rate of encoder or decoder.
* @hideinitializer
*/
#define OPUS_GET_SAMPLE_RATE(x) OPUS_GET_SAMPLE_RATE_REQUEST, __opus_check_int_ptr(x)
/** If set to 1, disables the use of phase inversion for intensity stereo,
* improving the quality of mono downmixes, but slightly reducing normal
* stereo quality. Disabling phase inversion in the decoder does not comply
* with RFC 6716, although it does not cause any interoperability issue and
* is expected to become part of the Opus standard once RFC 6716 is updated
* by draft-ietf-codec-opus-update.
* @see OPUS_GET_PHASE_INVERSION_DISABLED
* @param[in] x <tt>opus_int32</tt>: Allowed values:
* <dl>
* <dt>0</dt><dd>Enable phase inversion (default).</dd>
* <dt>1</dt><dd>Disable phase inversion.</dd>
* </dl>
* @hideinitializer */
#define OPUS_SET_PHASE_INVERSION_DISABLED(x) OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured phase inversion status.
* @see OPUS_SET_PHASE_INVERSION_DISABLED
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>Stereo phase inversion enabled (default).</dd>
* <dt>1</dt><dd>Stereo phase inversion disabled.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_PHASE_INVERSION_DISABLED(x) OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST, __opus_check_int_ptr(x)
/** Gets the DTX state of the encoder.
* Returns whether the last encoded frame was either a comfort noise update
* during DTX or not encoded because of DTX.
* @param[out] x <tt>opus_int32 *</tt>: Returns one of the following values:
* <dl>
* <dt>0</dt><dd>The encoder is not in DTX.</dd>
* <dt>1</dt><dd>The encoder is in DTX.</dd>
* </dl>
* @hideinitializer */
#define OPUS_GET_IN_DTX(x) OPUS_GET_IN_DTX_REQUEST, __opus_check_int_ptr(x)
/**@}*/
/** @defgroup opus_decoderctls Decoder related CTLs
* @see opus_genericctls, opus_encoderctls, opus_decoder
* @{
*/
/** Configures decoder gain adjustment.
* Scales the decoded output by a factor specified in Q8 dB units.
* This has a maximum range of -32768 to 32767 inclusive, and returns
* OPUS_BAD_ARG otherwise. The default is zero indicating no adjustment.
* This setting survives decoder reset.
*
* gain = pow(10, x/(20.0*256))
*
* @param[in] x <tt>opus_int32</tt>: Amount to scale PCM signal by in Q8 dB units.
* @hideinitializer */
#define OPUS_SET_GAIN(x) OPUS_SET_GAIN_REQUEST, __opus_check_int(x)
/** Gets the decoder's configured gain adjustment. @see OPUS_SET_GAIN
*
* @param[out] x <tt>opus_int32 *</tt>: Amount to scale PCM signal by in Q8 dB units.
* @hideinitializer */
#define OPUS_GET_GAIN(x) OPUS_GET_GAIN_REQUEST, __opus_check_int_ptr(x)
/** Gets the duration (in samples) of the last packet successfully decoded or concealed.
* @param[out] x <tt>opus_int32 *</tt>: Number of samples (at current sampling rate).
* @hideinitializer */
#define OPUS_GET_LAST_PACKET_DURATION(x) OPUS_GET_LAST_PACKET_DURATION_REQUEST, __opus_check_int_ptr(x)
/** Gets the pitch of the last decoded frame, if available.
* This can be used for any post-processing algorithm requiring the use of pitch,
* e.g. time stretching/shortening. If the last frame was not voiced, or if the
* pitch was not coded in the frame, then zero is returned.
*
* This CTL is only implemented for decoder instances.
*
* @param[out] x <tt>opus_int32 *</tt>: pitch period at 48 kHz (or 0 if not available)
*
* @hideinitializer */
#define OPUS_GET_PITCH(x) OPUS_GET_PITCH_REQUEST, __opus_check_int_ptr(x)
/**@}*/
/** @defgroup opus_libinfo Opus library information functions
* @{
*/
/** Converts an opus error code into a human readable string.
*
* @param[in] error <tt>int</tt>: Error number
* @returns Error string
*/
OPUS_EXPORT const char *opus_strerror(int error);
/** Gets the libopus version string.
*
* Applications may look for the substring "-fixed" in the version string to
* determine whether they have a fixed-point or floating-point build at
* runtime.
*
* @returns Version string
*/
OPUS_EXPORT const char *opus_get_version_string(void);
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_DEFINES_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,92 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "opus_multistream.h"
#include "opus.h"
#include "opus_private.h"
#include "celt/stack_alloc.h"
#include <stdarg.h>
#include "celt/float_cast.h"
#include "celt/os_support.h"
int validate_layout(const ChannelLayout *layout)
{
int i, max_channel;
max_channel = layout->nb_streams+layout->nb_coupled_streams;
if (max_channel>255)
return 0;
for (i=0;i<layout->nb_channels;i++)
{
if (layout->mapping[i] >= max_channel && layout->mapping[i] != 255)
return 0;
}
return 1;
}
int get_left_channel(const ChannelLayout *layout, int stream_id, int prev)
{
int i;
i = (prev<0) ? 0 : prev+1;
for (;i<layout->nb_channels;i++)
{
if (layout->mapping[i]==stream_id*2)
return i;
}
return -1;
}
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev)
{
int i;
i = (prev<0) ? 0 : prev+1;
for (;i<layout->nb_channels;i++)
{
if (layout->mapping[i]==stream_id*2+1)
return i;
}
return -1;
}
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev)
{
int i;
i = (prev<0) ? 0 : prev+1;
for (;i<layout->nb_channels;i++)
{
if (layout->mapping[i]==stream_id+layout->nb_coupled_streams)
return i;
}
return -1;
}

View File

@@ -0,0 +1,660 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/**
* @file opus_multistream.h
* @brief Opus reference implementation multistream API
*/
#ifndef OPUS_MULTISTREAM_H
#define OPUS_MULTISTREAM_H
#include "opus.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @cond OPUS_INTERNAL_DOC */
/** Macros to trigger compilation errors when the wrong types are provided to a
* CTL. */
/**@{*/
#define __opus_check_encstate_ptr(ptr) ((ptr) + ((ptr) - (OpusEncoder**)(ptr)))
#define __opus_check_decstate_ptr(ptr) ((ptr) + ((ptr) - (OpusDecoder**)(ptr)))
/**@}*/
/** These are the actual encoder and decoder CTL ID numbers.
* They should not be used directly by applications.
* In general, SETs should be even and GETs should be odd.*/
/**@{*/
#define OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST 5120
#define OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST 5122
/**@}*/
/** @endcond */
/** @defgroup opus_multistream_ctls Multistream specific encoder and decoder CTLs
*
* These are convenience macros that are specific to the
* opus_multistream_encoder_ctl() and opus_multistream_decoder_ctl()
* interface.
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls, and
* @ref opus_decoderctls may be applied to a multistream encoder or decoder as
* well.
* In addition, you may retrieve the encoder or decoder state for an specific
* stream via #OPUS_MULTISTREAM_GET_ENCODER_STATE or
* #OPUS_MULTISTREAM_GET_DECODER_STATE and apply CTLs to it individually.
*/
/**@{*/
/** Gets the encoder state for an individual stream of a multistream encoder.
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose encoder you
* wish to retrieve.
* This must be non-negative and less than
* the <code>streams</code> parameter used
* to initialize the encoder.
* @param[out] y <tt>OpusEncoder**</tt>: Returns a pointer to the given
* encoder state.
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
* @hideinitializer
*/
#define OPUS_MULTISTREAM_GET_ENCODER_STATE(x,y) OPUS_MULTISTREAM_GET_ENCODER_STATE_REQUEST, __opus_check_int(x), __opus_check_encstate_ptr(y)
/** Gets the decoder state for an individual stream of a multistream decoder.
* @param[in] x <tt>opus_int32</tt>: The index of the stream whose decoder you
* wish to retrieve.
* This must be non-negative and less than
* the <code>streams</code> parameter used
* to initialize the decoder.
* @param[out] y <tt>OpusDecoder**</tt>: Returns a pointer to the given
* decoder state.
* @retval OPUS_BAD_ARG The index of the requested stream was out of range.
* @hideinitializer
*/
#define OPUS_MULTISTREAM_GET_DECODER_STATE(x,y) OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST, __opus_check_int(x), __opus_check_decstate_ptr(y)
/**@}*/
/** @defgroup opus_multistream Opus Multistream API
* @{
*
* The multistream API allows individual Opus streams to be combined into a
* single packet, enabling support for up to 255 channels. Unlike an
* elementary Opus stream, the encoder and decoder must negotiate the channel
* configuration before the decoder can successfully interpret the data in the
* packets produced by the encoder. Some basic information, such as packet
* duration, can be computed without any special negotiation.
*
* The format for multistream Opus packets is defined in
* <a href="https://tools.ietf.org/html/rfc7845">RFC 7845</a>
* and is based on the self-delimited Opus framing described in Appendix B of
* <a href="https://tools.ietf.org/html/rfc6716">RFC 6716</a>.
* Normal Opus packets are just a degenerate case of multistream Opus packets,
* and can be encoded or decoded with the multistream API by setting
* <code>streams</code> to <code>1</code> when initializing the encoder or
* decoder.
*
* Multistream Opus streams can contain up to 255 elementary Opus streams.
* These may be either "uncoupled" or "coupled", indicating that the decoder
* is configured to decode them to either 1 or 2 channels, respectively.
* The streams are ordered so that all coupled streams appear at the
* beginning.
*
* A <code>mapping</code> table defines which decoded channel <code>i</code>
* should be used for each input/output (I/O) channel <code>j</code>. This table is
* typically provided as an unsigned char array.
* Let <code>i = mapping[j]</code> be the index for I/O channel <code>j</code>.
* If <code>i < 2*coupled_streams</code>, then I/O channel <code>j</code> is
* encoded as the left channel of stream <code>(i/2)</code> if <code>i</code>
* is even, or as the right channel of stream <code>(i/2)</code> if
* <code>i</code> is odd. Otherwise, I/O channel <code>j</code> is encoded as
* mono in stream <code>(i - coupled_streams)</code>, unless it has the special
* value 255, in which case it is omitted from the encoding entirely (the
* decoder will reproduce it as silence). Each value <code>i</code> must either
* be the special value 255 or be less than <code>streams + coupled_streams</code>.
*
* The output channels specified by the encoder
* should use the
* <a href="https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-810004.3.9">Vorbis
* channel ordering</a>. A decoder may wish to apply an additional permutation
* to the mapping the encoder used to achieve a different output channel
* order (e.g. for outputing in WAV order).
*
* Each multistream packet contains an Opus packet for each stream, and all of
* the Opus packets in a single multistream packet must have the same
* duration. Therefore the duration of a multistream packet can be extracted
* from the TOC sequence of the first stream, which is located at the
* beginning of the packet, just like an elementary Opus stream:
*
* @code
* int nb_samples;
* int nb_frames;
* nb_frames = opus_packet_get_nb_frames(data, len);
* if (nb_frames < 1)
* return nb_frames;
* nb_samples = opus_packet_get_samples_per_frame(data, 48000) * nb_frames;
* @endcode
*
* The general encoding and decoding process proceeds exactly the same as in
* the normal @ref opus_encoder and @ref opus_decoder APIs.
* See their documentation for an overview of how to use the corresponding
* multistream functions.
*/
/** Opus multistream encoder state.
* This contains the complete state of a multistream Opus encoder.
* It is position independent and can be freely copied.
* @see opus_multistream_encoder_create
* @see opus_multistream_encoder_init
*/
typedef struct OpusMSEncoder OpusMSEncoder;
/** Opus multistream decoder state.
* This contains the complete state of a multistream Opus decoder.
* It is position independent and can be freely copied.
* @see opus_multistream_decoder_create
* @see opus_multistream_decoder_init
*/
typedef struct OpusMSDecoder OpusMSDecoder;
/**\name Multistream encoder functions */
/**@{*/
/** Gets the size of an OpusMSEncoder structure.
* @param streams <tt>int</tt>: The total number of streams to encode from the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
* to encode.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* encoded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @returns The size in bytes on success, or a negative error code
* (see @ref opus_errorcodes) on error.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_encoder_get_size(
int streams,
int coupled_streams
);
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_surround_encoder_get_size(
int channels,
int mapping_family
);
/** Allocates and initializes a multistream encoder state.
* Call opus_multistream_encoder_destroy() to release
* this object when finished.
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels in the input signal.
* This must be at most 255.
* It may be greater than the number of
* coded channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams to encode from the
* input.
* This must be no more than the number of channels.
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
* to encode.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* encoded channels (<code>streams +
* coupled_streams</code>) must be no
* more than the number of input channels.
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
* encoded channels to input channels, as described in
* @ref opus_multistream. As an extra constraint, the
* multistream encoder does not allow encoding coupled
* streams for which one channel is unused since this
* is never a good idea.
* @param application <tt>int</tt>: The target encoder application.
* This must be one of the following:
* <dl>
* <dt>#OPUS_APPLICATION_VOIP</dt>
* <dd>Process signal for improved speech intelligibility.</dd>
* <dt>#OPUS_APPLICATION_AUDIO</dt>
* <dd>Favor faithfulness to the original input.</dd>
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
* <dd>Configure the minimum possible coding delay by disabling certain modes
* of operation.</dd>
* </dl>
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
* code (see @ref opus_errorcodes) on
* failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_encoder_create(
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping,
int application,
int *error
) OPUS_ARG_NONNULL(5);
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSEncoder *opus_multistream_surround_encoder_create(
opus_int32 Fs,
int channels,
int mapping_family,
int *streams,
int *coupled_streams,
unsigned char *mapping,
int application,
int *error
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
/** Initialize a previously allocated multistream encoder state.
* The memory pointed to by \a st must be at least the size returned by
* opus_multistream_encoder_get_size().
* This is intended for applications which use their own allocator instead of
* malloc.
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
* @see opus_multistream_encoder_create
* @see opus_multistream_encoder_get_size
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels in the input signal.
* This must be at most 255.
* It may be greater than the number of
* coded channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams to encode from the
* input.
* This must be no more than the number of channels.
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
* to encode.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* encoded channels (<code>streams +
* coupled_streams</code>) must be no
* more than the number of input channels.
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
* encoded channels to input channels, as described in
* @ref opus_multistream. As an extra constraint, the
* multistream encoder does not allow encoding coupled
* streams for which one channel is unused since this
* is never a good idea.
* @param application <tt>int</tt>: The target encoder application.
* This must be one of the following:
* <dl>
* <dt>#OPUS_APPLICATION_VOIP</dt>
* <dd>Process signal for improved speech intelligibility.</dd>
* <dt>#OPUS_APPLICATION_AUDIO</dt>
* <dd>Favor faithfulness to the original input.</dd>
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
* <dd>Configure the minimum possible coding delay by disabling certain modes
* of operation.</dd>
* </dl>
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
* on failure.
*/
OPUS_EXPORT int opus_multistream_encoder_init(
OpusMSEncoder *st,
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping,
int application
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
OPUS_EXPORT int opus_multistream_surround_encoder_init(
OpusMSEncoder *st,
opus_int32 Fs,
int channels,
int mapping_family,
int *streams,
int *coupled_streams,
unsigned char *mapping,
int application
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6) OPUS_ARG_NONNULL(7);
/** Encodes a multistream Opus frame.
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
* @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
* samples.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode(
OpusMSEncoder *st,
const opus_int16 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a multistream Opus frame from floating point input.
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
* samples with a normal range of
* +/-1.0.
* Samples with a range beyond +/-1.0
* are supported but will be clipped by
* decoders using the integer API and
* should only be used if it is known
* that the far end supports extended
* dynamic range.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_encode_float(
OpusMSEncoder *st,
const float *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Frees an <code>OpusMSEncoder</code> allocated by
* opus_multistream_encoder_create().
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to be freed.
*/
OPUS_EXPORT void opus_multistream_encoder_destroy(OpusMSEncoder *st);
/** Perform a CTL function on a multistream Opus encoder.
*
* Generally the request and subsequent arguments are generated by a
* convenience macro.
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls,
* @ref opus_encoderctls, or @ref opus_multistream_ctls.
* @see opus_genericctls
* @see opus_encoderctls
* @see opus_multistream_ctls
*/
OPUS_EXPORT int opus_multistream_encoder_ctl(OpusMSEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
/**\name Multistream decoder functions */
/**@{*/
/** Gets the size of an <code>OpusMSDecoder</code> structure.
* @param streams <tt>int</tt>: The total number of streams coded in the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
* (2 channel) streams.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* coded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @returns The size in bytes on success, or a negative error code
* (see @ref opus_errorcodes) on error.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_multistream_decoder_get_size(
int streams,
int coupled_streams
);
/** Allocates and initializes a multistream decoder state.
* Call opus_multistream_decoder_destroy() to release
* this object when finished.
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels to output.
* This must be at most 255.
* It may be different from the number of coded
* channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams coded in the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
* (2 channel) streams.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* coded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
* coded channels to output channels, as described in
* @ref opus_multistream.
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
* code (see @ref opus_errorcodes) on
* failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusMSDecoder *opus_multistream_decoder_create(
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping,
int *error
) OPUS_ARG_NONNULL(5);
/** Intialize a previously allocated decoder state object.
* The memory pointed to by \a st must be at least the size returned by
* opus_multistream_encoder_get_size().
* This is intended for applications which use their own allocator instead of
* malloc.
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
* @see opus_multistream_decoder_create
* @see opus_multistream_deocder_get_size
* @param st <tt>OpusMSEncoder*</tt>: Multistream encoder state to initialize.
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels to output.
* This must be at most 255.
* It may be different from the number of coded
* channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams coded in the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
* (2 channel) streams.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* coded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @param[in] mapping <code>const unsigned char[channels]</code>: Mapping from
* coded channels to output channels, as described in
* @ref opus_multistream.
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
* on failure.
*/
OPUS_EXPORT int opus_multistream_decoder_init(
OpusMSDecoder *st,
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
/** Decode a multistream Opus packet.
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
* samples.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int16 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a multistream Opus packet with floating point output.
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
* samples.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_multistream_decode_float(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
float *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on a multistream Opus decoder.
*
* Generally the request and subsequent arguments are generated by a
* convenience macro.
* @param st <tt>OpusMSDecoder*</tt>: Multistream decoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls,
* @ref opus_decoderctls, or @ref opus_multistream_ctls.
* @see opus_genericctls
* @see opus_decoderctls
* @see opus_multistream_ctls
*/
OPUS_EXPORT int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
/** Frees an <code>OpusMSDecoder</code> allocated by
* opus_multistream_decoder_create().
* @param st <tt>OpusMSDecoder</tt>: Multistream decoder state to be freed.
*/
OPUS_EXPORT void opus_multistream_decoder_destroy(OpusMSDecoder *st);
/**@}*/
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_MULTISTREAM_H */

View File

@@ -0,0 +1,549 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "opus_multistream.h"
#include "opus.h"
#include "opus_private.h"
#include "celt/stack_alloc.h"
#include <stdarg.h>
#include "celt/float_cast.h"
#include "celt/os_support.h"
/* DECODER */
#if defined(ENABLE_HARDENING) || defined(ENABLE_ASSERTIONS)
static void validate_ms_decoder(OpusMSDecoder *st)
{
validate_layout(&st->layout);
}
#define VALIDATE_MS_DECODER(st) validate_ms_decoder(st)
#else
#define VALIDATE_MS_DECODER(st)
#endif
opus_int32 opus_multistream_decoder_get_size(int nb_streams, int nb_coupled_streams)
{
int coupled_size;
int mono_size;
if(nb_streams<1||nb_coupled_streams>nb_streams||nb_coupled_streams<0)return 0;
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
return align(sizeof(OpusMSDecoder))
+ nb_coupled_streams * align(coupled_size)
+ (nb_streams-nb_coupled_streams) * align(mono_size);
}
int opus_multistream_decoder_init(
OpusMSDecoder *st,
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping
)
{
int coupled_size;
int mono_size;
int i, ret;
char *ptr;
if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
(streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
return OPUS_BAD_ARG;
st->layout.nb_channels = channels;
st->layout.nb_streams = streams;
st->layout.nb_coupled_streams = coupled_streams;
for (i=0;i<st->layout.nb_channels;i++)
st->layout.mapping[i] = mapping[i];
if (!validate_layout(&st->layout))
return OPUS_BAD_ARG;
ptr = (char*)st + align(sizeof(OpusMSDecoder));
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
for (i=0;i<st->layout.nb_coupled_streams;i++)
{
ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 2);
if(ret!=OPUS_OK)return ret;
ptr += align(coupled_size);
}
for (;i<st->layout.nb_streams;i++)
{
ret=opus_decoder_init((OpusDecoder*)ptr, Fs, 1);
if(ret!=OPUS_OK)return ret;
ptr += align(mono_size);
}
return OPUS_OK;
}
OpusMSDecoder *opus_multistream_decoder_create(
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
const unsigned char *mapping,
int *error
)
{
int ret;
OpusMSDecoder *st;
if ((channels>255) || (channels<1) || (coupled_streams>streams) ||
(streams<1) || (coupled_streams<0) || (streams>255-coupled_streams))
{
if (error)
*error = OPUS_BAD_ARG;
return NULL;
}
st = (OpusMSDecoder *)opus_alloc(opus_multistream_decoder_get_size(streams, coupled_streams));
if (st==NULL)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
ret = opus_multistream_decoder_init(st, Fs, channels, streams, coupled_streams, mapping);
if (error)
*error = ret;
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
return st;
}
static int opus_multistream_packet_validate(const unsigned char *data,
opus_int32 len, int nb_streams, opus_int32 Fs)
{
int s;
int count;
unsigned char toc;
opus_int16 size[48];
int samples=0;
opus_int32 packet_offset;
for (s=0;s<nb_streams;s++)
{
int tmp_samples;
if (len<=0)
return OPUS_INVALID_PACKET;
count = opus_packet_parse_impl(data, len, s!=nb_streams-1, &toc, NULL,
size, NULL, &packet_offset);
if (count<0)
return count;
tmp_samples = opus_packet_get_nb_samples(data, packet_offset, Fs);
if (s!=0 && samples != tmp_samples)
return OPUS_INVALID_PACKET;
samples = tmp_samples;
data += packet_offset;
len -= packet_offset;
}
return samples;
}
int opus_multistream_decode_native(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
void *pcm,
opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec,
int soft_clip,
void *user_data
)
{
opus_int32 Fs;
int coupled_size;
int mono_size;
int s, c;
char *ptr;
int do_plc=0;
VARDECL(opus_val16, buf);
ALLOC_STACK;
VALIDATE_MS_DECODER(st);
if (frame_size <= 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
/* Limit frame_size to avoid excessive stack allocations. */
MUST_SUCCEED(opus_multistream_decoder_ctl(st, OPUS_GET_SAMPLE_RATE(&Fs)));
frame_size = IMIN(frame_size, Fs/25*3);
ALLOC(buf, 2*frame_size, opus_val16);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
if (len==0)
do_plc = 1;
if (len < 0)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
if (!do_plc && len < 2*st->layout.nb_streams-1)
{
RESTORE_STACK;
return OPUS_INVALID_PACKET;
}
if (!do_plc)
{
int ret = opus_multistream_packet_validate(data, len, st->layout.nb_streams, Fs);
if (ret < 0)
{
RESTORE_STACK;
return ret;
} else if (ret > frame_size)
{
RESTORE_STACK;
return OPUS_BUFFER_TOO_SMALL;
}
}
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
opus_int32 packet_offset;
int ret;
dec = (OpusDecoder*)ptr;
ptr += (s < st->layout.nb_coupled_streams) ? align(coupled_size) : align(mono_size);
if (!do_plc && len<=0)
{
RESTORE_STACK;
return OPUS_INTERNAL_ERROR;
}
packet_offset = 0;
ret = opus_decode_native(dec, data, len, buf, frame_size, decode_fec, s!=st->layout.nb_streams-1, &packet_offset, soft_clip);
data += packet_offset;
len -= packet_offset;
if (ret <= 0)
{
RESTORE_STACK;
return ret;
}
frame_size = ret;
if (s < st->layout.nb_coupled_streams)
{
int chan, prev;
prev = -1;
/* Copy "left" audio to the channel(s) where it belongs */
while ( (chan = get_left_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
buf, 2, frame_size, user_data);
prev = chan;
}
prev = -1;
/* Copy "right" audio to the channel(s) where it belongs */
while ( (chan = get_right_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
buf+1, 2, frame_size, user_data);
prev = chan;
}
} else {
int chan, prev;
prev = -1;
/* Copy audio to the channel(s) where it belongs */
while ( (chan = get_mono_channel(&st->layout, s, prev)) != -1)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, chan,
buf, 1, frame_size, user_data);
prev = chan;
}
}
}
/* Handle muted channels */
for (c=0;c<st->layout.nb_channels;c++)
{
if (st->layout.mapping[c] == 255)
{
(*copy_channel_out)(pcm, st->layout.nb_channels, c,
NULL, 0, frame_size, user_data);
}
}
RESTORE_STACK;
return frame_size;
}
#if !defined(DISABLE_FLOAT_API)
static void opus_copy_channel_out_float(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size,
void *user_data
)
{
float *float_dst;
opus_int32 i;
(void)user_data;
float_dst = (float*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
float_dst[i*dst_stride+dst_channel] = (1/32768.f)*src[i*src_stride];
#else
float_dst[i*dst_stride+dst_channel] = src[i*src_stride];
#endif
}
else
{
for (i=0;i<frame_size;i++)
float_dst[i*dst_stride+dst_channel] = 0;
}
}
#endif
static void opus_copy_channel_out_short(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size,
void *user_data
)
{
opus_int16 *short_dst;
opus_int32 i;
(void)user_data;
short_dst = (opus_int16*)dst;
if (src != NULL)
{
for (i=0;i<frame_size;i++)
#if defined(FIXED_POINT)
short_dst[i*dst_stride+dst_channel] = src[i*src_stride];
#else
short_dst[i*dst_stride+dst_channel] = FLOAT2INT16(src[i*src_stride]);
#endif
}
else
{
for (i=0;i<frame_size;i++)
short_dst[i*dst_stride+dst_channel] = 0;
}
}
#ifdef FIXED_POINT
int opus_multistream_decode(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int16 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_short, frame_size, decode_fec, 0, NULL);
}
#ifndef DISABLE_FLOAT_API
int opus_multistream_decode_float(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
#else
int opus_multistream_decode(OpusMSDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_short, frame_size, decode_fec, 1, NULL);
}
int opus_multistream_decode_float(
OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_val16 *pcm,
int frame_size,
int decode_fec
)
{
return opus_multistream_decode_native(st, data, len,
pcm, opus_copy_channel_out_float, frame_size, decode_fec, 0, NULL);
}
#endif
int opus_multistream_decoder_ctl_va_list(OpusMSDecoder *st, int request,
va_list ap)
{
int coupled_size, mono_size;
char *ptr;
int ret = OPUS_OK;
coupled_size = opus_decoder_get_size(2);
mono_size = opus_decoder_get_size(1);
ptr = (char*)st + align(sizeof(OpusMSDecoder));
switch (request)
{
case OPUS_GET_BANDWIDTH_REQUEST:
case OPUS_GET_SAMPLE_RATE_REQUEST:
case OPUS_GET_GAIN_REQUEST:
case OPUS_GET_LAST_PACKET_DURATION_REQUEST:
case OPUS_GET_PHASE_INVERSION_DISABLED_REQUEST:
{
OpusDecoder *dec;
/* For int32* GET params, just query the first stream */
opus_int32 *value = va_arg(ap, opus_int32*);
dec = (OpusDecoder*)ptr;
ret = opus_decoder_ctl(dec, request, value);
}
break;
case OPUS_GET_FINAL_RANGE_REQUEST:
{
int s;
opus_uint32 *value = va_arg(ap, opus_uint32*);
opus_uint32 tmp;
if (!value)
{
goto bad_arg;
}
*value = 0;
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
dec = (OpusDecoder*)ptr;
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
ret = opus_decoder_ctl(dec, request, &tmp);
if (ret != OPUS_OK) break;
*value ^= tmp;
}
}
break;
case OPUS_RESET_STATE:
{
int s;
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
dec = (OpusDecoder*)ptr;
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
ret = opus_decoder_ctl(dec, OPUS_RESET_STATE);
if (ret != OPUS_OK)
break;
}
}
break;
case OPUS_MULTISTREAM_GET_DECODER_STATE_REQUEST:
{
int s;
opus_int32 stream_id;
OpusDecoder **value;
stream_id = va_arg(ap, opus_int32);
if (stream_id<0 || stream_id >= st->layout.nb_streams)
goto bad_arg;
value = va_arg(ap, OpusDecoder**);
if (!value)
{
goto bad_arg;
}
for (s=0;s<stream_id;s++)
{
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
}
*value = (OpusDecoder*)ptr;
}
break;
case OPUS_SET_GAIN_REQUEST:
case OPUS_SET_PHASE_INVERSION_DISABLED_REQUEST:
{
int s;
/* This works for int32 params */
opus_int32 value = va_arg(ap, opus_int32);
for (s=0;s<st->layout.nb_streams;s++)
{
OpusDecoder *dec;
dec = (OpusDecoder*)ptr;
if (s < st->layout.nb_coupled_streams)
ptr += align(coupled_size);
else
ptr += align(mono_size);
ret = opus_decoder_ctl(dec, request, value);
if (ret != OPUS_OK)
break;
}
}
break;
default:
ret = OPUS_UNIMPLEMENTED;
break;
}
return ret;
bad_arg:
return OPUS_BAD_ARG;
}
int opus_multistream_decoder_ctl(OpusMSDecoder *st, int request, ...)
{
int ret;
va_list ap;
va_start(ap, request);
ret = opus_multistream_decoder_ctl_va_list(st, request, ap);
va_end(ap);
return ret;
}
void opus_multistream_decoder_destroy(OpusMSDecoder *st)
{
opus_free(st);
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,201 @@
/* Copyright (c) 2012 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
#ifndef OPUS_PRIVATE_H
#define OPUS_PRIVATE_H
#include "celt/arch.h"
#include "opus.h"
#include "celt/celt.h"
#include <stdarg.h> /* va_list */
#include <stddef.h> /* offsetof */
struct OpusRepacketizer {
unsigned char toc;
int nb_frames;
const unsigned char *frames[48];
opus_int16 len[48];
int framesize;
};
typedef struct ChannelLayout {
int nb_channels;
int nb_streams;
int nb_coupled_streams;
unsigned char mapping[256];
} ChannelLayout;
typedef enum {
MAPPING_TYPE_NONE,
MAPPING_TYPE_SURROUND,
MAPPING_TYPE_AMBISONICS
} MappingType;
struct OpusMSEncoder {
ChannelLayout layout;
int arch;
int lfe_stream;
int application;
int variable_duration;
MappingType mapping_type;
opus_int32 bitrate_bps;
/* Encoder states go here */
/* then opus_val32 window_mem[channels*120]; */
/* then opus_val32 preemph_mem[channels]; */
};
struct OpusMSDecoder {
ChannelLayout layout;
/* Decoder states go here */
};
int opus_multistream_encoder_ctl_va_list(struct OpusMSEncoder *st, int request,
va_list ap);
int opus_multistream_decoder_ctl_va_list(struct OpusMSDecoder *st, int request,
va_list ap);
int validate_layout(const ChannelLayout *layout);
int get_left_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_right_channel(const ChannelLayout *layout, int stream_id, int prev);
int get_mono_channel(const ChannelLayout *layout, int stream_id, int prev);
typedef void (*opus_copy_channel_in_func)(
opus_val16 *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
);
typedef void (*opus_copy_channel_out_func)(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size,
void *user_data
);
#define MODE_SILK_ONLY 1000
#define MODE_HYBRID 1001
#define MODE_CELT_ONLY 1002
#define OPUS_SET_VOICE_RATIO_REQUEST 11018
#define OPUS_GET_VOICE_RATIO_REQUEST 11019
/** Configures the encoder's expected percentage of voice
* opposed to music or other signals.
*
* @note This interface is currently more aspiration than actuality. It's
* ultimately expected to bias an automatic signal classifier, but it currently
* just shifts the static bitrate to mode mapping around a little bit.
*
* @param[in] x <tt>int</tt>: Voice percentage in the range 0-100, inclusive.
* @hideinitializer */
#define OPUS_SET_VOICE_RATIO(x) OPUS_SET_VOICE_RATIO_REQUEST, __opus_check_int(x)
/** Gets the encoder's configured voice ratio value, @see OPUS_SET_VOICE_RATIO
*
* @param[out] x <tt>int*</tt>: Voice percentage in the range 0-100, inclusive.
* @hideinitializer */
#define OPUS_GET_VOICE_RATIO(x) OPUS_GET_VOICE_RATIO_REQUEST, __opus_check_int_ptr(x)
#define OPUS_SET_FORCE_MODE_REQUEST 11002
#define OPUS_SET_FORCE_MODE(x) OPUS_SET_FORCE_MODE_REQUEST, __opus_check_int(x)
typedef void (*downmix_func)(const void *, opus_val32 *, int, int, int, int, int);
void downmix_float(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
void downmix_int(const void *_x, opus_val32 *sub, int subframe, int offset, int c1, int c2, int C);
int is_digital_silence(const opus_val16* pcm, int frame_size, int channels, int lsb_depth);
int encode_size(int size, unsigned char *data);
opus_int32 frame_size_select(opus_int32 frame_size, int variable_duration, opus_int32 Fs);
opus_int32 opus_encode_native(OpusEncoder *st, const opus_val16 *pcm, int frame_size,
unsigned char *data, opus_int32 out_data_bytes, int lsb_depth,
const void *analysis_pcm, opus_int32 analysis_size, int c1, int c2,
int analysis_channels, downmix_func downmix, int float_api);
int opus_decode_native(OpusDecoder *st, const unsigned char *data, opus_int32 len,
opus_val16 *pcm, int frame_size, int decode_fec, int self_delimited,
opus_int32 *packet_offset, int soft_clip);
/* Make sure everything is properly aligned. */
static OPUS_INLINE int align(int i)
{
struct foo {char c; union { void* p; opus_int32 i; opus_val32 v; } u;};
unsigned int alignment = offsetof(struct foo, u);
/* Optimizing compilers should optimize div and multiply into and
for all sensible alignment values. */
return ((i + alignment - 1) / alignment) * alignment;
}
int opus_packet_parse_impl(const unsigned char *data, opus_int32 len,
int self_delimited, unsigned char *out_toc,
const unsigned char *frames[48], opus_int16 size[48],
int *payload_offset, opus_int32 *packet_offset);
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen, int self_delimited, int pad);
int pad_frame(unsigned char *data, opus_int32 len, opus_int32 new_len);
int opus_multistream_encode_native
(
struct OpusMSEncoder *st,
opus_copy_channel_in_func copy_channel_in,
const void *pcm,
int analysis_frame_size,
unsigned char *data,
opus_int32 max_data_bytes,
int lsb_depth,
downmix_func downmix,
int float_api,
void *user_data
);
int opus_multistream_decode_native(
struct OpusMSDecoder *st,
const unsigned char *data,
opus_int32 len,
void *pcm,
opus_copy_channel_out_func copy_channel_out,
int frame_size,
int decode_fec,
int soft_clip,
void *user_data
);
#endif /* OPUS_PRIVATE_H */

View File

@@ -0,0 +1,568 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/**
* @file opus_projection.h
* @brief Opus projection reference API
*/
#ifndef OPUS_PROJECTION_H
#define OPUS_PROJECTION_H
#include "opus_multistream.h"
#ifdef __cplusplus
extern "C" {
#endif
/** @cond OPUS_INTERNAL_DOC */
/** These are the actual encoder and decoder CTL ID numbers.
* They should not be used directly by applications.c
* In general, SETs should be even and GETs should be odd.*/
/**@{*/
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST 6001
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST 6003
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST 6005
/**@}*/
/** @endcond */
/** @defgroup opus_projection_ctls Projection specific encoder and decoder CTLs
*
* These are convenience macros that are specific to the
* opus_projection_encoder_ctl() and opus_projection_decoder_ctl()
* interface.
* The CTLs from @ref opus_genericctls, @ref opus_encoderctls,
* @ref opus_decoderctls, and @ref opus_multistream_ctls may be applied to a
* projection encoder or decoder as well.
*/
/**@{*/
/** Gets the gain (in dB. S7.8-format) of the demixing matrix from the encoder.
* @param[out] x <tt>opus_int32 *</tt>: Returns the gain (in dB. S7.8-format)
* of the demixing matrix.
* @hideinitializer
*/
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST, __opus_check_int_ptr(x)
/** Gets the size in bytes of the demixing matrix from the encoder.
* @param[out] x <tt>opus_int32 *</tt>: Returns the size in bytes of the
* demixing matrix.
* @hideinitializer
*/
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE(x) OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST, __opus_check_int_ptr(x)
/** Copies the demixing matrix to the supplied pointer location.
* @param[out] x <tt>unsigned char *</tt>: Returns the demixing matrix to the
* supplied pointer location.
* @param y <tt>opus_int32</tt>: The size in bytes of the reserved memory at the
* pointer location.
* @hideinitializer
*/
#define OPUS_PROJECTION_GET_DEMIXING_MATRIX(x,y) OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST, x, __opus_check_int(y)
/**@}*/
/** Opus projection encoder state.
* This contains the complete state of a projection Opus encoder.
* It is position independent and can be freely copied.
* @see opus_projection_ambisonics_encoder_create
*/
typedef struct OpusProjectionEncoder OpusProjectionEncoder;
/** Opus projection decoder state.
* This contains the complete state of a projection Opus decoder.
* It is position independent and can be freely copied.
* @see opus_projection_decoder_create
* @see opus_projection_decoder_init
*/
typedef struct OpusProjectionDecoder OpusProjectionDecoder;
/**\name Projection encoder functions */
/**@{*/
/** Gets the size of an OpusProjectionEncoder structure.
* @param channels <tt>int</tt>: The total number of input channels to encode.
* This must be no more than 255.
* @param mapping_family <tt>int</tt>: The mapping family to use for selecting
* the appropriate projection.
* @returns The size in bytes on success, or a negative error code
* (see @ref opus_errorcodes) on error.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_ambisonics_encoder_get_size(
int channels,
int mapping_family
);
/** Allocates and initializes a projection encoder state.
* Call opus_projection_encoder_destroy() to release
* this object when finished.
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels in the input signal.
* This must be at most 255.
* It may be greater than the number of
* coded channels (<code>streams +
* coupled_streams</code>).
* @param mapping_family <tt>int</tt>: The mapping family to use for selecting
* the appropriate projection.
* @param[out] streams <tt>int *</tt>: The total number of streams that will
* be encoded from the input.
* @param[out] coupled_streams <tt>int *</tt>: Number of coupled (2 channel)
* streams that will be encoded from the input.
* @param application <tt>int</tt>: The target encoder application.
* This must be one of the following:
* <dl>
* <dt>#OPUS_APPLICATION_VOIP</dt>
* <dd>Process signal for improved speech intelligibility.</dd>
* <dt>#OPUS_APPLICATION_AUDIO</dt>
* <dd>Favor faithfulness to the original input.</dd>
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
* <dd>Configure the minimum possible coding delay by disabling certain modes
* of operation.</dd>
* </dl>
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
* code (see @ref opus_errorcodes) on
* failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
opus_int32 Fs,
int channels,
int mapping_family,
int *streams,
int *coupled_streams,
int application,
int *error
) OPUS_ARG_NONNULL(4) OPUS_ARG_NONNULL(5);
/** Initialize a previously allocated projection encoder state.
* The memory pointed to by \a st must be at least the size returned by
* opus_projection_ambisonics_encoder_get_size().
* This is intended for applications which use their own allocator instead of
* malloc.
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
* @see opus_projection_ambisonics_encoder_create
* @see opus_projection_ambisonics_encoder_get_size
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to initialize.
* @param Fs <tt>opus_int32</tt>: Sampling rate of the input signal (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels in the input signal.
* This must be at most 255.
* It may be greater than the number of
* coded channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams to encode from the
* input.
* This must be no more than the number of channels.
* @param coupled_streams <tt>int</tt>: Number of coupled (2 channel) streams
* to encode.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* encoded channels (<code>streams +
* coupled_streams</code>) must be no
* more than the number of input channels.
* @param application <tt>int</tt>: The target encoder application.
* This must be one of the following:
* <dl>
* <dt>#OPUS_APPLICATION_VOIP</dt>
* <dd>Process signal for improved speech intelligibility.</dd>
* <dt>#OPUS_APPLICATION_AUDIO</dt>
* <dd>Favor faithfulness to the original input.</dd>
* <dt>#OPUS_APPLICATION_RESTRICTED_LOWDELAY</dt>
* <dd>Configure the minimum possible coding delay by disabling certain modes
* of operation.</dd>
* </dl>
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
* on failure.
*/
OPUS_EXPORT int opus_projection_ambisonics_encoder_init(
OpusProjectionEncoder *st,
opus_int32 Fs,
int channels,
int mapping_family,
int *streams,
int *coupled_streams,
int application
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(5) OPUS_ARG_NONNULL(6);
/** Encodes a projection Opus frame.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
* @param[in] pcm <tt>const opus_int16*</tt>: The input signal as interleaved
* samples.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode(
OpusProjectionEncoder *st,
const opus_int16 *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Encodes a projection Opus frame from floating point input.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
* @param[in] pcm <tt>const float*</tt>: The input signal as interleaved
* samples with a normal range of
* +/-1.0.
* Samples with a range beyond +/-1.0
* are supported but will be clipped by
* decoders using the integer API and
* should only be used if it is known
* that the far end supports extended
* dynamic range.
* This must contain
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: Number of samples per channel in the input
* signal.
* This must be an Opus frame size for the
* encoder's sampling rate.
* For example, at 48 kHz the permitted values
* are 120, 240, 480, 960, 1920, and 2880.
* Passing in a duration of less than 10 ms
* (480 samples at 48 kHz) will prevent the
* encoder from using the LPC or hybrid modes.
* @param[out] data <tt>unsigned char*</tt>: Output payload.
* This must contain storage for at
* least \a max_data_bytes.
* @param [in] max_data_bytes <tt>opus_int32</tt>: Size of the allocated
* memory for the output
* payload. This may be
* used to impose an upper limit on
* the instant bitrate, but should
* not be used as the only bitrate
* control. Use #OPUS_SET_BITRATE to
* control the bitrate.
* @returns The length of the encoded packet (in bytes) on success or a
* negative error code (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_encode_float(
OpusProjectionEncoder *st,
const float *pcm,
int frame_size,
unsigned char *data,
opus_int32 max_data_bytes
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(2) OPUS_ARG_NONNULL(4);
/** Frees an <code>OpusProjectionEncoder</code> allocated by
* opus_projection_ambisonics_encoder_create().
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state to be freed.
*/
OPUS_EXPORT void opus_projection_encoder_destroy(OpusProjectionEncoder *st);
/** Perform a CTL function on a projection Opus encoder.
*
* Generally the request and subsequent arguments are generated by a
* convenience macro.
* @param st <tt>OpusProjectionEncoder*</tt>: Projection encoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls,
* @ref opus_encoderctls, @ref opus_multistream_ctls, or
* @ref opus_projection_ctls
* @see opus_genericctls
* @see opus_encoderctls
* @see opus_multistream_ctls
* @see opus_projection_ctls
*/
OPUS_EXPORT int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...) OPUS_ARG_NONNULL(1);
/**@}*/
/**\name Projection decoder functions */
/**@{*/
/** Gets the size of an <code>OpusProjectionDecoder</code> structure.
* @param channels <tt>int</tt>: The total number of output channels.
* This must be no more than 255.
* @param streams <tt>int</tt>: The total number of streams coded in the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number streams to decode as coupled
* (2 channel) streams.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* coded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @returns The size in bytes on success, or a negative error code
* (see @ref opus_errorcodes) on error.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT opus_int32 opus_projection_decoder_get_size(
int channels,
int streams,
int coupled_streams
);
/** Allocates and initializes a projection decoder state.
* Call opus_projection_decoder_destroy() to release
* this object when finished.
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels to output.
* This must be at most 255.
* It may be different from the number of coded
* channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams coded in the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
* (2 channel) streams.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* coded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
* that mapping from coded channels to output channels,
* as described in @ref opus_projection and
* @ref opus_projection_ctls.
* @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
* demixing matrix, as
* described in @ref
* opus_projection_ctls.
* @param[out] error <tt>int *</tt>: Returns #OPUS_OK on success, or an error
* code (see @ref opus_errorcodes) on
* failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT OpusProjectionDecoder *opus_projection_decoder_create(
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
unsigned char *demixing_matrix,
opus_int32 demixing_matrix_size,
int *error
) OPUS_ARG_NONNULL(5);
/** Intialize a previously allocated projection decoder state object.
* The memory pointed to by \a st must be at least the size returned by
* opus_projection_decoder_get_size().
* This is intended for applications which use their own allocator instead of
* malloc.
* To reset a previously initialized state, use the #OPUS_RESET_STATE CTL.
* @see opus_projection_decoder_create
* @see opus_projection_deocder_get_size
* @param st <tt>OpusProjectionDecoder*</tt>: Projection encoder state to initialize.
* @param Fs <tt>opus_int32</tt>: Sampling rate to decode at (in Hz).
* This must be one of 8000, 12000, 16000,
* 24000, or 48000.
* @param channels <tt>int</tt>: Number of channels to output.
* This must be at most 255.
* It may be different from the number of coded
* channels (<code>streams +
* coupled_streams</code>).
* @param streams <tt>int</tt>: The total number of streams coded in the
* input.
* This must be no more than 255.
* @param coupled_streams <tt>int</tt>: Number of streams to decode as coupled
* (2 channel) streams.
* This must be no larger than the total
* number of streams.
* Additionally, The total number of
* coded channels (<code>streams +
* coupled_streams</code>) must be no
* more than 255.
* @param[in] demixing_matrix <tt>const unsigned char[demixing_matrix_size]</tt>: Demixing matrix
* that mapping from coded channels to output channels,
* as described in @ref opus_projection and
* @ref opus_projection_ctls.
* @param demixing_matrix_size <tt>opus_int32</tt>: The size in bytes of the
* demixing matrix, as
* described in @ref
* opus_projection_ctls.
* @returns #OPUS_OK on success, or an error code (see @ref opus_errorcodes)
* on failure.
*/
OPUS_EXPORT int opus_projection_decoder_init(
OpusProjectionDecoder *st,
opus_int32 Fs,
int channels,
int streams,
int coupled_streams,
unsigned char *demixing_matrix,
opus_int32 demixing_matrix_size
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(6);
/** Decode a projection Opus packet.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
* samples.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode(
OpusProjectionDecoder *st,
const unsigned char *data,
opus_int32 len,
opus_int16 *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Decode a projection Opus packet with floating point output.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
* @param[in] data <tt>const unsigned char*</tt>: Input payload.
* Use a <code>NULL</code>
* pointer to indicate packet
* loss.
* @param len <tt>opus_int32</tt>: Number of bytes in payload.
* @param[out] pcm <tt>opus_int16*</tt>: Output signal, with interleaved
* samples.
* This must contain room for
* <code>frame_size*channels</code>
* samples.
* @param frame_size <tt>int</tt>: The number of samples per channel of
* available space in \a pcm.
* If this is less than the maximum packet duration
* (120 ms; 5760 for 48kHz), this function will not be capable
* of decoding some packets. In the case of PLC (data==NULL)
* or FEC (decode_fec=1), then frame_size needs to be exactly
* the duration of audio that is missing, otherwise the
* decoder will not be in the optimal state to decode the
* next incoming packet. For the PLC and FEC cases, frame_size
* <b>must</b> be a multiple of 2.5 ms.
* @param decode_fec <tt>int</tt>: Flag (0 or 1) to request that any in-band
* forward error correction data be decoded.
* If no such data is available, the frame is
* decoded as if it were lost.
* @returns Number of samples decoded on success or a negative error code
* (see @ref opus_errorcodes) on failure.
*/
OPUS_EXPORT OPUS_WARN_UNUSED_RESULT int opus_projection_decode_float(
OpusProjectionDecoder *st,
const unsigned char *data,
opus_int32 len,
float *pcm,
int frame_size,
int decode_fec
) OPUS_ARG_NONNULL(1) OPUS_ARG_NONNULL(4);
/** Perform a CTL function on a projection Opus decoder.
*
* Generally the request and subsequent arguments are generated by a
* convenience macro.
* @param st <tt>OpusProjectionDecoder*</tt>: Projection decoder state.
* @param request This and all remaining parameters should be replaced by one
* of the convenience macros in @ref opus_genericctls,
* @ref opus_decoderctls, @ref opus_multistream_ctls, or
* @ref opus_projection_ctls.
* @see opus_genericctls
* @see opus_decoderctls
* @see opus_multistream_ctls
* @see opus_projection_ctls
*/
OPUS_EXPORT int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...) OPUS_ARG_NONNULL(1);
/** Frees an <code>OpusProjectionDecoder</code> allocated by
* opus_projection_decoder_create().
* @param st <tt>OpusProjectionDecoder</tt>: Projection decoder state to be freed.
*/
OPUS_EXPORT void opus_projection_decoder_destroy(OpusProjectionDecoder *st);
/**@}*/
/**@}*/
#ifdef __cplusplus
}
#endif
#endif /* OPUS_PROJECTION_H */

View File

@@ -0,0 +1,258 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "celt/mathops.h"
#include "celt/os_support.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "opus_projection.h"
#include "opus_multistream.h"
#include "mapping_matrix.h"
#include "celt/stack_alloc.h"
struct OpusProjectionDecoder
{
opus_int32 demixing_matrix_size_in_bytes;
/* Encoder states go here */
};
#if !defined(DISABLE_FLOAT_API)
static void opus_projection_copy_channel_out_float(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size,
void *user_data)
{
float *float_dst;
const MappingMatrix *matrix;
float_dst = (float *)dst;
matrix = (const MappingMatrix *)user_data;
if (dst_channel == 0)
OPUS_CLEAR(float_dst, frame_size * dst_stride);
if (src != NULL)
mapping_matrix_multiply_channel_out_float(matrix, src, dst_channel,
src_stride, float_dst, dst_stride, frame_size);
}
#endif
static void opus_projection_copy_channel_out_short(
void *dst,
int dst_stride,
int dst_channel,
const opus_val16 *src,
int src_stride,
int frame_size,
void *user_data)
{
opus_int16 *short_dst;
const MappingMatrix *matrix;
short_dst = (opus_int16 *)dst;
matrix = (const MappingMatrix *)user_data;
if (dst_channel == 0)
OPUS_CLEAR(short_dst, frame_size * dst_stride);
if (src != NULL)
mapping_matrix_multiply_channel_out_short(matrix, src, dst_channel,
src_stride, short_dst, dst_stride, frame_size);
}
static MappingMatrix *get_dec_demixing_matrix(OpusProjectionDecoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (MappingMatrix*)(void*)((char*)st +
align(sizeof(OpusProjectionDecoder)));
}
static OpusMSDecoder *get_multistream_decoder(OpusProjectionDecoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (OpusMSDecoder*)(void*)((char*)st +
align(sizeof(OpusProjectionDecoder) +
st->demixing_matrix_size_in_bytes));
}
opus_int32 opus_projection_decoder_get_size(int channels, int streams,
int coupled_streams)
{
opus_int32 matrix_size;
opus_int32 decoder_size;
matrix_size =
mapping_matrix_get_size(streams + coupled_streams, channels);
if (!matrix_size)
return 0;
decoder_size = opus_multistream_decoder_get_size(streams, coupled_streams);
if (!decoder_size)
return 0;
return align(sizeof(OpusProjectionDecoder)) + matrix_size + decoder_size;
}
int opus_projection_decoder_init(OpusProjectionDecoder *st, opus_int32 Fs,
int channels, int streams, int coupled_streams,
unsigned char *demixing_matrix, opus_int32 demixing_matrix_size)
{
int nb_input_streams;
opus_int32 expected_matrix_size;
int i, ret;
unsigned char mapping[255];
VARDECL(opus_int16, buf);
ALLOC_STACK;
/* Verify supplied matrix size. */
nb_input_streams = streams + coupled_streams;
expected_matrix_size = nb_input_streams * channels * sizeof(opus_int16);
if (expected_matrix_size != demixing_matrix_size)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
/* Convert demixing matrix input into internal format. */
ALLOC(buf, nb_input_streams * channels, opus_int16);
for (i = 0; i < nb_input_streams * channels; i++)
{
int s = demixing_matrix[2*i + 1] << 8 | demixing_matrix[2*i];
s = ((s & 0xFFFF) ^ 0x8000) - 0x8000;
buf[i] = (opus_int16)s;
}
/* Assign demixing matrix. */
st->demixing_matrix_size_in_bytes =
mapping_matrix_get_size(channels, nb_input_streams);
if (!st->demixing_matrix_size_in_bytes)
{
RESTORE_STACK;
return OPUS_BAD_ARG;
}
mapping_matrix_init(get_dec_demixing_matrix(st), channels, nb_input_streams, 0,
buf, demixing_matrix_size);
/* Set trivial mapping so each input channel pairs with a matrix column. */
for (i = 0; i < channels; i++)
mapping[i] = i;
ret = opus_multistream_decoder_init(
get_multistream_decoder(st), Fs, channels, streams, coupled_streams, mapping);
RESTORE_STACK;
return ret;
}
OpusProjectionDecoder *opus_projection_decoder_create(
opus_int32 Fs, int channels, int streams, int coupled_streams,
unsigned char *demixing_matrix, opus_int32 demixing_matrix_size, int *error)
{
int size;
int ret;
OpusProjectionDecoder *st;
/* Allocate space for the projection decoder. */
size = opus_projection_decoder_get_size(channels, streams, coupled_streams);
if (!size) {
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
st = (OpusProjectionDecoder *)opus_alloc(size);
if (!st)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
/* Initialize projection decoder with provided settings. */
ret = opus_projection_decoder_init(st, Fs, channels, streams, coupled_streams,
demixing_matrix, demixing_matrix_size);
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
if (error)
*error = ret;
return st;
}
#ifdef FIXED_POINT
int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st));
}
#else
int opus_projection_decode(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, opus_int16 *pcm, int frame_size,
int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_short, frame_size, decode_fec, 1,
get_dec_demixing_matrix(st));
}
#endif
#ifndef DISABLE_FLOAT_API
int opus_projection_decode_float(OpusProjectionDecoder *st, const unsigned char *data,
opus_int32 len, float *pcm, int frame_size, int decode_fec)
{
return opus_multistream_decode_native(get_multistream_decoder(st), data, len,
pcm, opus_projection_copy_channel_out_float, frame_size, decode_fec, 0,
get_dec_demixing_matrix(st));
}
#endif
int opus_projection_decoder_ctl(OpusProjectionDecoder *st, int request, ...)
{
va_list ap;
int ret = OPUS_OK;
va_start(ap, request);
ret = opus_multistream_decoder_ctl_va_list(get_multistream_decoder(st),
request, ap);
va_end(ap);
return ret;
}
void opus_projection_decoder_destroy(OpusProjectionDecoder *st)
{
opus_free(st);
}

View File

@@ -0,0 +1,468 @@
/* Copyright (c) 2017 Google Inc.
Written by Andrew Allen */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "celt/mathops.h"
#include "celt/os_support.h"
#include "opus_private.h"
#include "opus_defines.h"
#include "opus_projection.h"
#include "opus_multistream.h"
#include "celt/stack_alloc.h"
#include "mapping_matrix.h"
struct OpusProjectionEncoder
{
opus_int32 mixing_matrix_size_in_bytes;
opus_int32 demixing_matrix_size_in_bytes;
/* Encoder states go here */
};
#if !defined(DISABLE_FLOAT_API)
static void opus_projection_copy_channel_in_float(
opus_val16 *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_float((const MappingMatrix*)user_data,
(const float*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
#endif
static void opus_projection_copy_channel_in_short(
opus_val16 *dst,
int dst_stride,
const void *src,
int src_stride,
int src_channel,
int frame_size,
void *user_data
)
{
mapping_matrix_multiply_channel_in_short((const MappingMatrix*)user_data,
(const opus_int16*)src, src_stride, dst, src_channel, dst_stride, frame_size);
}
static int get_order_plus_one_from_channels(int channels, int *order_plus_one)
{
int order_plus_one_;
int acn_channels;
int nondiegetic_channels;
/* Allowed numbers of channels:
* (1 + n)^2 + 2j, for n = 0...14 and j = 0 or 1.
*/
if (channels < 1 || channels > 227)
return OPUS_BAD_ARG;
order_plus_one_ = isqrt32(channels);
acn_channels = order_plus_one_ * order_plus_one_;
nondiegetic_channels = channels - acn_channels;
if (nondiegetic_channels != 0 && nondiegetic_channels != 2)
return OPUS_BAD_ARG;
if (order_plus_one)
*order_plus_one = order_plus_one_;
return OPUS_OK;
}
static int get_streams_from_channels(int channels, int mapping_family,
int *streams, int *coupled_streams,
int *order_plus_one)
{
if (mapping_family == 3)
{
if (get_order_plus_one_from_channels(channels, order_plus_one) != OPUS_OK)
return OPUS_BAD_ARG;
if (streams)
*streams = (channels + 1) / 2;
if (coupled_streams)
*coupled_streams = channels / 2;
return OPUS_OK;
}
return OPUS_BAD_ARG;
}
static MappingMatrix *get_mixing_matrix(OpusProjectionEncoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (MappingMatrix *)(void*)((char*)st +
align(sizeof(OpusProjectionEncoder)));
}
static MappingMatrix *get_enc_demixing_matrix(OpusProjectionEncoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (MappingMatrix *)(void*)((char*)st +
align(sizeof(OpusProjectionEncoder) +
st->mixing_matrix_size_in_bytes));
}
static OpusMSEncoder *get_multistream_encoder(OpusProjectionEncoder *st)
{
/* void* cast avoids clang -Wcast-align warning */
return (OpusMSEncoder *)(void*)((char*)st +
align(sizeof(OpusProjectionEncoder) +
st->mixing_matrix_size_in_bytes +
st->demixing_matrix_size_in_bytes));
}
opus_int32 opus_projection_ambisonics_encoder_get_size(int channels,
int mapping_family)
{
int nb_streams;
int nb_coupled_streams;
int order_plus_one;
int mixing_matrix_rows, mixing_matrix_cols;
int demixing_matrix_rows, demixing_matrix_cols;
opus_int32 mixing_matrix_size, demixing_matrix_size;
opus_int32 encoder_size;
int ret;
ret = get_streams_from_channels(channels, mapping_family, &nb_streams,
&nb_coupled_streams, &order_plus_one);
if (ret != OPUS_OK)
return 0;
if (order_plus_one == 2)
{
mixing_matrix_rows = mapping_matrix_foa_mixing.rows;
mixing_matrix_cols = mapping_matrix_foa_mixing.cols;
demixing_matrix_rows = mapping_matrix_foa_demixing.rows;
demixing_matrix_cols = mapping_matrix_foa_demixing.cols;
}
else if (order_plus_one == 3)
{
mixing_matrix_rows = mapping_matrix_soa_mixing.rows;
mixing_matrix_cols = mapping_matrix_soa_mixing.cols;
demixing_matrix_rows = mapping_matrix_soa_demixing.rows;
demixing_matrix_cols = mapping_matrix_soa_demixing.cols;
}
else if (order_plus_one == 4)
{
mixing_matrix_rows = mapping_matrix_toa_mixing.rows;
mixing_matrix_cols = mapping_matrix_toa_mixing.cols;
demixing_matrix_rows = mapping_matrix_toa_demixing.rows;
demixing_matrix_cols = mapping_matrix_toa_demixing.cols;
}
else
return 0;
mixing_matrix_size =
mapping_matrix_get_size(mixing_matrix_rows, mixing_matrix_cols);
if (!mixing_matrix_size)
return 0;
demixing_matrix_size =
mapping_matrix_get_size(demixing_matrix_rows, demixing_matrix_cols);
if (!demixing_matrix_size)
return 0;
encoder_size =
opus_multistream_encoder_get_size(nb_streams, nb_coupled_streams);
if (!encoder_size)
return 0;
return align(sizeof(OpusProjectionEncoder)) +
mixing_matrix_size + demixing_matrix_size + encoder_size;
}
int opus_projection_ambisonics_encoder_init(OpusProjectionEncoder *st, opus_int32 Fs,
int channels, int mapping_family,
int *streams, int *coupled_streams,
int application)
{
MappingMatrix *mixing_matrix;
MappingMatrix *demixing_matrix;
OpusMSEncoder *ms_encoder;
int i;
int ret;
int order_plus_one;
unsigned char mapping[255];
if (streams == NULL || coupled_streams == NULL) {
return OPUS_BAD_ARG;
}
if (get_streams_from_channels(channels, mapping_family, streams,
coupled_streams, &order_plus_one) != OPUS_OK)
return OPUS_BAD_ARG;
if (mapping_family == 3)
{
/* Assign mixing matrix based on available pre-computed matrices. */
mixing_matrix = get_mixing_matrix(st);
if (order_plus_one == 2)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_foa_mixing.rows,
mapping_matrix_foa_mixing.cols, mapping_matrix_foa_mixing.gain,
mapping_matrix_foa_mixing_data,
sizeof(mapping_matrix_foa_mixing_data));
}
else if (order_plus_one == 3)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_soa_mixing.rows,
mapping_matrix_soa_mixing.cols, mapping_matrix_soa_mixing.gain,
mapping_matrix_soa_mixing_data,
sizeof(mapping_matrix_soa_mixing_data));
}
else if (order_plus_one == 4)
{
mapping_matrix_init(mixing_matrix, mapping_matrix_toa_mixing.rows,
mapping_matrix_toa_mixing.cols, mapping_matrix_toa_mixing.gain,
mapping_matrix_toa_mixing_data,
sizeof(mapping_matrix_toa_mixing_data));
}
else
return OPUS_BAD_ARG;
st->mixing_matrix_size_in_bytes = mapping_matrix_get_size(
mixing_matrix->rows, mixing_matrix->cols);
if (!st->mixing_matrix_size_in_bytes)
return OPUS_BAD_ARG;
/* Assign demixing matrix based on available pre-computed matrices. */
demixing_matrix = get_enc_demixing_matrix(st);
if (order_plus_one == 2)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_foa_demixing.rows,
mapping_matrix_foa_demixing.cols, mapping_matrix_foa_demixing.gain,
mapping_matrix_foa_demixing_data,
sizeof(mapping_matrix_foa_demixing_data));
}
else if (order_plus_one == 3)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_soa_demixing.rows,
mapping_matrix_soa_demixing.cols, mapping_matrix_soa_demixing.gain,
mapping_matrix_soa_demixing_data,
sizeof(mapping_matrix_soa_demixing_data));
}
else if (order_plus_one == 4)
{
mapping_matrix_init(demixing_matrix, mapping_matrix_toa_demixing.rows,
mapping_matrix_toa_demixing.cols, mapping_matrix_toa_demixing.gain,
mapping_matrix_toa_demixing_data,
sizeof(mapping_matrix_toa_demixing_data));
}
else
return OPUS_BAD_ARG;
st->demixing_matrix_size_in_bytes = mapping_matrix_get_size(
demixing_matrix->rows, demixing_matrix->cols);
if (!st->demixing_matrix_size_in_bytes)
return OPUS_BAD_ARG;
}
else
return OPUS_UNIMPLEMENTED;
/* Ensure matrices are large enough for desired coding scheme. */
if (*streams + *coupled_streams > mixing_matrix->rows ||
channels > mixing_matrix->cols ||
channels > demixing_matrix->rows ||
*streams + *coupled_streams > demixing_matrix->cols)
return OPUS_BAD_ARG;
/* Set trivial mapping so each input channel pairs with a matrix column. */
for (i = 0; i < channels; i++)
mapping[i] = i;
/* Initialize multistream encoder with provided settings. */
ms_encoder = get_multistream_encoder(st);
ret = opus_multistream_encoder_init(ms_encoder, Fs, channels, *streams,
*coupled_streams, mapping, application);
return ret;
}
OpusProjectionEncoder *opus_projection_ambisonics_encoder_create(
opus_int32 Fs, int channels, int mapping_family, int *streams,
int *coupled_streams, int application, int *error)
{
int size;
int ret;
OpusProjectionEncoder *st;
/* Allocate space for the projection encoder. */
size = opus_projection_ambisonics_encoder_get_size(channels, mapping_family);
if (!size) {
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
st = (OpusProjectionEncoder *)opus_alloc(size);
if (!st)
{
if (error)
*error = OPUS_ALLOC_FAIL;
return NULL;
}
/* Initialize projection encoder with provided settings. */
ret = opus_projection_ambisonics_encoder_init(st, Fs, channels,
mapping_family, streams, coupled_streams, application);
if (ret != OPUS_OK)
{
opus_free(st);
st = NULL;
}
if (error)
*error = ret;
return st;
}
int opus_projection_encode(OpusProjectionEncoder *st, const opus_int16 *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_short, pcm, frame_size, data,
max_data_bytes, 16, downmix_int, 0, get_mixing_matrix(st));
}
#ifndef DISABLE_FLOAT_API
#ifdef FIXED_POINT
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_float, pcm, frame_size, data,
max_data_bytes, 16, downmix_float, 1, get_mixing_matrix(st));
}
#else
int opus_projection_encode_float(OpusProjectionEncoder *st, const float *pcm,
int frame_size, unsigned char *data,
opus_int32 max_data_bytes)
{
return opus_multistream_encode_native(get_multistream_encoder(st),
opus_projection_copy_channel_in_float, pcm, frame_size, data,
max_data_bytes, 24, downmix_float, 1, get_mixing_matrix(st));
}
#endif
#endif
void opus_projection_encoder_destroy(OpusProjectionEncoder *st)
{
opus_free(st);
}
int opus_projection_encoder_ctl(OpusProjectionEncoder *st, int request, ...)
{
va_list ap;
MappingMatrix *demixing_matrix;
OpusMSEncoder *ms_encoder;
int ret = OPUS_OK;
ms_encoder = get_multistream_encoder(st);
demixing_matrix = get_enc_demixing_matrix(st);
va_start(ap, request);
switch(request)
{
case OPUS_PROJECTION_GET_DEMIXING_MATRIX_SIZE_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value =
ms_encoder->layout.nb_channels * (ms_encoder->layout.nb_streams
+ ms_encoder->layout.nb_coupled_streams) * sizeof(opus_int16);
}
break;
case OPUS_PROJECTION_GET_DEMIXING_MATRIX_GAIN_REQUEST:
{
opus_int32 *value = va_arg(ap, opus_int32*);
if (!value)
{
goto bad_arg;
}
*value = demixing_matrix->gain;
}
break;
case OPUS_PROJECTION_GET_DEMIXING_MATRIX_REQUEST:
{
int i, j, k, l;
int nb_input_streams;
int nb_output_streams;
unsigned char *external_char;
opus_int16 *internal_short;
opus_int32 external_size;
opus_int32 internal_size;
/* (I/O is in relation to the decoder's perspective). */
nb_input_streams = ms_encoder->layout.nb_streams +
ms_encoder->layout.nb_coupled_streams;
nb_output_streams = ms_encoder->layout.nb_channels;
external_char = va_arg(ap, unsigned char *);
external_size = va_arg(ap, opus_int32);
if (!external_char)
{
goto bad_arg;
}
internal_short = mapping_matrix_get_data(demixing_matrix);
internal_size = nb_input_streams * nb_output_streams * sizeof(opus_int16);
if (external_size != internal_size)
{
goto bad_arg;
}
/* Copy demixing matrix subset to output destination. */
l = 0;
for (i = 0; i < nb_input_streams; i++) {
for (j = 0; j < nb_output_streams; j++) {
k = demixing_matrix->rows * i + j;
external_char[2*l] = (unsigned char)internal_short[k];
external_char[2*l+1] = (unsigned char)(internal_short[k] >> 8);
l++;
}
}
}
break;
default:
{
ret = opus_multistream_encoder_ctl_va_list(ms_encoder, request, ap);
}
break;
}
va_end(ap);
return ret;
bad_arg:
va_end(ap);
return OPUS_BAD_ARG;
}

View File

@@ -0,0 +1,166 @@
/* (C) COPYRIGHT 1994-2002 Xiph.Org Foundation */
/* Modified by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
/* opus_types.h based on ogg_types.h from libogg */
/**
@file opus_types.h
@brief Opus reference implementation types
*/
#ifndef OPUS_TYPES_H
#define OPUS_TYPES_H
#define opus_int int /* used for counters etc; at least 16 bits */
#define opus_int64 long long
#define opus_int8 signed char
#define opus_uint unsigned int /* used for counters etc; at least 16 bits */
#define opus_uint64 unsigned long long
#define opus_uint8 unsigned char
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
#if (defined(__STDC__) && __STDC__ && defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
#include <stdint.h>
# undef opus_int64
# undef opus_int8
# undef opus_uint64
# undef opus_uint8
typedef int8_t opus_int8;
typedef uint8_t opus_uint8;
typedef int16_t opus_int16;
typedef uint16_t opus_uint16;
typedef int32_t opus_int32;
typedef uint32_t opus_uint32;
typedef int64_t opus_int64;
typedef uint64_t opus_uint64;
#elif defined(_WIN32)
# if defined(__CYGWIN__)
# include <_G_config.h>
typedef _G_int32_t opus_int32;
typedef _G_uint32_t opus_uint32;
typedef _G_int16 opus_int16;
typedef _G_uint16 opus_uint16;
# elif defined(__MINGW32__)
typedef short opus_int16;
typedef unsigned short opus_uint16;
typedef int opus_int32;
typedef unsigned int opus_uint32;
# elif defined(__MWERKS__)
typedef int opus_int32;
typedef unsigned int opus_uint32;
typedef short opus_int16;
typedef unsigned short opus_uint16;
# else
/* MSVC/Borland */
typedef __int32 opus_int32;
typedef unsigned __int32 opus_uint32;
typedef __int16 opus_int16;
typedef unsigned __int16 opus_uint16;
# endif
#elif defined(__MACOS__)
# include <sys/types.h>
typedef SInt16 opus_int16;
typedef UInt16 opus_uint16;
typedef SInt32 opus_int32;
typedef UInt32 opus_uint32;
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
# include <sys/types.h>
typedef int16_t opus_int16;
typedef u_int16_t opus_uint16;
typedef int32_t opus_int32;
typedef u_int32_t opus_uint32;
#elif defined(__BEOS__)
/* Be */
# include <inttypes.h>
typedef int16 opus_int16;
typedef u_int16 opus_uint16;
typedef int32_t opus_int32;
typedef u_int32_t opus_uint32;
#elif defined (__EMX__)
/* OS/2 GCC */
typedef short opus_int16;
typedef unsigned short opus_uint16;
typedef int opus_int32;
typedef unsigned int opus_uint32;
#elif defined (DJGPP)
/* DJGPP */
typedef short opus_int16;
typedef unsigned short opus_uint16;
typedef int opus_int32;
typedef unsigned int opus_uint32;
#elif defined(R5900)
/* PS2 EE */
typedef int opus_int32;
typedef unsigned opus_uint32;
typedef short opus_int16;
typedef unsigned short opus_uint16;
#elif defined(__SYMBIAN32__)
/* Symbian GCC */
typedef signed short opus_int16;
typedef unsigned short opus_uint16;
typedef signed int opus_int32;
typedef unsigned int opus_uint32;
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
typedef short opus_int16;
typedef unsigned short opus_uint16;
typedef long opus_int32;
typedef unsigned long opus_uint32;
#elif defined(CONFIG_TI_C6X)
typedef short opus_int16;
typedef unsigned short opus_uint16;
typedef int opus_int32;
typedef unsigned int opus_uint32;
#else
/* Give up, take a reasonable guess */
typedef short opus_int16;
typedef unsigned short opus_uint16;
typedef int opus_int32;
typedef unsigned int opus_uint32;
#endif
#endif /* OPUS_TYPES_H */

View File

@@ -0,0 +1,374 @@
/* Copyright (c) 2011 Xiph.Org Foundation
Written by Jean-Marc Valin */
/*
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.
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 COPYRIGHT OWNER
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.
*/
//#ifdef HAVE_CONFIG_H
#include "config.h"
//#endif
#include "opus.h"
#include "opus_private.h"
#include "celt/os_support.h"
int opus_repacketizer_get_size(void)
{
return sizeof(OpusRepacketizer);
}
OpusRepacketizer *opus_repacketizer_init(OpusRepacketizer *rp)
{
rp->nb_frames = 0;
return rp;
}
OpusRepacketizer *opus_repacketizer_create(void)
{
OpusRepacketizer *rp;
rp=(OpusRepacketizer *)opus_alloc(opus_repacketizer_get_size());
if(rp==NULL)return NULL;
return opus_repacketizer_init(rp);
}
void opus_repacketizer_destroy(OpusRepacketizer *rp)
{
opus_free(rp);
}
static int opus_repacketizer_cat_impl(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len, int self_delimited)
{
unsigned char tmp_toc;
int curr_nb_frames,ret;
/* Set of check ToC */
if (len<1) return OPUS_INVALID_PACKET;
if (rp->nb_frames == 0)
{
rp->toc = data[0];
rp->framesize = opus_packet_get_samples_per_frame(data, 8000);
} else if ((rp->toc&0xFC) != (data[0]&0xFC))
{
/*fprintf(stderr, "toc mismatch: 0x%x vs 0x%x\n", rp->toc, data[0]);*/
return OPUS_INVALID_PACKET;
}
curr_nb_frames = opus_packet_get_nb_frames(data, len);
if(curr_nb_frames<1) return OPUS_INVALID_PACKET;
/* Check the 120 ms maximum packet size */
if ((curr_nb_frames+rp->nb_frames)*rp->framesize > 960)
{
return OPUS_INVALID_PACKET;
}
ret=opus_packet_parse_impl(data, len, self_delimited, &tmp_toc, &rp->frames[rp->nb_frames], &rp->len[rp->nb_frames], NULL, NULL);
if(ret<1)return ret;
rp->nb_frames += curr_nb_frames;
return OPUS_OK;
}
int opus_repacketizer_cat(OpusRepacketizer *rp, const unsigned char *data, opus_int32 len)
{
return opus_repacketizer_cat_impl(rp, data, len, 0);
}
int opus_repacketizer_get_nb_frames(OpusRepacketizer *rp)
{
return rp->nb_frames;
}
opus_int32 opus_repacketizer_out_range_impl(OpusRepacketizer *rp, int begin, int end,
unsigned char *data, opus_int32 maxlen, int self_delimited, int pad)
{
int i, count;
opus_int32 tot_size;
opus_int16 *len;
const unsigned char **frames;
unsigned char * ptr;
if (begin<0 || begin>=end || end>rp->nb_frames)
{
/*fprintf(stderr, "%d %d %d\n", begin, end, rp->nb_frames);*/
return OPUS_BAD_ARG;
}
count = end-begin;
len = rp->len+begin;
frames = rp->frames+begin;
if (self_delimited)
tot_size = 1 + (len[count-1]>=252);
else
tot_size = 0;
ptr = data;
if (count==1)
{
/* Code 0 */
tot_size += len[0]+1;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = rp->toc&0xFC;
} else if (count==2)
{
if (len[1] == len[0])
{
/* Code 1 */
tot_size += 2*len[0]+1;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x1;
} else {
/* Code 2 */
tot_size += len[0]+len[1]+2+(len[0]>=252);
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x2;
ptr += encode_size(len[0], ptr);
}
}
if (count > 2 || (pad && tot_size < maxlen))
{
/* Code 3 */
int vbr;
int pad_amount=0;
/* Restart the process for the padding case */
ptr = data;
if (self_delimited)
tot_size = 1 + (len[count-1]>=252);
else
tot_size = 0;
vbr = 0;
for (i=1;i<count;i++)
{
if (len[i] != len[0])
{
vbr=1;
break;
}
}
if (vbr)
{
tot_size += 2;
for (i=0;i<count-1;i++)
tot_size += 1 + (len[i]>=252) + len[i];
tot_size += len[count-1];
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x3;
*ptr++ = count | 0x80;
} else {
tot_size += count*len[0]+2;
if (tot_size > maxlen)
return OPUS_BUFFER_TOO_SMALL;
*ptr++ = (rp->toc&0xFC) | 0x3;
*ptr++ = count;
}
pad_amount = pad ? (maxlen-tot_size) : 0;
if (pad_amount != 0)
{
int nb_255s;
data[1] |= 0x40;
nb_255s = (pad_amount-1)/255;
for (i=0;i<nb_255s;i++)
*ptr++ = 255;
*ptr++ = pad_amount-255*nb_255s-1;
tot_size += pad_amount;
}
if (vbr)
{
for (i=0;i<count-1;i++)
ptr += encode_size(len[i], ptr);
}
}
if (self_delimited) {
int sdlen = encode_size(len[count-1], ptr);
ptr += sdlen;
}
/* Copy the actual data */
for (i=0;i<count;i++)
{
/* Using OPUS_MOVE() instead of OPUS_COPY() in case we're doing in-place
padding from opus_packet_pad or opus_packet_unpad(). */
/* assert disabled because it's not valid in C. */
/* celt_assert(frames[i] + len[i] <= data || ptr <= frames[i]); */
OPUS_MOVE(ptr, frames[i], len[i]);
ptr += len[i];
}
if (pad)
{
/* Fill padding with zeros. */
while (ptr<data+maxlen)
*ptr++=0;
}
return tot_size;
}
opus_int32 opus_repacketizer_out_range(OpusRepacketizer *rp, int begin, int end, unsigned char *data, opus_int32 maxlen)
{
return opus_repacketizer_out_range_impl(rp, begin, end, data, maxlen, 0, 0);
}
opus_int32 opus_repacketizer_out(OpusRepacketizer *rp, unsigned char *data, opus_int32 maxlen)
{
return opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, maxlen, 0, 0);
}
int opus_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len)
{
OpusRepacketizer *rp = (OpusRepacketizer*)malloc(sizeof(OpusRepacketizer));
opus_int32 ret;
if (len < 1) {
free(rp);
return OPUS_BAD_ARG;
}
if (len==new_len) {
free(rp);
return OPUS_OK;
}
else if (len > new_len) {
free(rp);
return OPUS_BAD_ARG;
}
opus_repacketizer_init(rp);
/* Moving payload to the end of the packet so we can do in-place padding */
OPUS_MOVE(data+new_len-len, data, len);
ret = opus_repacketizer_cat(rp, data+new_len-len, len);
if (ret != OPUS_OK) {
free(rp);
return ret;
}
ret = opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, new_len, 0, 1);
free(rp);
if (ret > 0)
return OPUS_OK;
else
return ret;
}
opus_int32 opus_packet_unpad(unsigned char *data, opus_int32 len)
{
OpusRepacketizer *rp = (OpusRepacketizer*)malloc(sizeof(OpusRepacketizer));
opus_int32 ret;
if (len < 1) {
free(rp);
return OPUS_BAD_ARG;
}
opus_repacketizer_init(rp);
ret = opus_repacketizer_cat(rp, data, len);
if (ret < 0) {
free(rp);
return ret;
}
ret = opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, data, len, 0, 0);
free(rp);
celt_assert(ret > 0 && ret <= len);
return ret;
}
int opus_multistream_packet_pad(unsigned char *data, opus_int32 len, opus_int32 new_len, int nb_streams)
{
int s;
int count;
unsigned char toc;
opus_int16 size[48];
opus_int32 packet_offset;
opus_int32 amount;
if (len < 1)
return OPUS_BAD_ARG;
if (len==new_len)
return OPUS_OK;
else if (len > new_len)
return OPUS_BAD_ARG;
amount = new_len - len;
/* Seek to last stream */
for (s=0;s<nb_streams-1;s++)
{
if (len<=0)
return OPUS_INVALID_PACKET;
count = opus_packet_parse_impl(data, len, 1, &toc, NULL,
size, NULL, &packet_offset);
if (count<0)
return count;
data += packet_offset;
len -= packet_offset;
}
return opus_packet_pad(data, len, len+amount);
}
opus_int32 opus_multistream_packet_unpad(unsigned char *data, opus_int32 len, int nb_streams)
{
int s;
unsigned char toc;
opus_int16 size[48];
opus_int32 packet_offset;
OpusRepacketizer *rp = (OpusRepacketizer*)malloc(sizeof(OpusRepacketizer));
unsigned char *dst;
opus_int32 dst_len;
if (len < 1){
free(rp);
return OPUS_BAD_ARG;
}
dst = data;
dst_len = 0;
/* Unpad all frames */
for (s=0;s<nb_streams;s++)
{
opus_int32 ret;
int self_delimited = s!=nb_streams-1;
if (len<=0) {
free(rp);
return OPUS_INVALID_PACKET;
}
opus_repacketizer_init(rp);
ret = opus_packet_parse_impl(data, len, self_delimited, &toc, NULL,
size, NULL, &packet_offset);
if (ret<0) {
free(rp);
return ret;
}
ret = opus_repacketizer_cat_impl(rp, data, packet_offset, self_delimited);
if (ret < 0) {
free(rp);
return ret;
}
ret = opus_repacketizer_out_range_impl(rp, 0, rp->nb_frames, dst, len, self_delimited, 0);
if (ret < 0) {
free(rp);
return ret;
}
else
dst_len += ret;
dst += ret;
data += packet_offset;
len -= packet_offset;
}
free(rp);
return dst_len;
}

View File

@@ -0,0 +1,267 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
/* Conversion between prediction filter coefficients and NLSFs */
/* Requires the order to be an even number */
/* A piecewise linear approximation maps LSF <-> cos(LSF) */
/* Therefore the result is not accurate NLSFs, but the two */
/* functions are accurate inverses of each other */
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "SigProc_FIX.h"
#include "tables.h"
/* Number of binary divisions, when not in low complexity mode */
#define BIN_DIV_STEPS_A2NLSF_FIX 3 /* must be no higher than 16 - log2( LSF_COS_TAB_SZ_FIX ) */
#define MAX_ITERATIONS_A2NLSF_FIX 16
/* Helper function for A2NLSF(..) */
/* Transforms polynomials from cos(n*f) to cos(f)^n */
static OPUS_INLINE void silk_A2NLSF_trans_poly(
opus_int32 *p, /* I/O Polynomial */
const opus_int dd /* I Polynomial order (= filter order / 2 ) */
)
{
opus_int k, n;
for( k = 2; k <= dd; k++ ) {
for( n = dd; n > k; n-- ) {
p[ n - 2 ] -= p[ n ];
}
p[ k - 2 ] -= silk_LSHIFT( p[ k ], 1 );
}
}
/* Helper function for A2NLSF(..) */
/* Polynomial evaluation */
static OPUS_INLINE opus_int32 silk_A2NLSF_eval_poly( /* return the polynomial evaluation, in Q16 */
opus_int32 *p, /* I Polynomial, Q16 */
const opus_int32 x, /* I Evaluation point, Q12 */
const opus_int dd /* I Order */
)
{
opus_int n;
opus_int32 x_Q16, y32;
y32 = p[ dd ]; /* Q16 */
x_Q16 = silk_LSHIFT( x, 4 );
if ( opus_likely( 8 == dd ) )
{
y32 = silk_SMLAWW( p[ 7 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 6 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 5 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 4 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 3 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 2 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 1 ], y32, x_Q16 );
y32 = silk_SMLAWW( p[ 0 ], y32, x_Q16 );
}
else
{
for( n = dd - 1; n >= 0; n-- ) {
y32 = silk_SMLAWW( p[ n ], y32, x_Q16 ); /* Q16 */
}
}
return y32;
}
static OPUS_INLINE void silk_A2NLSF_init(
const opus_int32 *a_Q16,
opus_int32 *P,
opus_int32 *Q,
const opus_int dd
)
{
opus_int k;
/* Convert filter coefs to even and odd polynomials */
P[dd] = silk_LSHIFT( 1, 16 );
Q[dd] = silk_LSHIFT( 1, 16 );
for( k = 0; k < dd; k++ ) {
P[ k ] = -a_Q16[ dd - k - 1 ] - a_Q16[ dd + k ]; /* Q16 */
Q[ k ] = -a_Q16[ dd - k - 1 ] + a_Q16[ dd + k ]; /* Q16 */
}
/* Divide out zeros as we have that for even filter orders, */
/* z = 1 is always a root in Q, and */
/* z = -1 is always a root in P */
for( k = dd; k > 0; k-- ) {
P[ k - 1 ] -= P[ k ];
Q[ k - 1 ] += Q[ k ];
}
/* Transform polynomials from cos(n*f) to cos(f)^n */
silk_A2NLSF_trans_poly( P, dd );
silk_A2NLSF_trans_poly( Q, dd );
}
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
void silk_A2NLSF(
opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
const opus_int d /* I Filter order (must be even) */
)
{
opus_int i, k, m, dd, root_ix, ffrac;
opus_int32 xlo, xhi, xmid;
opus_int32 ylo, yhi, ymid, thr;
opus_int32 nom, den;
opus_int32 P[ SILK_MAX_ORDER_LPC / 2 + 1 ];
opus_int32 Q[ SILK_MAX_ORDER_LPC / 2 + 1 ];
opus_int32 *PQ[ 2 ];
opus_int32 *p;
/* Store pointers to array */
PQ[ 0 ] = P;
PQ[ 1 ] = Q;
dd = silk_RSHIFT( d, 1 );
silk_A2NLSF_init( a_Q16, P, Q, dd );
/* Find roots, alternating between P and Q */
p = P; /* Pointer to polynomial */
xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
if( ylo < 0 ) {
/* Set the first NLSF to zero and move on to the next */
NLSF[ 0 ] = 0;
p = Q; /* Pointer to polynomial */
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
root_ix = 1; /* Index of current root */
} else {
root_ix = 0; /* Index of current root */
}
k = 1; /* Loop counter */
i = 0; /* Counter for bandwidth expansions applied */
thr = 0;
while( 1 ) {
/* Evaluate polynomial */
xhi = silk_LSFCosTab_FIX_Q12[ k ]; /* Q12 */
yhi = silk_A2NLSF_eval_poly( p, xhi, dd );
/* Detect zero crossing */
if( ( ylo <= 0 && yhi >= thr ) || ( ylo >= 0 && yhi <= -thr ) ) {
if( yhi == 0 ) {
/* If the root lies exactly at the end of the current */
/* interval, look for the next root in the next interval */
thr = 1;
} else {
thr = 0;
}
/* Binary division */
ffrac = -256;
for( m = 0; m < BIN_DIV_STEPS_A2NLSF_FIX; m++ ) {
/* Evaluate polynomial */
xmid = silk_RSHIFT_ROUND( xlo + xhi, 1 );
ymid = silk_A2NLSF_eval_poly( p, xmid, dd );
/* Detect zero crossing */
if( ( ylo <= 0 && ymid >= 0 ) || ( ylo >= 0 && ymid <= 0 ) ) {
/* Reduce frequency */
xhi = xmid;
yhi = ymid;
} else {
/* Increase frequency */
xlo = xmid;
ylo = ymid;
ffrac = silk_ADD_RSHIFT( ffrac, 128, m );
}
}
/* Interpolate */
if( silk_abs( ylo ) < 65536 ) {
/* Avoid dividing by zero */
den = ylo - yhi;
nom = silk_LSHIFT( ylo, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) + silk_RSHIFT( den, 1 );
if( den != 0 ) {
ffrac += silk_DIV32( nom, den );
}
} else {
/* No risk of dividing by zero because abs(ylo - yhi) >= abs(ylo) >= 65536 */
ffrac += silk_DIV32( ylo, silk_RSHIFT( ylo - yhi, 8 - BIN_DIV_STEPS_A2NLSF_FIX ) );
}
NLSF[ root_ix ] = (opus_int16)silk_min_32( silk_LSHIFT( (opus_int32)k, 8 ) + ffrac, silk_int16_MAX );
silk_assert( NLSF[ root_ix ] >= 0 );
root_ix++; /* Next root */
if( root_ix >= d ) {
/* Found all roots */
break;
}
/* Alternate pointer to polynomial */
p = PQ[ root_ix & 1 ];
/* Evaluate polynomial */
xlo = silk_LSFCosTab_FIX_Q12[ k - 1 ]; /* Q12*/
ylo = silk_LSHIFT( 1 - ( root_ix & 2 ), 12 );
} else {
/* Increment loop counter */
k++;
xlo = xhi;
ylo = yhi;
thr = 0;
if( k > LSF_COS_TAB_SZ_FIX ) {
i++;
if( i > MAX_ITERATIONS_A2NLSF_FIX ) {
/* Set NLSFs to white spectrum and exit */
NLSF[ 0 ] = (opus_int16)silk_DIV32_16( 1 << 15, d + 1 );
for( k = 1; k < d; k++ ) {
NLSF[ k ] = (opus_int16)silk_ADD16( NLSF[ k-1 ], NLSF[ 0 ] );
}
return;
}
/* Error: Apply progressively more bandwidth expansion and run again */
silk_bwexpander_32( a_Q16, d, 65536 - silk_LSHIFT( 1, i ) );
silk_A2NLSF_init( a_Q16, P, Q, dd );
p = P; /* Pointer to polynomial */
xlo = silk_LSFCosTab_FIX_Q12[ 0 ]; /* Q12*/
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
if( ylo < 0 ) {
/* Set the first NLSF to zero and move on to the next */
NLSF[ 0 ] = 0;
p = Q; /* Pointer to polynomial */
ylo = silk_A2NLSF_eval_poly( p, xlo, dd );
root_ix = 1; /* Index of current root */
} else {
root_ix = 0; /* Index of current root */
}
k = 1; /* Reset loop counter */
}
}
}
}

View File

@@ -0,0 +1,135 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
#ifndef SILK_API_H
#define SILK_API_H
#include "control.h"
#include "typedef.h"
#include "errors.h"
#include "../celt/entenc.h"
#include "../celt/entdec.h"
#ifdef __cplusplus
extern "C"
{
#endif
#define SILK_MAX_FRAMES_PER_PACKET 3
/* Struct for TOC (Table of Contents) */
typedef struct {
opus_int VADFlag; /* Voice activity for packet */
opus_int VADFlags[ SILK_MAX_FRAMES_PER_PACKET ]; /* Voice activity for each frame in packet */
opus_int inbandFECFlag; /* Flag indicating if packet contains in-band FEC */
} silk_TOC_struct;
/****************************************/
/* Encoder functions */
/****************************************/
/***********************************************/
/* Get size in bytes of the Silk encoder state */
/***********************************************/
opus_int silk_Get_Encoder_Size( /* O Returns error code */
opus_int *encSizeBytes /* O Number of bytes in SILK encoder state */
);
/*************************/
/* Init or reset encoder */
/*************************/
opus_int silk_InitEncoder( /* O Returns error code */
void *encState, /* I/O State */
int arch, /* I Run-time architecture */
silk_EncControlStruct *encStatus /* O Encoder Status */
);
/**************************/
/* Encode frame with Silk */
/**************************/
/* Note: if prefillFlag is set, the input must contain 10 ms of audio, irrespective of what */
/* encControl->payloadSize_ms is set to */
opus_int silk_Encode( /* O Returns error code */
void *encState, /* I/O State */
silk_EncControlStruct *encControl, /* I Control status */
const opus_int16 *samplesIn, /* I Speech sample input vector */
opus_int nSamplesIn, /* I Number of samples in input vector */
ec_enc *psRangeEnc, /* I/O Compressor data structure */
opus_int32 *nBytesOut, /* I/O Number of bytes in payload (input: Max bytes) */
const opus_int prefillFlag, /* I Flag to indicate prefilling buffers no coding */
int activity /* I Decision of Opus voice activity detector */
);
/****************************************/
/* Decoder functions */
/****************************************/
/***********************************************/
/* Get size in bytes of the Silk decoder state */
/***********************************************/
opus_int silk_Get_Decoder_Size( /* O Returns error code */
opus_int *decSizeBytes /* O Number of bytes in SILK decoder state */
);
/*************************/
/* Init or Reset decoder */
/*************************/
opus_int silk_InitDecoder( /* O Returns error code */
void *decState /* I/O State */
);
/******************/
/* Decode a frame */
/******************/
opus_int silk_Decode( /* O Returns error code */
void* decState, /* I/O State */
silk_DecControlStruct* decControl, /* I/O Control Structure */
opus_int lostFlag, /* I 0: no loss, 1 loss, 2 decode fec */
opus_int newPacketFlag, /* I Indicates first decoder call for this packet */
ec_dec *psRangeDec, /* I/O Compressor data structure */
opus_int16 *samplesOut, /* O Decoded output speech vector */
opus_int32 *nSamplesOut, /* O Number of samples decoded */
int arch /* I Run-time architecture */
);
#if 0
/**************************************/
/* Get table of contents for a packet */
/**************************************/
opus_int silk_get_TOC(
const opus_uint8 *payload, /* I Payload data */
const opus_int nBytesIn, /* I Number of input bytes */
const opus_int nFramesPerPayload, /* I Number of SILK frames per payload */
silk_TOC_struct *Silk_TOC /* O Type of content */
);
#endif
#ifdef __cplusplus
}
#endif
#endif

View File

@@ -0,0 +1,184 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
#include "../celt/stack_alloc.h"
/* Generates excitation for CNG LPC synthesis */
static OPUS_INLINE void silk_CNG_exc(
opus_int32 exc_Q14[], /* O CNG excitation signal Q10 */
opus_int32 exc_buf_Q14[], /* I Random samples buffer Q10 */
opus_int length, /* I Length */
opus_int32 *rand_seed /* I/O Seed to random index generator */
)
{
opus_int32 seed;
opus_int i, idx, exc_mask;
exc_mask = CNG_BUF_MASK_MAX;
while( exc_mask > length ) {
exc_mask = silk_RSHIFT( exc_mask, 1 );
}
seed = *rand_seed;
for( i = 0; i < length; i++ ) {
seed = silk_RAND( seed );
idx = (opus_int)( silk_RSHIFT( seed, 24 ) & exc_mask );
silk_assert( idx >= 0 );
silk_assert( idx <= CNG_BUF_MASK_MAX );
exc_Q14[ i ] = exc_buf_Q14[ idx ];
}
*rand_seed = seed;
}
void silk_CNG_Reset(
silk_decoder_state *psDec /* I/O Decoder state */
)
{
opus_int i, NLSF_step_Q15, NLSF_acc_Q15;
NLSF_step_Q15 = silk_DIV32_16( silk_int16_MAX, psDec->LPC_order + 1 );
NLSF_acc_Q15 = 0;
for( i = 0; i < psDec->LPC_order; i++ ) {
NLSF_acc_Q15 += NLSF_step_Q15;
psDec->sCNG.CNG_smth_NLSF_Q15[ i ] = NLSF_acc_Q15;
}
psDec->sCNG.CNG_smth_Gain_Q16 = 0;
psDec->sCNG.rand_seed = 3176576;
}
/* Updates CNG estimate, and applies the CNG when packet was lost */
void silk_CNG(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O Signal */
opus_int length /* I Length of residual */
)
{
opus_int i, subfr;
opus_int32 LPC_pred_Q10, max_Gain_Q16, gain_Q16, gain_Q10;
opus_int16 A_Q12[ MAX_LPC_ORDER ];
silk_CNG_struct *psCNG = &psDec->sCNG;
SAVE_STACK;
if( psDec->fs_kHz != psCNG->fs_kHz ) {
/* Reset state */
silk_CNG_Reset( psDec );
psCNG->fs_kHz = psDec->fs_kHz;
}
if( psDec->lossCnt == 0 && psDec->prevSignalType == TYPE_NO_VOICE_ACTIVITY ) {
/* Update CNG parameters */
/* Smoothing of LSF's */
for( i = 0; i < psDec->LPC_order; i++ ) {
psCNG->CNG_smth_NLSF_Q15[ i ] += silk_SMULWB( (opus_int32)psDec->prevNLSF_Q15[ i ] - (opus_int32)psCNG->CNG_smth_NLSF_Q15[ i ], CNG_NLSF_SMTH_Q16 );
}
/* Find the subframe with the highest gain */
max_Gain_Q16 = 0;
subfr = 0;
for( i = 0; i < psDec->nb_subfr; i++ ) {
if( psDecCtrl->Gains_Q16[ i ] > max_Gain_Q16 ) {
max_Gain_Q16 = psDecCtrl->Gains_Q16[ i ];
subfr = i;
}
}
/* Update CNG excitation buffer with excitation from this subframe */
silk_memmove( &psCNG->CNG_exc_buf_Q14[ psDec->subfr_length ], psCNG->CNG_exc_buf_Q14, ( psDec->nb_subfr - 1 ) * psDec->subfr_length * sizeof( opus_int32 ) );
silk_memcpy( psCNG->CNG_exc_buf_Q14, &psDec->exc_Q14[ subfr * psDec->subfr_length ], psDec->subfr_length * sizeof( opus_int32 ) );
/* Smooth gains */
for( i = 0; i < psDec->nb_subfr; i++ ) {
psCNG->CNG_smth_Gain_Q16 += silk_SMULWB( psDecCtrl->Gains_Q16[ i ] - psCNG->CNG_smth_Gain_Q16, CNG_GAIN_SMTH_Q16 );
}
}
/* Add CNG when packet is lost or during DTX */
if( psDec->lossCnt ) {
VARDECL( opus_int32, CNG_sig_Q14 );
ALLOC( CNG_sig_Q14, length + MAX_LPC_ORDER, opus_int32 );
/* Generate CNG excitation */
gain_Q16 = silk_SMULWW( psDec->sPLC.randScale_Q14, psDec->sPLC.prevGain_Q16[1] );
if( gain_Q16 >= (1 << 21) || psCNG->CNG_smth_Gain_Q16 > (1 << 23) ) {
gain_Q16 = silk_SMULTT( gain_Q16, gain_Q16 );
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULTT( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 16 );
} else {
gain_Q16 = silk_SMULWW( gain_Q16, gain_Q16 );
gain_Q16 = silk_SUB_LSHIFT32(silk_SMULWW( psCNG->CNG_smth_Gain_Q16, psCNG->CNG_smth_Gain_Q16 ), gain_Q16, 5 );
gain_Q16 = silk_LSHIFT32( silk_SQRT_APPROX( gain_Q16 ), 8 );
}
gain_Q10 = silk_RSHIFT( gain_Q16, 6 );
silk_CNG_exc( CNG_sig_Q14 + MAX_LPC_ORDER, psCNG->CNG_exc_buf_Q14, length, &psCNG->rand_seed );
/* Convert CNG NLSF to filter representation */
silk_NLSF2A( A_Q12, psCNG->CNG_smth_NLSF_Q15, psDec->LPC_order, psDec->arch );
/* Generate CNG signal, by synthesis filtering */
silk_memcpy( CNG_sig_Q14, psCNG->CNG_synth_state, MAX_LPC_ORDER * sizeof( opus_int32 ) );
celt_assert( psDec->LPC_order == 10 || psDec->LPC_order == 16 );
for( i = 0; i < length; i++ ) {
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
if( psDec->LPC_order == 16 ) {
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 11 ], A_Q12[ 10 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 12 ], A_Q12[ 11 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 13 ], A_Q12[ 12 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 14 ], A_Q12[ 13 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 15 ], A_Q12[ 14 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, CNG_sig_Q14[ MAX_LPC_ORDER + i - 16 ], A_Q12[ 15 ] );
}
/* Update states */
CNG_sig_Q14[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( CNG_sig_Q14[ MAX_LPC_ORDER + i ], silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ) );
/* Scale with Gain and add to input signal */
frame[ i ] = (opus_int16)silk_ADD_SAT16( frame[ i ], silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( CNG_sig_Q14[ MAX_LPC_ORDER + i ], gain_Q10 ), 8 ) ) );
}
silk_memcpy( psCNG->CNG_synth_state, &CNG_sig_Q14[ length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
} else {
silk_memset( psCNG->CNG_synth_state, 0, psDec->LPC_order * sizeof( opus_int32 ) );
}
RESTORE_STACK;
}

View File

@@ -0,0 +1,77 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#ifdef FIXED_POINT
#include "fixed/main_FIX.h"
#else
#include "main_FLP.h"
#endif
#include "tuning_parameters.h"
/* High-pass filter with cutoff frequency adaptation based on pitch lag statistics */
void silk_HP_variable_cutoff(
silk_encoder_state_Fxx state_Fxx[] /* I/O Encoder states */
)
{
opus_int quality_Q15;
opus_int32 pitch_freq_Hz_Q16, pitch_freq_log_Q7, delta_freq_Q7;
silk_encoder_state *psEncC1 = &state_Fxx[ 0 ].sCmn;
/* Adaptive cutoff frequency: estimate low end of pitch frequency range */
if( psEncC1->prevSignalType == TYPE_VOICED ) {
/* difference, in log domain */
pitch_freq_Hz_Q16 = silk_DIV32_16( silk_LSHIFT( silk_MUL( psEncC1->fs_kHz, 1000 ), 16 ), psEncC1->prevLag );
pitch_freq_log_Q7 = silk_lin2log( pitch_freq_Hz_Q16 ) - ( 16 << 7 );
/* adjustment based on quality */
quality_Q15 = psEncC1->input_quality_bands_Q15[ 0 ];
pitch_freq_log_Q7 = silk_SMLAWB( pitch_freq_log_Q7, silk_SMULWB( silk_LSHIFT( -quality_Q15, 2 ), quality_Q15 ),
pitch_freq_log_Q7 - ( silk_lin2log( SILK_FIX_CONST( VARIABLE_HP_MIN_CUTOFF_HZ, 16 ) ) - ( 16 << 7 ) ) );
/* delta_freq = pitch_freq_log - psEnc->variable_HP_smth1; */
delta_freq_Q7 = pitch_freq_log_Q7 - silk_RSHIFT( psEncC1->variable_HP_smth1_Q15, 8 );
if( delta_freq_Q7 < 0 ) {
/* less smoothing for decreasing pitch frequency, to track something close to the minimum */
delta_freq_Q7 = silk_MUL( delta_freq_Q7, 3 );
}
/* limit delta, to reduce impact of outliers in pitch estimation */
delta_freq_Q7 = silk_LIMIT_32( delta_freq_Q7, -SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ), SILK_FIX_CONST( VARIABLE_HP_MAX_DELTA_FREQ, 7 ) );
/* update smoother */
psEncC1->variable_HP_smth1_Q15 = silk_SMLAWB( psEncC1->variable_HP_smth1_Q15,
silk_SMULBB( psEncC1->speech_activity_Q8, delta_freq_Q7 ), SILK_FIX_CONST( VARIABLE_HP_SMTH_COEF1, 16 ) );
/* limit frequency range */
psEncC1->variable_HP_smth1_Q15 = silk_LIMIT_32( psEncC1->variable_HP_smth1_Q15,
silk_LSHIFT( silk_lin2log( VARIABLE_HP_MIN_CUTOFF_HZ ), 8 ),
silk_LSHIFT( silk_lin2log( VARIABLE_HP_MAX_CUTOFF_HZ ), 8 ) );
}
}

View File

@@ -0,0 +1,188 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
/*! \file silk_Inlines.h
* \brief silk_Inlines.h defines OPUS_INLINE signal processing functions.
*/
#ifndef SILK_FIX_INLINES_H
#define SILK_FIX_INLINES_H
#ifdef __cplusplus
extern "C"
{
#endif
/* count leading zeros of opus_int64 */
static OPUS_INLINE opus_int32 silk_CLZ64( opus_int64 in )
{
opus_int32 in_upper;
in_upper = (opus_int32)silk_RSHIFT64(in, 32);
if (in_upper == 0) {
/* Search in the lower 32 bits */
return 32 + silk_CLZ32( (opus_int32) in );
} else {
/* Search in the upper 32 bits */
return silk_CLZ32( in_upper );
}
}
/* get number of leading zeros and fractional part (the bits right after the leading one */
static OPUS_INLINE void silk_CLZ_FRAC(
opus_int32 in, /* I input */
opus_int32 *lz, /* O number of leading zeros */
opus_int32 *frac_Q7 /* O the 7 bits right after the leading one */
)
{
opus_int32 lzeros = silk_CLZ32(in);
* lz = lzeros;
* frac_Q7 = silk_ROR32(in, 24 - lzeros) & 0x7f;
}
/* Approximation of square root */
/* Accuracy: < +/- 10% for output values > 15 */
/* < +/- 2.5% for output values > 120 */
static OPUS_INLINE opus_int32 silk_SQRT_APPROX( opus_int32 x )
{
opus_int32 y, lz, frac_Q7;
if( x <= 0 ) {
return 0;
}
silk_CLZ_FRAC(x, &lz, &frac_Q7);
if( lz & 1 ) {
y = 32768;
} else {
y = 46214; /* 46214 = sqrt(2) * 32768 */
}
/* get scaling right */
y >>= silk_RSHIFT(lz, 1);
/* increment using fractional part of input */
y = silk_SMLAWB(y, y, silk_SMULBB(213, frac_Q7));
return y;
}
/* Divide two int32 values and return result as int32 in a given Q-domain */
static OPUS_INLINE opus_int32 silk_DIV32_varQ( /* O returns a good approximation of "(a32 << Qres) / b32" */
const opus_int32 a32, /* I numerator (Q0) */
const opus_int32 b32, /* I denominator (Q0) */
const opus_int Qres /* I Q-domain of result (>= 0) */
)
{
opus_int a_headrm, b_headrm, lshift;
opus_int32 b32_inv, a32_nrm, b32_nrm, result;
silk_assert( b32 != 0 );
silk_assert( Qres >= 0 );
/* Compute number of bits head room and normalize inputs */
a_headrm = silk_CLZ32( silk_abs(a32) ) - 1;
a32_nrm = silk_LSHIFT(a32, a_headrm); /* Q: a_headrm */
b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */
/* Inverse of b32, with 14 bits of precision */
b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
/* First approximation */
result = silk_SMULWB(a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
/* Compute residual by subtracting product of denominator and first approximation */
/* It's OK to overflow because the final value of a32_nrm should always be small */
a32_nrm = silk_SUB32_ovflw(a32_nrm, silk_LSHIFT_ovflw( silk_SMMUL(b32_nrm, result), 3 )); /* Q: a_headrm */
/* Refinement */
result = silk_SMLAWB(result, a32_nrm, b32_inv); /* Q: 29 + a_headrm - b_headrm */
/* Convert to Qres domain */
lshift = 29 + a_headrm - b_headrm - Qres;
if( lshift < 0 ) {
return silk_LSHIFT_SAT32(result, -lshift);
} else {
if( lshift < 32){
return silk_RSHIFT(result, lshift);
} else {
/* Avoid undefined result */
return 0;
}
}
}
/* Invert int32 value and return result as int32 in a given Q-domain */
static OPUS_INLINE opus_int32 silk_INVERSE32_varQ( /* O returns a good approximation of "(1 << Qres) / b32" */
const opus_int32 b32, /* I denominator (Q0) */
const opus_int Qres /* I Q-domain of result (> 0) */
)
{
opus_int b_headrm, lshift;
opus_int32 b32_inv, b32_nrm, err_Q32, result;
silk_assert( b32 != 0 );
silk_assert( Qres > 0 );
/* Compute number of bits head room and normalize input */
b_headrm = silk_CLZ32( silk_abs(b32) ) - 1;
b32_nrm = silk_LSHIFT(b32, b_headrm); /* Q: b_headrm */
/* Inverse of b32, with 14 bits of precision */
b32_inv = silk_DIV32_16( silk_int32_MAX >> 2, silk_RSHIFT(b32_nrm, 16) ); /* Q: 29 + 16 - b_headrm */
/* First approximation */
result = silk_LSHIFT(b32_inv, 16); /* Q: 61 - b_headrm */
/* Compute residual by subtracting product of denominator and first approximation from one */
err_Q32 = silk_LSHIFT( ((opus_int32)1<<29) - silk_SMULWB(b32_nrm, b32_inv), 3 ); /* Q32 */
/* Refinement */
result = silk_SMLAWW(result, err_Q32, b32_inv); /* Q: 61 - b_headrm */
/* Convert to Qres domain */
lshift = 61 - b_headrm - Qres;
if( lshift <= 0 ) {
return silk_LSHIFT_SAT32(result, -lshift);
} else {
if( lshift < 32){
return silk_RSHIFT(result, lshift);
}else{
/* Avoid undefined result */
return 0;
}
}
}
#ifdef __cplusplus
}
#endif
#endif /* SILK_FIX_INLINES_H */

View File

@@ -0,0 +1,111 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "SigProc_FIX.h"
#include "../celt/celt_lpc.h"
/*******************************************/
/* LPC analysis filter */
/* NB! State is kept internally and the */
/* filter always starts with zero state */
/* first d output samples are set to zero */
/*******************************************/
/* OPT: Using celt_fir() for this function should be faster, but it may cause
integer overflows in intermediate values (not final results), which the
current implementation silences by casting to unsigned. Enabling
this should be safe in pretty much all cases, even though it is not technically
C89-compliant. */
#define USE_CELT_FIR 0
void silk_LPC_analysis_filter(
opus_int16 *out, /* O Output signal */
const opus_int16 *in, /* I Input signal */
const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
const opus_int32 len, /* I Signal length */
const opus_int32 d, /* I Filter order */
int arch /* I Run-time architecture */
)
{
opus_int j;
#if defined(FIXED_POINT) && USE_CELT_FIR
opus_int16 num[SILK_MAX_ORDER_LPC];
#else
int ix;
opus_int32 out32_Q12, out32;
const opus_int16 *in_ptr;
#endif
celt_assert( d >= 6 );
celt_assert( (d & 1) == 0 );
celt_assert( d <= len );
#if defined(FIXED_POINT) && USE_CELT_FIR
celt_assert( d <= SILK_MAX_ORDER_LPC );
for ( j = 0; j < d; j++ ) {
num[ j ] = -B[ j ];
}
celt_fir( in + d, num, out + d, len - d, d, arch );
for ( j = 0; j < d; j++ ) {
out[ j ] = 0;
}
#else
(void)arch;
for( ix = d; ix < len; ix++ ) {
in_ptr = &in[ ix - 1 ];
out32_Q12 = silk_SMULBB( in_ptr[ 0 ], B[ 0 ] );
/* Allowing wrap around so that two wraps can cancel each other. The rare
cases where the result wraps around can only be triggered by invalid streams*/
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -1 ], B[ 1 ] );
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -2 ], B[ 2 ] );
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -3 ], B[ 3 ] );
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -4 ], B[ 4 ] );
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -5 ], B[ 5 ] );
for( j = 6; j < d; j += 2 ) {
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j ], B[ j ] );
out32_Q12 = silk_SMLABB_ovflw( out32_Q12, in_ptr[ -j - 1 ], B[ j + 1 ] );
}
/* Subtract prediction */
out32_Q12 = silk_SUB32_ovflw( silk_LSHIFT( (opus_int32)in_ptr[ 1 ], 12 ), out32_Q12 );
/* Scale to Q0 */
out32 = silk_RSHIFT_ROUND( out32_Q12, 12 );
/* Saturate output */
out[ ix ] = (opus_int16)silk_SAT16( out32 );
}
/* Set first d output samples to zero */
silk_memset( out, 0, d * sizeof( opus_int16 ) );
#endif
}

View File

@@ -0,0 +1,81 @@
/***********************************************************************
Copyright (c) 2013, Koen Vos. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "SigProc_FIX.h"
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
void silk_LPC_fit(
opus_int16 *a_QOUT, /* O Output signal */
opus_int32 *a_QIN, /* I/O Input signal */
const opus_int QOUT, /* I Input Q domain */
const opus_int QIN, /* I Input Q domain */
const opus_int d /* I Filter order */
)
{
opus_int i, k, idx = 0;
opus_int32 maxabs, absval, chirp_Q16;
/* Limit the maximum absolute value of the prediction coefficients, so that they'll fit in int16 */
for( i = 0; i < 10; i++ ) {
/* Find maximum absolute value and its index */
maxabs = 0;
for( k = 0; k < d; k++ ) {
absval = silk_abs( a_QIN[k] );
if( absval > maxabs ) {
maxabs = absval;
idx = k;
}
}
maxabs = silk_RSHIFT_ROUND( maxabs, QIN - QOUT );
if( maxabs > silk_int16_MAX ) {
/* Reduce magnitude of prediction coefficients */
maxabs = silk_min( maxabs, 163838 ); /* ( silk_int32_MAX >> 14 ) + silk_int16_MAX = 163838 */
chirp_Q16 = SILK_FIX_CONST( 0.999, 16 ) - silk_DIV32( silk_LSHIFT( maxabs - silk_int16_MAX, 14 ),
silk_RSHIFT32( silk_MUL( maxabs, idx + 1), 2 ) );
silk_bwexpander_32( a_QIN, d, chirp_Q16 );
} else {
break;
}
}
if( i == 10 ) {
/* Reached the last iteration, clip the coefficients */
for( k = 0; k < d; k++ ) {
a_QOUT[ k ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT ) );
a_QIN[ k ] = silk_LSHIFT( (opus_int32)a_QOUT[ k ], QIN - QOUT );
}
} else {
for( k = 0; k < d; k++ ) {
a_QOUT[ k ] = (opus_int16)silk_RSHIFT_ROUND( a_QIN[ k ], QIN - QOUT );
}
}
}

View File

@@ -0,0 +1,141 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "SigProc_FIX.h"
#include "define.h"
#define QA 24
#define A_LIMIT SILK_FIX_CONST( 0.99975, QA )
#define MUL32_FRAC_Q(a32, b32, Q) ((opus_int32)(silk_RSHIFT_ROUND64(silk_SMULL(a32, b32), Q)))
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
static opus_int32 LPC_inverse_pred_gain_QA_c( /* O Returns inverse prediction gain in energy domain, Q30 */
opus_int32 A_QA[ SILK_MAX_ORDER_LPC ], /* I Prediction coefficients */
const opus_int order /* I Prediction order */
)
{
opus_int k, n, mult2Q;
opus_int32 invGain_Q30, rc_Q31, rc_mult1_Q30, rc_mult2, tmp1, tmp2;
invGain_Q30 = SILK_FIX_CONST( 1, 30 );
for( k = order - 1; k > 0; k-- ) {
/* Check for stability */
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
return 0;
}
/* Set RC equal to negated AR coef */
rc_Q31 = -silk_LSHIFT( A_QA[ k ], 31 - QA );
/* rc_mult1_Q30 range: [ 1 : 2^30 ] */
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
silk_assert( rc_mult1_Q30 > ( 1 << 15 ) ); /* reduce A_LIMIT if fails */
silk_assert( rc_mult1_Q30 <= ( 1 << 30 ) );
/* Update inverse gain */
/* invGain_Q30 range: [ 0 : 2^30 ] */
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
silk_assert( invGain_Q30 >= 0 );
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
return 0;
}
/* rc_mult2 range: [ 2^30 : silk_int32_MAX ] */
mult2Q = 32 - silk_CLZ32( silk_abs( rc_mult1_Q30 ) );
rc_mult2 = silk_INVERSE32_varQ( rc_mult1_Q30, mult2Q + 30 );
/* Update AR coefficient */
for( n = 0; n < (k + 1) >> 1; n++ ) {
opus_int64 tmp64;
tmp1 = A_QA[ n ];
tmp2 = A_QA[ k - n - 1 ];
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp1,
MUL32_FRAC_Q( tmp2, rc_Q31, 31 ) ), rc_mult2 ), mult2Q);
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
return 0;
}
A_QA[ n ] = ( opus_int32 )tmp64;
tmp64 = silk_RSHIFT_ROUND64( silk_SMULL( silk_SUB_SAT32(tmp2,
MUL32_FRAC_Q( tmp1, rc_Q31, 31 ) ), rc_mult2), mult2Q);
if( tmp64 > silk_int32_MAX || tmp64 < silk_int32_MIN ) {
return 0;
}
A_QA[ k - n - 1 ] = ( opus_int32 )tmp64;
}
}
/* Check for stability */
if( ( A_QA[ k ] > A_LIMIT ) || ( A_QA[ k ] < -A_LIMIT ) ) {
return 0;
}
/* Set RC equal to negated AR coef */
rc_Q31 = -silk_LSHIFT( A_QA[ 0 ], 31 - QA );
/* Range: [ 1 : 2^30 ] */
rc_mult1_Q30 = silk_SUB32( SILK_FIX_CONST( 1, 30 ), silk_SMMUL( rc_Q31, rc_Q31 ) );
/* Update inverse gain */
/* Range: [ 0 : 2^30 ] */
invGain_Q30 = silk_LSHIFT( silk_SMMUL( invGain_Q30, rc_mult1_Q30 ), 2 );
silk_assert( invGain_Q30 >= 0 );
silk_assert( invGain_Q30 <= ( 1 << 30 ) );
if( invGain_Q30 < SILK_FIX_CONST( 1.0f / MAX_PREDICTION_POWER_GAIN, 30 ) ) {
return 0;
}
return invGain_Q30;
}
/* For input in Q12 domain */
opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */
)
{
opus_int k;
opus_int32 Atmp_QA[ SILK_MAX_ORDER_LPC ];
opus_int32 DC_resp = 0;
/* Increase Q domain of the AR coefficients */
for( k = 0; k < order; k++ ) {
DC_resp += (opus_int32)A_Q12[ k ];
Atmp_QA[ k ] = silk_LSHIFT32( (opus_int32)A_Q12[ k ], QA - 12 );
}
/* If the DC is unstable, we don't even need to do the full calculations */
if( DC_resp >= 4096 ) {
return 0;
}
return LPC_inverse_pred_gain_QA_c( Atmp_QA, order );
}

View File

@@ -0,0 +1,135 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
/*
Elliptic/Cauer filters designed with 0.1 dB passband ripple,
80 dB minimum stopband attenuation, and
[0.95 : 0.15 : 0.35] normalized cut off frequencies.
*/
#include "main.h"
/* Helper function, interpolates the filter taps */
static OPUS_INLINE void silk_LP_interpolate_filter_taps(
opus_int32 B_Q28[ TRANSITION_NB ],
opus_int32 A_Q28[ TRANSITION_NA ],
const opus_int ind,
const opus_int32 fac_Q16
)
{
opus_int nb, na;
if( ind < TRANSITION_INT_NUM - 1 ) {
if( fac_Q16 > 0 ) {
if( fac_Q16 < 32768 ) { /* fac_Q16 is in range of a 16-bit int */
/* Piece-wise linear interpolation of B and A */
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
B_Q28[ nb ] = silk_SMLAWB(
silk_Transition_LP_B_Q28[ ind ][ nb ],
silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
silk_Transition_LP_B_Q28[ ind ][ nb ],
fac_Q16 );
}
for( na = 0; na < TRANSITION_NA; na++ ) {
A_Q28[ na ] = silk_SMLAWB(
silk_Transition_LP_A_Q28[ ind ][ na ],
silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
silk_Transition_LP_A_Q28[ ind ][ na ],
fac_Q16 );
}
} else { /* ( fac_Q16 - ( 1 << 16 ) ) is in range of a 16-bit int */
silk_assert( fac_Q16 - ( 1 << 16 ) == silk_SAT16( fac_Q16 - ( 1 << 16 ) ) );
/* Piece-wise linear interpolation of B and A */
for( nb = 0; nb < TRANSITION_NB; nb++ ) {
B_Q28[ nb ] = silk_SMLAWB(
silk_Transition_LP_B_Q28[ ind + 1 ][ nb ],
silk_Transition_LP_B_Q28[ ind + 1 ][ nb ] -
silk_Transition_LP_B_Q28[ ind ][ nb ],
fac_Q16 - ( (opus_int32)1 << 16 ) );
}
for( na = 0; na < TRANSITION_NA; na++ ) {
A_Q28[ na ] = silk_SMLAWB(
silk_Transition_LP_A_Q28[ ind + 1 ][ na ],
silk_Transition_LP_A_Q28[ ind + 1 ][ na ] -
silk_Transition_LP_A_Q28[ ind ][ na ],
fac_Q16 - ( (opus_int32)1 << 16 ) );
}
}
} else {
silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ ind ], TRANSITION_NB * sizeof( opus_int32 ) );
silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ ind ], TRANSITION_NA * sizeof( opus_int32 ) );
}
} else {
silk_memcpy( B_Q28, silk_Transition_LP_B_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NB * sizeof( opus_int32 ) );
silk_memcpy( A_Q28, silk_Transition_LP_A_Q28[ TRANSITION_INT_NUM - 1 ], TRANSITION_NA * sizeof( opus_int32 ) );
}
}
/* Low-pass filter with variable cutoff frequency based on */
/* piece-wise linear interpolation between elliptic filters */
/* Start by setting psEncC->mode <> 0; */
/* Deactivate by setting psEncC->mode = 0; */
void silk_LP_variable_cutoff(
silk_LP_state *psLP, /* I/O LP filter state */
opus_int16 *frame, /* I/O Low-pass filtered output signal */
const opus_int frame_length /* I Frame length */
)
{
opus_int32 B_Q28[ TRANSITION_NB ], A_Q28[ TRANSITION_NA ], fac_Q16 = 0;
opus_int ind = 0;
silk_assert( psLP->transition_frame_no >= 0 && psLP->transition_frame_no <= TRANSITION_FRAMES );
/* Run filter if needed */
if( psLP->mode != 0 ) {
/* Calculate index and interpolation factor for interpolation */
#if( TRANSITION_INT_STEPS == 64 )
fac_Q16 = silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 - 6 );
#else
fac_Q16 = silk_DIV32_16( silk_LSHIFT( TRANSITION_FRAMES - psLP->transition_frame_no, 16 ), TRANSITION_FRAMES );
#endif
ind = silk_RSHIFT( fac_Q16, 16 );
fac_Q16 -= silk_LSHIFT( ind, 16 );
silk_assert( ind >= 0 );
silk_assert( ind < TRANSITION_INT_NUM );
/* Interpolate filter coefficients */
silk_LP_interpolate_filter_taps( B_Q28, A_Q28, ind, fac_Q16 );
/* Update transition frame number for next frame */
psLP->transition_frame_no = silk_LIMIT( psLP->transition_frame_no + psLP->mode, 0, TRANSITION_FRAMES );
/* ARMA low-pass filtering */
silk_assert( TRANSITION_NB == 3 && TRANSITION_NA == 2 );
silk_biquad_alt_stride1( frame, B_Q28, A_Q28, psLP->In_LP_State, frame, frame_length);
}
}

View File

@@ -0,0 +1,710 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
#ifndef SIGPROCFIX_API_MACROCOUNT_H
#define SIGPROCFIX_API_MACROCOUNT_H
#include <stdio.h>
#ifdef silk_MACRO_COUNT
#define varDefine opus_int64 ops_count = 0;
extern opus_int64 ops_count;
static OPUS_INLINE opus_int64 silk_SaveCount(){
return(ops_count);
}
static OPUS_INLINE opus_int64 silk_SaveResetCount(){
opus_int64 ret;
ret = ops_count;
ops_count = 0;
return(ret);
}
static OPUS_INLINE silk_PrintCount(){
printf("ops_count = %d \n ", (opus_int32)ops_count);
}
#undef silk_MUL
static OPUS_INLINE opus_int32 silk_MUL(opus_int32 a32, opus_int32 b32){
opus_int32 ret;
ops_count += 4;
ret = a32 * b32;
return ret;
}
#undef silk_MUL_uint
static OPUS_INLINE opus_uint32 silk_MUL_uint(opus_uint32 a32, opus_uint32 b32){
opus_uint32 ret;
ops_count += 4;
ret = a32 * b32;
return ret;
}
#undef silk_MLA
static OPUS_INLINE opus_int32 silk_MLA(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
ops_count += 4;
ret = a32 + b32 * c32;
return ret;
}
#undef silk_MLA_uint
static OPUS_INLINE opus_int32 silk_MLA_uint(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32){
opus_uint32 ret;
ops_count += 4;
ret = a32 + b32 * c32;
return ret;
}
#undef silk_SMULWB
static OPUS_INLINE opus_int32 silk_SMULWB(opus_int32 a32, opus_int32 b32){
opus_int32 ret;
ops_count += 5;
ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
return ret;
}
#undef silk_SMLAWB
static OPUS_INLINE opus_int32 silk_SMLAWB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
ops_count += 5;
ret = ((a32) + ((((b32) >> 16) * (opus_int32)((opus_int16)(c32))) + ((((b32) & 0x0000FFFF) * (opus_int32)((opus_int16)(c32))) >> 16)));
return ret;
}
#undef silk_SMULWT
static OPUS_INLINE opus_int32 silk_SMULWT(opus_int32 a32, opus_int32 b32){
opus_int32 ret;
ops_count += 4;
ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
return ret;
}
#undef silk_SMLAWT
static OPUS_INLINE opus_int32 silk_SMLAWT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
ops_count += 4;
ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
return ret;
}
#undef silk_SMULBB
static OPUS_INLINE opus_int32 silk_SMULBB(opus_int32 a32, opus_int32 b32){
opus_int32 ret;
ops_count += 1;
ret = (opus_int32)((opus_int16)a32) * (opus_int32)((opus_int16)b32);
return ret;
}
#undef silk_SMLABB
static OPUS_INLINE opus_int32 silk_SMLABB(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
ops_count += 1;
ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
return ret;
}
#undef silk_SMULBT
static OPUS_INLINE opus_int32 silk_SMULBT(opus_int32 a32, opus_int32 b32 ){
opus_int32 ret;
ops_count += 4;
ret = ((opus_int32)((opus_int16)a32)) * (b32 >> 16);
return ret;
}
#undef silk_SMLABT
static OPUS_INLINE opus_int32 silk_SMLABT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
ops_count += 1;
ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
return ret;
}
#undef silk_SMULTT
static OPUS_INLINE opus_int32 silk_SMULTT(opus_int32 a32, opus_int32 b32){
opus_int32 ret;
ops_count += 1;
ret = (a32 >> 16) * (b32 >> 16);
return ret;
}
#undef silk_SMLATT
static OPUS_INLINE opus_int32 silk_SMLATT(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
ops_count += 1;
ret = a32 + (b32 >> 16) * (c32 >> 16);
return ret;
}
/* multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode)*/
#undef silk_MLA_ovflw
#define silk_MLA_ovflw silk_MLA
#undef silk_SMLABB_ovflw
#define silk_SMLABB_ovflw silk_SMLABB
#undef silk_SMLABT_ovflw
#define silk_SMLABT_ovflw silk_SMLABT
#undef silk_SMLATT_ovflw
#define silk_SMLATT_ovflw silk_SMLATT
#undef silk_SMLAWB_ovflw
#define silk_SMLAWB_ovflw silk_SMLAWB
#undef silk_SMLAWT_ovflw
#define silk_SMLAWT_ovflw silk_SMLAWT
#undef silk_SMULL
static OPUS_INLINE opus_int64 silk_SMULL(opus_int32 a32, opus_int32 b32){
opus_int64 ret;
ops_count += 8;
ret = ((opus_int64)(a32) * /*(opus_int64)*/(b32));
return ret;
}
#undef silk_SMLAL
static OPUS_INLINE opus_int64 silk_SMLAL(opus_int64 a64, opus_int32 b32, opus_int32 c32){
opus_int64 ret;
ops_count += 8;
ret = a64 + ((opus_int64)(b32) * /*(opus_int64)*/(c32));
return ret;
}
#undef silk_SMLALBB
static OPUS_INLINE opus_int64 silk_SMLALBB(opus_int64 a64, opus_int16 b16, opus_int16 c16){
opus_int64 ret;
ops_count += 4;
ret = a64 + ((opus_int64)(b16) * /*(opus_int64)*/(c16));
return ret;
}
#undef SigProcFIX_CLZ16
static OPUS_INLINE opus_int32 SigProcFIX_CLZ16(opus_int16 in16)
{
opus_int32 out32 = 0;
ops_count += 10;
if( in16 == 0 ) {
return 16;
}
/* test nibbles */
if( in16 & 0xFF00 ) {
if( in16 & 0xF000 ) {
in16 >>= 12;
} else {
out32 += 4;
in16 >>= 8;
}
} else {
if( in16 & 0xFFF0 ) {
out32 += 8;
in16 >>= 4;
} else {
out32 += 12;
}
}
/* test bits and return */
if( in16 & 0xC ) {
if( in16 & 0x8 )
return out32 + 0;
else
return out32 + 1;
} else {
if( in16 & 0xE )
return out32 + 2;
else
return out32 + 3;
}
}
#undef SigProcFIX_CLZ32
static OPUS_INLINE opus_int32 SigProcFIX_CLZ32(opus_int32 in32)
{
/* test highest 16 bits and convert to opus_int16 */
ops_count += 2;
if( in32 & 0xFFFF0000 ) {
return SigProcFIX_CLZ16((opus_int16)(in32 >> 16));
} else {
return SigProcFIX_CLZ16((opus_int16)in32) + 16;
}
}
#undef silk_DIV32
static OPUS_INLINE opus_int32 silk_DIV32(opus_int32 a32, opus_int32 b32){
ops_count += 64;
return a32 / b32;
}
#undef silk_DIV32_16
static OPUS_INLINE opus_int32 silk_DIV32_16(opus_int32 a32, opus_int32 b32){
ops_count += 32;
return a32 / b32;
}
#undef silk_SAT8
static OPUS_INLINE opus_int8 silk_SAT8(opus_int64 a){
opus_int8 tmp;
ops_count += 1;
tmp = (opus_int8)((a) > silk_int8_MAX ? silk_int8_MAX : \
((a) < silk_int8_MIN ? silk_int8_MIN : (a)));
return(tmp);
}
#undef silk_SAT16
static OPUS_INLINE opus_int16 silk_SAT16(opus_int64 a){
opus_int16 tmp;
ops_count += 1;
tmp = (opus_int16)((a) > silk_int16_MAX ? silk_int16_MAX : \
((a) < silk_int16_MIN ? silk_int16_MIN : (a)));
return(tmp);
}
#undef silk_SAT32
static OPUS_INLINE opus_int32 silk_SAT32(opus_int64 a){
opus_int32 tmp;
ops_count += 1;
tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : \
((a) < silk_int32_MIN ? silk_int32_MIN : (a)));
return(tmp);
}
#undef silk_POS_SAT32
static OPUS_INLINE opus_int32 silk_POS_SAT32(opus_int64 a){
opus_int32 tmp;
ops_count += 1;
tmp = (opus_int32)((a) > silk_int32_MAX ? silk_int32_MAX : (a));
return(tmp);
}
#undef silk_ADD_POS_SAT8
static OPUS_INLINE opus_int8 silk_ADD_POS_SAT8(opus_int64 a, opus_int64 b){
opus_int8 tmp;
ops_count += 1;
tmp = (opus_int8)((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)));
return(tmp);
}
#undef silk_ADD_POS_SAT16
static OPUS_INLINE opus_int16 silk_ADD_POS_SAT16(opus_int64 a, opus_int64 b){
opus_int16 tmp;
ops_count += 1;
tmp = (opus_int16)((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)));
return(tmp);
}
#undef silk_ADD_POS_SAT32
static OPUS_INLINE opus_int32 silk_ADD_POS_SAT32(opus_int64 a, opus_int64 b){
opus_int32 tmp;
ops_count += 1;
tmp = (opus_int32)((((a)+(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)));
return(tmp);
}
#undef silk_LSHIFT8
static OPUS_INLINE opus_int8 silk_LSHIFT8(opus_int8 a, opus_int32 shift){
opus_int8 ret;
ops_count += 1;
ret = a << shift;
return ret;
}
#undef silk_LSHIFT16
static OPUS_INLINE opus_int16 silk_LSHIFT16(opus_int16 a, opus_int32 shift){
opus_int16 ret;
ops_count += 1;
ret = a << shift;
return ret;
}
#undef silk_LSHIFT32
static OPUS_INLINE opus_int32 silk_LSHIFT32(opus_int32 a, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a << shift;
return ret;
}
#undef silk_LSHIFT64
static OPUS_INLINE opus_int64 silk_LSHIFT64(opus_int64 a, opus_int shift){
ops_count += 1;
return a << shift;
}
#undef silk_LSHIFT_ovflw
static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw(opus_int32 a, opus_int32 shift){
ops_count += 1;
return a << shift;
}
#undef silk_LSHIFT_uint
static OPUS_INLINE opus_uint32 silk_LSHIFT_uint(opus_uint32 a, opus_int32 shift){
opus_uint32 ret;
ops_count += 1;
ret = a << shift;
return ret;
}
#undef silk_RSHIFT8
static OPUS_INLINE opus_int8 silk_RSHIFT8(opus_int8 a, opus_int32 shift){
ops_count += 1;
return a >> shift;
}
#undef silk_RSHIFT16
static OPUS_INLINE opus_int16 silk_RSHIFT16(opus_int16 a, opus_int32 shift){
ops_count += 1;
return a >> shift;
}
#undef silk_RSHIFT32
static OPUS_INLINE opus_int32 silk_RSHIFT32(opus_int32 a, opus_int32 shift){
ops_count += 1;
return a >> shift;
}
#undef silk_RSHIFT64
static OPUS_INLINE opus_int64 silk_RSHIFT64(opus_int64 a, opus_int64 shift){
ops_count += 1;
return a >> shift;
}
#undef silk_RSHIFT_uint
static OPUS_INLINE opus_uint32 silk_RSHIFT_uint(opus_uint32 a, opus_int32 shift){
ops_count += 1;
return a >> shift;
}
#undef silk_ADD_LSHIFT
static OPUS_INLINE opus_int32 silk_ADD_LSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a + (b << shift);
return ret; /* shift >= 0*/
}
#undef silk_ADD_LSHIFT32
static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a + (b << shift);
return ret; /* shift >= 0*/
}
#undef silk_ADD_LSHIFT_uint
static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
opus_uint32 ret;
ops_count += 1;
ret = a + (b << shift);
return ret; /* shift >= 0*/
}
#undef silk_ADD_RSHIFT
static OPUS_INLINE opus_int32 silk_ADD_RSHIFT(opus_int32 a, opus_int32 b, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a + (b >> shift);
return ret; /* shift > 0*/
}
#undef silk_ADD_RSHIFT32
static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a + (b >> shift);
return ret; /* shift > 0*/
}
#undef silk_ADD_RSHIFT_uint
static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint(opus_uint32 a, opus_uint32 b, opus_int32 shift){
opus_uint32 ret;
ops_count += 1;
ret = a + (b >> shift);
return ret; /* shift > 0*/
}
#undef silk_SUB_LSHIFT32
static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a - (b << shift);
return ret; /* shift >= 0*/
}
#undef silk_SUB_RSHIFT32
static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32(opus_int32 a, opus_int32 b, opus_int32 shift){
opus_int32 ret;
ops_count += 1;
ret = a - (b >> shift);
return ret; /* shift > 0*/
}
#undef silk_RSHIFT_ROUND
static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND(opus_int32 a, opus_int32 shift){
opus_int32 ret;
ops_count += 3;
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
return ret;
}
#undef silk_RSHIFT_ROUND64
static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64(opus_int64 a, opus_int32 shift){
opus_int64 ret;
ops_count += 6;
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
return ret;
}
#undef silk_abs_int64
static OPUS_INLINE opus_int64 silk_abs_int64(opus_int64 a){
ops_count += 1;
return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN*/
}
#undef silk_abs_int32
static OPUS_INLINE opus_int32 silk_abs_int32(opus_int32 a){
ops_count += 1;
return silk_abs(a);
}
#undef silk_min
static silk_min(a, b){
ops_count += 1;
return (((a) < (b)) ? (a) : (b));
}
#undef silk_max
static silk_max(a, b){
ops_count += 1;
return (((a) > (b)) ? (a) : (b));
}
#undef silk_sign
static silk_sign(a){
ops_count += 1;
return ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ));
}
#undef silk_ADD16
static OPUS_INLINE opus_int16 silk_ADD16(opus_int16 a, opus_int16 b){
opus_int16 ret;
ops_count += 1;
ret = a + b;
return ret;
}
#undef silk_ADD32
static OPUS_INLINE opus_int32 silk_ADD32(opus_int32 a, opus_int32 b){
opus_int32 ret;
ops_count += 1;
ret = a + b;
return ret;
}
#undef silk_ADD64
static OPUS_INLINE opus_int64 silk_ADD64(opus_int64 a, opus_int64 b){
opus_int64 ret;
ops_count += 2;
ret = a + b;
return ret;
}
#undef silk_SUB16
static OPUS_INLINE opus_int16 silk_SUB16(opus_int16 a, opus_int16 b){
opus_int16 ret;
ops_count += 1;
ret = a - b;
return ret;
}
#undef silk_SUB32
static OPUS_INLINE opus_int32 silk_SUB32(opus_int32 a, opus_int32 b){
opus_int32 ret;
ops_count += 1;
ret = a - b;
return ret;
}
#undef silk_SUB64
static OPUS_INLINE opus_int64 silk_SUB64(opus_int64 a, opus_int64 b){
opus_int64 ret;
ops_count += 2;
ret = a - b;
return ret;
}
#undef silk_ADD_SAT16
static OPUS_INLINE opus_int16 silk_ADD_SAT16( opus_int16 a16, opus_int16 b16 ) {
opus_int16 res;
/* Nb will be counted in AKP_add32 and silk_SAT16*/
res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
return res;
}
#undef silk_ADD_SAT32
static OPUS_INLINE opus_int32 silk_ADD_SAT32(opus_int32 a32, opus_int32 b32){
opus_int32 res;
ops_count += 1;
res = ((((a32) + (b32)) & 0x80000000) == 0 ? \
((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
return res;
}
#undef silk_ADD_SAT64
static OPUS_INLINE opus_int64 silk_ADD_SAT64( opus_int64 a64, opus_int64 b64 ) {
opus_int64 res;
ops_count += 1;
res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \
((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
return res;
}
#undef silk_SUB_SAT16
static OPUS_INLINE opus_int16 silk_SUB_SAT16( opus_int16 a16, opus_int16 b16 ) {
opus_int16 res;
silk_assert(0);
/* Nb will be counted in sub-macros*/
res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
return res;
}
#undef silk_SUB_SAT32
static OPUS_INLINE opus_int32 silk_SUB_SAT32( opus_int32 a32, opus_int32 b32 ) {
opus_int32 res;
ops_count += 1;
res = ((((a32)-(b32)) & 0x80000000) == 0 ? \
(( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
return res;
}
#undef silk_SUB_SAT64
static OPUS_INLINE opus_int64 silk_SUB_SAT64( opus_int64 a64, opus_int64 b64 ) {
opus_int64 res;
ops_count += 1;
res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \
(( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
return res;
}
#undef silk_SMULWW
static OPUS_INLINE opus_int32 silk_SMULWW(opus_int32 a32, opus_int32 b32){
opus_int32 ret;
/* Nb will be counted in sub-macros*/
ret = silk_MLA(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16));
return ret;
}
#undef silk_SMLAWW
static OPUS_INLINE opus_int32 silk_SMLAWW(opus_int32 a32, opus_int32 b32, opus_int32 c32){
opus_int32 ret;
/* Nb will be counted in sub-macros*/
ret = silk_MLA(silk_SMLAWB((a32), (b32), (c32)), (b32), silk_RSHIFT_ROUND((c32), 16));
return ret;
}
#undef silk_min_int
static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
{
ops_count += 1;
return (((a) < (b)) ? (a) : (b));
}
#undef silk_min_16
static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
{
ops_count += 1;
return (((a) < (b)) ? (a) : (b));
}
#undef silk_min_32
static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
{
ops_count += 1;
return (((a) < (b)) ? (a) : (b));
}
#undef silk_min_64
static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
{
ops_count += 1;
return (((a) < (b)) ? (a) : (b));
}
/* silk_min() versions with typecast in the function call */
#undef silk_max_int
static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
{
ops_count += 1;
return (((a) > (b)) ? (a) : (b));
}
#undef silk_max_16
static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
{
ops_count += 1;
return (((a) > (b)) ? (a) : (b));
}
#undef silk_max_32
static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
{
ops_count += 1;
return (((a) > (b)) ? (a) : (b));
}
#undef silk_max_64
static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
{
ops_count += 1;
return (((a) > (b)) ? (a) : (b));
}
#undef silk_LIMIT_int
static OPUS_INLINE opus_int silk_LIMIT_int(opus_int a, opus_int limit1, opus_int limit2)
{
opus_int ret;
ops_count += 6;
ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
return(ret);
}
#undef silk_LIMIT_16
static OPUS_INLINE opus_int16 silk_LIMIT_16(opus_int16 a, opus_int16 limit1, opus_int16 limit2)
{
opus_int16 ret;
ops_count += 6;
ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
return(ret);
}
#undef silk_LIMIT_32
static OPUS_INLINE opus_int32 silk_LIMIT_32(opus_int32 a, opus_int32 limit1, opus_int32 limit2)
{
opus_int32 ret;
ops_count += 6;
ret = ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))));
return(ret);
}
#else
#define varDefine
#define silk_SaveCount()
#endif
#endif

View File

@@ -0,0 +1,951 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
Copyright (C) 2012 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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
#ifndef MACRO_DEBUG_H
#define MACRO_DEBUG_H
/* Redefine macro functions with extensive assertion in DEBUG mode.
As functions can't be undefined, this file can't work with SigProcFIX_MacroCount.h */
#if ( defined (FIXED_DEBUG) || ( 0 && defined (_DEBUG) ) ) && !defined (silk_MACRO_COUNT)
#undef silk_ADD16
#define silk_ADD16(a,b) silk_ADD16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_ADD16_(opus_int16 a, opus_int16 b, char *file, int line){
opus_int16 ret;
ret = a + b;
if ( ret != silk_ADD_SAT16( a, b ) )
{
fprintf (stderr, "silk_ADD16(%d, %d) in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_ADD32
#define silk_ADD32(a,b) silk_ADD32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_ADD32_(opus_int32 a, opus_int32 b, char *file, int line){
opus_int32 ret;
ret = a + b;
if ( ret != silk_ADD_SAT32( a, b ) )
{
fprintf (stderr, "silk_ADD32(%d, %d) in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_ADD64
#define silk_ADD64(a,b) silk_ADD64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_ADD64_(opus_int64 a, opus_int64 b, char *file, int line){
opus_int64 ret;
ret = a + b;
if ( ret != silk_ADD_SAT64( a, b ) )
{
fprintf (stderr, "silk_ADD64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SUB16
#define silk_SUB16(a,b) silk_SUB16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_SUB16_(opus_int16 a, opus_int16 b, char *file, int line){
opus_int16 ret;
ret = a - b;
if ( ret != silk_SUB_SAT16( a, b ) )
{
fprintf (stderr, "silk_SUB16(%d, %d) in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SUB32
#define silk_SUB32(a,b) silk_SUB32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SUB32_(opus_int32 a, opus_int32 b, char *file, int line){
opus_int32 ret;
ret = a - b;
if ( ret != silk_SUB_SAT32( a, b ) )
{
fprintf (stderr, "silk_SUB32(%d, %d) in %s: line %d\n", a, b, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SUB64
#define silk_SUB64(a,b) silk_SUB64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_SUB64_(opus_int64 a, opus_int64 b, char *file, int line){
opus_int64 ret;
ret = a - b;
if ( ret != silk_SUB_SAT64( a, b ) )
{
fprintf (stderr, "silk_SUB64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)b, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_ADD_SAT16
#define silk_ADD_SAT16(a,b) silk_ADD_SAT16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_ADD_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line) {
opus_int16 res;
res = (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a16), (b16) ) );
if ( res != silk_SAT16( (opus_int32)a16 + (opus_int32)b16 ) )
{
fprintf (stderr, "silk_ADD_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return res;
}
#undef silk_ADD_SAT32
#define silk_ADD_SAT32(a,b) silk_ADD_SAT32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_ADD_SAT32_(opus_int32 a32, opus_int32 b32, char *file, int line){
opus_int32 res;
res = ((((opus_uint32)(a32) + (opus_uint32)(b32)) & 0x80000000) == 0 ? \
((((a32) & (b32)) & 0x80000000) != 0 ? silk_int32_MIN : (a32)+(b32)) : \
((((a32) | (b32)) & 0x80000000) == 0 ? silk_int32_MAX : (a32)+(b32)) );
if ( res != silk_SAT32( (opus_int64)a32 + (opus_int64)b32 ) )
{
fprintf (stderr, "silk_ADD_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return res;
}
#undef silk_ADD_SAT64
#define silk_ADD_SAT64(a,b) silk_ADD_SAT64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_ADD_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line) {
opus_int64 res;
int fail = 0;
res = ((((a64) + (b64)) & 0x8000000000000000LL) == 0 ? \
((((a64) & (b64)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a64)+(b64)) : \
((((a64) | (b64)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a64)+(b64)) );
if( res != a64 + b64 ) {
/* Check that we saturated to the correct extreme value */
if ( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ) )
{
fail = 1;
}
} else {
/* Saturation not necessary */
fail = res != a64 + b64;
}
if ( fail )
{
fprintf (stderr, "silk_ADD_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return res;
}
#undef silk_SUB_SAT16
#define silk_SUB_SAT16(a,b) silk_SUB_SAT16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_SUB_SAT16_( opus_int16 a16, opus_int16 b16, char *file, int line ) {
opus_int16 res;
res = (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a16), (b16) ) );
if ( res != silk_SAT16( (opus_int32)a16 - (opus_int32)b16 ) )
{
fprintf (stderr, "silk_SUB_SAT16(%d, %d) in %s: line %d\n", a16, b16, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return res;
}
#undef silk_SUB_SAT32
#define silk_SUB_SAT32(a,b) silk_SUB_SAT32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SUB_SAT32_( opus_int32 a32, opus_int32 b32, char *file, int line ) {
opus_int32 res;
res = ((((opus_uint32)(a32)-(opus_uint32)(b32)) & 0x80000000) == 0 ? \
(( (a32) & ((b32)^0x80000000) & 0x80000000) ? silk_int32_MIN : (a32)-(b32)) : \
((((a32)^0x80000000) & (b32) & 0x80000000) ? silk_int32_MAX : (a32)-(b32)) );
if ( res != silk_SAT32( (opus_int64)a32 - (opus_int64)b32 ) )
{
fprintf (stderr, "silk_SUB_SAT32(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return res;
}
#undef silk_SUB_SAT64
#define silk_SUB_SAT64(a,b) silk_SUB_SAT64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_SUB_SAT64_( opus_int64 a64, opus_int64 b64, char *file, int line ) {
opus_int64 res;
int fail = 0;
res = ((((a64)-(b64)) & 0x8000000000000000LL) == 0 ? \
(( (a64) & ((b64)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a64)-(b64)) : \
((((a64)^0x8000000000000000LL) & (b64) & 0x8000000000000000LL) ? silk_int64_MAX : (a64)-(b64)) );
if( res != a64 - b64 ) {
/* Check that we saturated to the correct extreme value */
if( !(( res == silk_int64_MAX && ( ( a64 >> 1 ) + ( b64 >> 1 ) > ( silk_int64_MAX >> 3 ) ) ) ||
( res == silk_int64_MIN && ( ( a64 >> 1 ) + ( b64 >> 1 ) < ( silk_int64_MIN >> 3 ) ) ) ))
{
fail = 1;
}
} else {
/* Saturation not necessary */
fail = res != a64 - b64;
}
if ( fail )
{
fprintf (stderr, "silk_SUB_SAT64(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return res;
}
#undef silk_MUL
#define silk_MUL(a,b) silk_MUL_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_MUL_(opus_int32 a32, opus_int32 b32, char *file, int line){
opus_int32 ret;
opus_int64 ret64;
ret = a32 * b32;
ret64 = (opus_int64)a32 * (opus_int64)b32;
if ( (opus_int64)ret != ret64 )
{
fprintf (stderr, "silk_MUL(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_MUL_uint
#define silk_MUL_uint(a,b) silk_MUL_uint_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_uint32 silk_MUL_uint_(opus_uint32 a32, opus_uint32 b32, char *file, int line){
opus_uint32 ret;
ret = a32 * b32;
if ( (opus_uint64)ret != (opus_uint64)a32 * (opus_uint64)b32 )
{
fprintf (stderr, "silk_MUL_uint(%u, %u) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_MLA
#define silk_MLA(a,b,c) silk_MLA_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_MLA_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret;
ret = a32 + b32 * c32;
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
{
fprintf (stderr, "silk_MLA(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_MLA_uint
#define silk_MLA_uint(a,b,c) silk_MLA_uint_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_MLA_uint_(opus_uint32 a32, opus_uint32 b32, opus_uint32 c32, char *file, int line){
opus_uint32 ret;
ret = a32 + b32 * c32;
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int64)c32 )
{
fprintf (stderr, "silk_MLA_uint(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMULWB
#define silk_SMULWB(a,b) silk_SMULWB_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMULWB_(opus_int32 a32, opus_int32 b32, char *file, int line){
opus_int32 ret;
ret = (a32 >> 16) * (opus_int32)((opus_int16)b32) + (((a32 & 0x0000FFFF) * (opus_int32)((opus_int16)b32)) >> 16);
if ( (opus_int64)ret != ((opus_int64)a32 * (opus_int16)b32) >> 16 )
{
fprintf (stderr, "silk_SMULWB(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMLAWB
#define silk_SMLAWB(a,b,c) silk_SMLAWB_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMLAWB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret;
ret = silk_ADD32( a32, silk_SMULWB( b32, c32 ) );
if ( silk_ADD32( a32, silk_SMULWB( b32, c32 ) ) != silk_ADD_SAT32( a32, silk_SMULWB( b32, c32 ) ) )
{
fprintf (stderr, "silk_SMLAWB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMULWT
#define silk_SMULWT(a,b) silk_SMULWT_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMULWT_(opus_int32 a32, opus_int32 b32, char *file, int line){
opus_int32 ret;
ret = (a32 >> 16) * (b32 >> 16) + (((a32 & 0x0000FFFF) * (b32 >> 16)) >> 16);
if ( (opus_int64)ret != ((opus_int64)a32 * (b32 >> 16)) >> 16 )
{
fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMLAWT
#define silk_SMLAWT(a,b,c) silk_SMLAWT_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMLAWT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret;
ret = a32 + ((b32 >> 16) * (c32 >> 16)) + (((b32 & 0x0000FFFF) * ((c32 >> 16)) >> 16));
if ( (opus_int64)ret != (opus_int64)a32 + (((opus_int64)b32 * (c32 >> 16)) >> 16) )
{
fprintf (stderr, "silk_SMLAWT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMULL
#define silk_SMULL(a,b) silk_SMULL_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_SMULL_(opus_int64 a64, opus_int64 b64, char *file, int line){
opus_int64 ret64;
int fail = 0;
ret64 = a64 * b64;
if( b64 != 0 ) {
fail = a64 != (ret64 / b64);
} else if( a64 != 0 ) {
fail = b64 != (ret64 / a64);
}
if ( fail )
{
fprintf (stderr, "silk_SMULL(%lld, %lld) in %s: line %d\n", (long long)a64, (long long)b64, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret64;
}
/* no checking needed for silk_SMULBB */
#undef silk_SMLABB
#define silk_SMLABB(a,b,c) silk_SMLABB_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMLABB_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret;
ret = a32 + (opus_int32)((opus_int16)b32) * (opus_int32)((opus_int16)c32);
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (opus_int16)c32 )
{
fprintf (stderr, "silk_SMLABB(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
/* no checking needed for silk_SMULBT */
#undef silk_SMLABT
#define silk_SMLABT(a,b,c) silk_SMLABT_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMLABT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret;
ret = a32 + ((opus_int32)((opus_int16)b32)) * (c32 >> 16);
if ( (opus_int64)ret != (opus_int64)a32 + (opus_int64)b32 * (c32 >> 16) )
{
fprintf (stderr, "silk_SMLABT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
/* no checking needed for silk_SMULTT */
#undef silk_SMLATT
#define silk_SMLATT(a,b,c) silk_SMLATT_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMLATT_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret;
ret = a32 + (b32 >> 16) * (c32 >> 16);
if ( (opus_int64)ret != (opus_int64)a32 + (b32 >> 16) * (c32 >> 16) )
{
fprintf (stderr, "silk_SMLATT(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMULWW
#define silk_SMULWW(a,b) silk_SMULWW_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMULWW_(opus_int32 a32, opus_int32 b32, char *file, int line){
opus_int32 ret, tmp1, tmp2;
opus_int64 ret64;
int fail = 0;
ret = silk_SMULWB( a32, b32 );
tmp1 = silk_RSHIFT_ROUND( b32, 16 );
tmp2 = silk_MUL( a32, tmp1 );
fail |= (opus_int64)tmp2 != (opus_int64) a32 * (opus_int64) tmp1;
tmp1 = ret;
ret = silk_ADD32( tmp1, tmp2 );
fail |= silk_ADD32( tmp1, tmp2 ) != silk_ADD_SAT32( tmp1, tmp2 );
ret64 = silk_RSHIFT64( silk_SMULL( a32, b32 ), 16 );
fail |= (opus_int64)ret != ret64;
if ( fail )
{
fprintf (stderr, "silk_SMULWT(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_SMLAWW
#define silk_SMLAWW(a,b,c) silk_SMLAWW_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SMLAWW_(opus_int32 a32, opus_int32 b32, opus_int32 c32, char *file, int line){
opus_int32 ret, tmp;
tmp = silk_SMULWW( b32, c32 );
ret = silk_ADD32( a32, tmp );
if ( ret != silk_ADD_SAT32( a32, tmp ) )
{
fprintf (stderr, "silk_SMLAWW(%d, %d, %d) in %s: line %d\n", a32, b32, c32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
#undef silk_MLA_ovflw
#define silk_MLA_ovflw(a32, b32, c32) ((a32) + ((b32) * (c32)))
#undef silk_SMLABB_ovflw
#define silk_SMLABB_ovflw(a32, b32, c32) ((a32) + ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32)))
/* no checking needed for silk_SMULL
no checking needed for silk_SMLAL
no checking needed for silk_SMLALBB
no checking needed for SigProcFIX_CLZ16
no checking needed for SigProcFIX_CLZ32*/
#undef silk_DIV32
#define silk_DIV32(a,b) silk_DIV32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_DIV32_(opus_int32 a32, opus_int32 b32, char *file, int line){
if ( b32 == 0 )
{
fprintf (stderr, "silk_DIV32(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a32 / b32;
}
#undef silk_DIV32_16
#define silk_DIV32_16(a,b) silk_DIV32_16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_DIV32_16_(opus_int32 a32, opus_int32 b32, char *file, int line){
int fail = 0;
fail |= b32 == 0;
fail |= b32 > silk_int16_MAX;
fail |= b32 < silk_int16_MIN;
if ( fail )
{
fprintf (stderr, "silk_DIV32_16(%d, %d) in %s: line %d\n", a32, b32, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a32 / b32;
}
/* no checking needed for silk_SAT8
no checking needed for silk_SAT16
no checking needed for silk_SAT32
no checking needed for silk_POS_SAT32
no checking needed for silk_ADD_POS_SAT8
no checking needed for silk_ADD_POS_SAT16
no checking needed for silk_ADD_POS_SAT32 */
#undef silk_LSHIFT8
#define silk_LSHIFT8(a,b) silk_LSHIFT8_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int8 silk_LSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
opus_int8 ret;
int fail = 0;
ret = a << shift;
fail |= shift < 0;
fail |= shift >= 8;
fail |= (opus_int64)ret != ((opus_int64)a) << shift;
if ( fail )
{
fprintf (stderr, "silk_LSHIFT8(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_LSHIFT16
#define silk_LSHIFT16(a,b) silk_LSHIFT16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_LSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
opus_int16 ret;
int fail = 0;
ret = a << shift;
fail |= shift < 0;
fail |= shift >= 16;
fail |= (opus_int64)ret != ((opus_int64)a) << shift;
if ( fail )
{
fprintf (stderr, "silk_LSHIFT16(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_LSHIFT32
#define silk_LSHIFT32(a,b) silk_LSHIFT32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_LSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
opus_int32 ret;
int fail = 0;
ret = a << shift;
fail |= shift < 0;
fail |= shift >= 32;
fail |= (opus_int64)ret != ((opus_int64)a) << shift;
if ( fail )
{
fprintf (stderr, "silk_LSHIFT32(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_LSHIFT64
#define silk_LSHIFT64(a,b) silk_LSHIFT64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_LSHIFT64_(opus_int64 a, opus_int shift, char *file, int line){
opus_int64 ret;
int fail = 0;
ret = a << shift;
fail |= shift < 0;
fail |= shift >= 64;
fail |= (ret>>shift) != ((opus_int64)a);
if ( fail )
{
fprintf (stderr, "silk_LSHIFT64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_LSHIFT_ovflw
#define silk_LSHIFT_ovflw(a,b) silk_LSHIFT_ovflw_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_LSHIFT_ovflw_(opus_int32 a, opus_int32 shift, char *file, int line){
if ( (shift < 0) || (shift >= 32) ) /* no check for overflow */
{
fprintf (stderr, "silk_LSHIFT_ovflw(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a << shift;
}
#undef silk_LSHIFT_uint
#define silk_LSHIFT_uint(a,b) silk_LSHIFT_uint_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_uint32 silk_LSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
opus_uint32 ret;
ret = a << shift;
if ( (shift < 0) || ((opus_int64)ret != ((opus_int64)a) << shift))
{
fprintf (stderr, "silk_LSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_RSHIFT8
#define silk_RSHITF8(a,b) silk_RSHIFT8_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int8 silk_RSHIFT8_(opus_int8 a, opus_int32 shift, char *file, int line){
if ( (shift < 0) || (shift>=8) )
{
fprintf (stderr, "silk_RSHITF8(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a >> shift;
}
#undef silk_RSHIFT16
#define silk_RSHITF16(a,b) silk_RSHIFT16_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_RSHIFT16_(opus_int16 a, opus_int32 shift, char *file, int line){
if ( (shift < 0) || (shift>=16) )
{
fprintf (stderr, "silk_RSHITF16(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a >> shift;
}
#undef silk_RSHIFT32
#define silk_RSHIFT32(a,b) silk_RSHIFT32_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_RSHIFT32_(opus_int32 a, opus_int32 shift, char *file, int line){
if ( (shift < 0) || (shift>=32) )
{
fprintf (stderr, "silk_RSHITF32(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a >> shift;
}
#undef silk_RSHIFT64
#define silk_RSHIFT64(a,b) silk_RSHIFT64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_RSHIFT64_(opus_int64 a, opus_int64 shift, char *file, int line){
if ( (shift < 0) || (shift>=64) )
{
fprintf (stderr, "silk_RSHITF64(%lld, %lld) in %s: line %d\n", (long long)a, (long long)shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a >> shift;
}
#undef silk_RSHIFT_uint
#define silk_RSHIFT_uint(a,b) silk_RSHIFT_uint_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_uint32 silk_RSHIFT_uint_(opus_uint32 a, opus_int32 shift, char *file, int line){
if ( (shift < 0) || (shift>32) )
{
fprintf (stderr, "silk_RSHIFT_uint(%u, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return a >> shift;
}
#undef silk_ADD_LSHIFT
#define silk_ADD_LSHIFT(a,b,c) silk_ADD_LSHIFT_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE int silk_ADD_LSHIFT_(int a, int b, int shift, char *file, int line){
opus_int16 ret;
ret = a + (b << shift);
if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
{
fprintf (stderr, "silk_ADD_LSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift >= 0 */
}
#undef silk_ADD_LSHIFT32
#define silk_ADD_LSHIFT32(a,b,c) silk_ADD_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_ADD_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
opus_int32 ret;
ret = a + (b << shift);
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
{
fprintf (stderr, "silk_ADD_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift >= 0 */
}
#undef silk_ADD_LSHIFT_uint
#define silk_ADD_LSHIFT_uint(a,b,c) silk_ADD_LSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_uint32 silk_ADD_LSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
opus_uint32 ret;
ret = a + (b << shift);
if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) << shift)) )
{
fprintf (stderr, "silk_ADD_LSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift >= 0 */
}
#undef silk_ADD_RSHIFT
#define silk_ADD_RSHIFT(a,b,c) silk_ADD_RSHIFT_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE int silk_ADD_RSHIFT_(int a, int b, int shift, char *file, int line){
opus_int16 ret;
ret = a + (b >> shift);
if ( (shift < 0) || (shift>15) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
{
fprintf (stderr, "silk_ADD_RSHIFT(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift > 0 */
}
#undef silk_ADD_RSHIFT32
#define silk_ADD_RSHIFT32(a,b,c) silk_ADD_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_ADD_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
opus_int32 ret;
ret = a + (b >> shift);
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
{
fprintf (stderr, "silk_ADD_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift > 0 */
}
#undef silk_ADD_RSHIFT_uint
#define silk_ADD_RSHIFT_uint(a,b,c) silk_ADD_RSHIFT_uint_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_uint32 silk_ADD_RSHIFT_uint_(opus_uint32 a, opus_uint32 b, opus_int32 shift, char *file, int line){
opus_uint32 ret;
ret = a + (b >> shift);
if ( (shift < 0) || (shift>32) || ((opus_int64)ret != (opus_int64)a + (((opus_int64)b) >> shift)) )
{
fprintf (stderr, "silk_ADD_RSHIFT_uint(%u, %u, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift > 0 */
}
#undef silk_SUB_LSHIFT32
#define silk_SUB_LSHIFT32(a,b,c) silk_SUB_LSHIFT32_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SUB_LSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
opus_int32 ret;
ret = a - (b << shift);
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) << shift)) )
{
fprintf (stderr, "silk_SUB_LSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift >= 0 */
}
#undef silk_SUB_RSHIFT32
#define silk_SUB_RSHIFT32(a,b,c) silk_SUB_RSHIFT32_((a), (b), (c), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_SUB_RSHIFT32_(opus_int32 a, opus_int32 b, opus_int32 shift, char *file, int line){
opus_int32 ret;
ret = a - (b >> shift);
if ( (shift < 0) || (shift>31) || ((opus_int64)ret != (opus_int64)a - (((opus_int64)b) >> shift)) )
{
fprintf (stderr, "silk_SUB_RSHIFT32(%d, %d, %d) in %s: line %d\n", a, b, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret; /* shift > 0 */
}
#undef silk_RSHIFT_ROUND
#define silk_RSHIFT_ROUND(a,b) silk_RSHIFT_ROUND_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_RSHIFT_ROUND_(opus_int32 a, opus_int32 shift, char *file, int line){
opus_int32 ret;
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
/* the marco definition can't handle a shift of zero */
if ( (shift <= 0) || (shift>31) || ((opus_int64)ret != ((opus_int64)a + ((opus_int64)1 << (shift - 1))) >> shift) )
{
fprintf (stderr, "silk_RSHIFT_ROUND(%d, %d) in %s: line %d\n", a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return ret;
}
#undef silk_RSHIFT_ROUND64
#define silk_RSHIFT_ROUND64(a,b) silk_RSHIFT_ROUND64_((a), (b), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_RSHIFT_ROUND64_(opus_int64 a, opus_int32 shift, char *file, int line){
opus_int64 ret;
/* the marco definition can't handle a shift of zero */
if ( (shift <= 0) || (shift>=64) )
{
fprintf (stderr, "silk_RSHIFT_ROUND64(%lld, %d) in %s: line %d\n", (long long)a, shift, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
ret = shift == 1 ? (a >> 1) + (a & 1) : ((a >> (shift - 1)) + 1) >> 1;
return ret;
}
/* silk_abs is used on floats also, so doesn't work... */
/*#undef silk_abs
static OPUS_INLINE opus_int32 silk_abs(opus_int32 a){
silk_assert(a != 0x80000000);
return (((a) > 0) ? (a) : -(a)); // Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN
}*/
#undef silk_abs_int64
#define silk_abs_int64(a) silk_abs_int64_((a), __FILE__, __LINE__)
static OPUS_INLINE opus_int64 silk_abs_int64_(opus_int64 a, char *file, int line){
if ( a == silk_int64_MIN )
{
fprintf (stderr, "silk_abs_int64(%lld) in %s: line %d\n", (long long)a, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return (((a) > 0) ? (a) : -(a)); /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
}
#undef silk_abs_int32
#define silk_abs_int32(a) silk_abs_int32_((a), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_abs_int32_(opus_int32 a, char *file, int line){
if ( a == silk_int32_MIN )
{
fprintf (stderr, "silk_abs_int32(%d) in %s: line %d\n", a, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return silk_abs(a);
}
#undef silk_CHECK_FIT8
#define silk_CHECK_FIT8(a) silk_CHECK_FIT8_((a), __FILE__, __LINE__)
static OPUS_INLINE opus_int8 silk_CHECK_FIT8_( opus_int64 a, char *file, int line ){
opus_int8 ret;
ret = (opus_int8)a;
if ( (opus_int64)ret != a )
{
fprintf (stderr, "silk_CHECK_FIT8(%lld) in %s: line %d\n", (long long)a, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return( ret );
}
#undef silk_CHECK_FIT16
#define silk_CHECK_FIT16(a) silk_CHECK_FIT16_((a), __FILE__, __LINE__)
static OPUS_INLINE opus_int16 silk_CHECK_FIT16_( opus_int64 a, char *file, int line ){
opus_int16 ret;
ret = (opus_int16)a;
if ( (opus_int64)ret != a )
{
fprintf (stderr, "silk_CHECK_FIT16(%lld) in %s: line %d\n", (long long)a, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return( ret );
}
#undef silk_CHECK_FIT32
#define silk_CHECK_FIT32(a) silk_CHECK_FIT32_((a), __FILE__, __LINE__)
static OPUS_INLINE opus_int32 silk_CHECK_FIT32_( opus_int64 a, char *file, int line ){
opus_int32 ret;
ret = (opus_int32)a;
if ( (opus_int64)ret != a )
{
fprintf (stderr, "silk_CHECK_FIT32(%lld) in %s: line %d\n", (long long)a, file, line);
#ifdef FIXED_DEBUG_ASSERT
silk_assert( 0 );
#endif
}
return( ret );
}
/* no checking for silk_NSHIFT_MUL_32_32
no checking for silk_NSHIFT_MUL_16_16
no checking needed for silk_min
no checking needed for silk_max
no checking needed for silk_sign
*/
#endif
#endif /* MACRO_DEBUG_H */

View File

@@ -0,0 +1,146 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
/* conversion between prediction filter coefficients and LSFs */
/* order should be even */
/* a piecewise linear approximation maps LSF <-> cos(LSF) */
/* therefore the result is not accurate LSFs, but the two */
/* functions are accurate inverses of each other */
#include "SigProc_FIX.h"
#include "tables.h"
#define QA 16
/* helper function for NLSF2A(..) */
static OPUS_INLINE void silk_NLSF2A_find_poly(
opus_int32 *out, /* O intermediate polynomial, QA [dd+1] */
const opus_int32 *cLSF, /* I vector of interleaved 2*cos(LSFs), QA [d] */
opus_int dd /* I polynomial order (= 1/2 * filter order) */
)
{
opus_int k, n;
opus_int32 ftmp;
out[0] = silk_LSHIFT( 1, QA );
out[1] = -cLSF[0];
for( k = 1; k < dd; k++ ) {
ftmp = cLSF[2*k]; /* QA*/
out[k+1] = silk_LSHIFT( out[k-1], 1 ) - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[k] ), QA );
for( n = k; n > 1; n-- ) {
out[n] += out[n-2] - (opus_int32)silk_RSHIFT_ROUND64( silk_SMULL( ftmp, out[n-1] ), QA );
}
out[1] -= ftmp;
}
}
/* compute whitening filter coefficients from normalized line spectral frequencies */
void silk_NLSF2A(
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
const opus_int d, /* I filter order (should be even) */
int arch /* I Run-time architecture */
)
{
/* This ordering was found to maximize quality. It improves numerical accuracy of
silk_NLSF2A_find_poly() compared to "standard" ordering. */
static const unsigned char ordering16[16] = {
0, 15, 8, 7, 4, 11, 12, 3, 2, 13, 10, 5, 6, 9, 14, 1
};
static const unsigned char ordering10[10] = {
0, 9, 6, 3, 4, 5, 8, 1, 2, 7
};
const unsigned char *ordering;
opus_int k, i, dd;
opus_int32 *cos_LSF_QA = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC );
opus_int32 *P = (opus_int32*)malloc(sizeof(opus_int32) * (SILK_MAX_ORDER_LPC / 2 + 1));
opus_int32 *Q= (opus_int32*)malloc(sizeof(opus_int32) * (SILK_MAX_ORDER_LPC / 2 + 1));
opus_int32 Ptmp, Qtmp, f_int, f_frac, cos_val, delta;
opus_int32 *a32_QA1 = (opus_int32*)malloc(sizeof(opus_int32) * SILK_MAX_ORDER_LPC );
silk_assert( LSF_COS_TAB_SZ_FIX == 128 );
celt_assert( d==10 || d==16 );
/* convert LSFs to 2*cos(LSF), using piecewise linear curve from table */
ordering = d == 16 ? ordering16 : ordering10;
for( k = 0; k < d; k++ ) {
silk_assert( NLSF[k] >= 0 );
/* f_int on a scale 0-127 (rounded down) */
f_int = silk_RSHIFT( NLSF[k], 15 - 7 );
/* f_frac, range: 0..255 */
f_frac = NLSF[k] - silk_LSHIFT( f_int, 15 - 7 );
silk_assert(f_int >= 0);
silk_assert(f_int < LSF_COS_TAB_SZ_FIX );
/* Read start and end value from table */
cos_val = silk_LSFCosTab_FIX_Q12[ f_int ]; /* Q12 */
delta = silk_LSFCosTab_FIX_Q12[ f_int + 1 ] - cos_val; /* Q12, with a range of 0..200 */
/* Linear interpolation */
cos_LSF_QA[ordering[k]] = silk_RSHIFT_ROUND( silk_LSHIFT( cos_val, 8 ) + silk_MUL( delta, f_frac ), 20 - QA ); /* QA */
}
dd = silk_RSHIFT( d, 1 );
/* generate even and odd polynomials using convolution */
silk_NLSF2A_find_poly( P, &cos_LSF_QA[ 0 ], dd );
silk_NLSF2A_find_poly( Q, &cos_LSF_QA[ 1 ], dd );
/* convert even and odd polynomials to opus_int32 Q12 filter coefs */
for( k = 0; k < dd; k++ ) {
Ptmp = P[ k+1 ] + P[ k ];
Qtmp = Q[ k+1 ] - Q[ k ];
/* the Ptmp and Qtmp values at this stage need to fit in int32 */
a32_QA1[ k ] = -Qtmp - Ptmp; /* QA+1 */
a32_QA1[ d-k-1 ] = Qtmp - Ptmp; /* QA+1 */
}
/* Convert int32 coefficients to Q12 int16 coefs */
silk_LPC_fit( a_Q12, a32_QA1, 12, QA + 1, d );
for( i = 0; silk_LPC_inverse_pred_gain( a_Q12, d, arch ) == 0 && i < MAX_LPC_STABILIZE_ITERATIONS; i++ ) {
/* Prediction coefficients are (too close to) unstable; apply bandwidth expansion */
/* on the unscaled coefficients, convert to Q12 and measure again */
silk_bwexpander_32( a32_QA1, d, 65536 - silk_LSHIFT( 2, i ) );
for( k = 0; k < d; k++ ) {
a_Q12[ k ] = (opus_int16)silk_RSHIFT_ROUND( a32_QA1[ k ], QA + 1 - 12 ); /* QA+1 -> Q12 */
}
}
free(cos_LSF_QA);
free(P);
free(Q);
free(a32_QA1);
}

View File

@@ -0,0 +1,76 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
/* Compute quantization errors for an LPC_order element input vector for a VQ codebook */
void silk_NLSF_VQ(
opus_int32 err_Q24[], /* O Quantization errors [K] */
const opus_int16 in_Q15[], /* I Input vectors to be quantized [LPC_order] */
const opus_uint8 pCB_Q8[], /* I Codebook vectors [K*LPC_order] */
const opus_int16 pWght_Q9[], /* I Codebook weights [K*LPC_order] */
const opus_int K, /* I Number of codebook vectors */
const opus_int LPC_order /* I Number of LPCs */
)
{
opus_int i, m;
opus_int32 diff_Q15, diffw_Q24, sum_error_Q24, pred_Q24;
const opus_int16 *w_Q9_ptr;
const opus_uint8 *cb_Q8_ptr;
celt_assert( ( LPC_order & 1 ) == 0 );
/* Loop over codebook */
cb_Q8_ptr = pCB_Q8;
w_Q9_ptr = pWght_Q9;
for( i = 0; i < K; i++ ) {
sum_error_Q24 = 0;
pred_Q24 = 0;
for( m = LPC_order-2; m >= 0; m -= 2 ) {
/* Compute weighted absolute predictive quantization error for index m + 1 */
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m + 1 ], (opus_int32)cb_Q8_ptr[ m + 1 ], 7 ); /* range: [ -32767 : 32767 ]*/
diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m + 1 ] );
sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
pred_Q24 = diffw_Q24;
/* Compute weighted absolute predictive quantization error for index m */
diff_Q15 = silk_SUB_LSHIFT32( in_Q15[ m ], (opus_int32)cb_Q8_ptr[ m ], 7 ); /* range: [ -32767 : 32767 ]*/
diffw_Q24 = silk_SMULBB( diff_Q15, w_Q9_ptr[ m ] );
sum_error_Q24 = silk_ADD32( sum_error_Q24, silk_abs( silk_SUB_RSHIFT32( diffw_Q24, pred_Q24, 1 ) ) );
pred_Q24 = diffw_Q24;
silk_assert( sum_error_Q24 >= 0 );
}
err_Q24[ i ] = sum_error_Q24;
cb_Q8_ptr += LPC_order;
w_Q9_ptr += LPC_order;
}
}

View File

@@ -0,0 +1,80 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "define.h"
#include "SigProc_FIX.h"
/*
R. Laroia, N. Phamdo and N. Farvardin, "Robust and Efficient Quantization of Speech LSP
Parameters Using Structured Vector Quantization", Proc. IEEE Int. Conf. Acoust., Speech,
Signal Processing, pp. 641-644, 1991.
*/
/* Laroia low complexity NLSF weights */
void silk_NLSF_VQ_weights_laroia(
opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */
const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */
const opus_int D /* I Input vector dimension (even) */
)
{
opus_int k;
opus_int32 tmp1_int, tmp2_int;
celt_assert( D > 0 );
celt_assert( ( D & 1 ) == 0 );
/* First value */
tmp1_int = silk_max_int( pNLSF_Q15[ 0 ], 1 );
tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
tmp2_int = silk_max_int( pNLSF_Q15[ 1 ] - pNLSF_Q15[ 0 ], 1 );
tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
pNLSFW_Q_OUT[ 0 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
silk_assert( pNLSFW_Q_OUT[ 0 ] > 0 );
/* Main loop */
for( k = 1; k < D - 1; k += 2 ) {
tmp1_int = silk_max_int( pNLSF_Q15[ k + 1 ] - pNLSF_Q15[ k ], 1 );
tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
pNLSFW_Q_OUT[ k ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
silk_assert( pNLSFW_Q_OUT[ k ] > 0 );
tmp2_int = silk_max_int( pNLSF_Q15[ k + 2 ] - pNLSF_Q15[ k + 1 ], 1 );
tmp2_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp2_int );
pNLSFW_Q_OUT[ k + 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
silk_assert( pNLSFW_Q_OUT[ k + 1 ] > 0 );
}
/* Last value */
tmp1_int = silk_max_int( ( 1 << 15 ) - pNLSF_Q15[ D - 1 ], 1 );
tmp1_int = silk_DIV32_16( (opus_int32)1 << ( 15 + NLSF_W_Q ), tmp1_int );
pNLSFW_Q_OUT[ D - 1 ] = (opus_int16)silk_min_int( tmp1_int + tmp2_int, silk_int16_MAX );
silk_assert( pNLSFW_Q_OUT[ D - 1 ] > 0 );
}

View File

@@ -0,0 +1,93 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
/* Predictive dequantizer for NLSF residuals */
static OPUS_INLINE void silk_NLSF_residual_dequant( /* O Returns RD value in Q30 */
opus_int16 x_Q10[], /* O Output [ order ] */
const opus_int8 indices[], /* I Quantization indices [ order ] */
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
const opus_int quant_step_size_Q16, /* I Quantization step size */
const opus_int16 order /* I Number of input values */
)
{
opus_int i, out_Q10, pred_Q10;
out_Q10 = 0;
for( i = order-1; i >= 0; i-- ) {
pred_Q10 = silk_RSHIFT( silk_SMULBB( out_Q10, (opus_int16)pred_coef_Q8[ i ] ), 8 );
out_Q10 = silk_LSHIFT( indices[ i ], 10 );
if( out_Q10 > 0 ) {
out_Q10 = silk_SUB16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( out_Q10 < 0 ) {
out_Q10 = silk_ADD16( out_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
}
out_Q10 = silk_SMLAWB( pred_Q10, (opus_int32)out_Q10, quant_step_size_Q16 );
x_Q10[ i ] = out_Q10;
}
}
/***********************/
/* NLSF vector decoder */
/***********************/
void silk_NLSF_decode(
opus_int16 *pNLSF_Q15, /* O Quantized NLSF vector [ LPC_ORDER ] */
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
const silk_NLSF_CB_struct *psNLSF_CB /* I Codebook object */
)
{
opus_int i;
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
opus_int16 res_Q10[ MAX_LPC_ORDER ];
opus_int32 NLSF_Q15_tmp;
const opus_uint8 *pCB_element;
const opus_int16 *pCB_Wght_Q9;
/* Unpack entropy table indices and predictor for current CB1 index */
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, NLSFIndices[ 0 ] );
/* Predictive residual dequantizer */
silk_NLSF_residual_dequant( res_Q10, &NLSFIndices[ 1 ], pred_Q8, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->order );
/* Apply inverse square-rooted weights to first stage and add to output */
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ NLSFIndices[ 0 ] * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) {
NLSF_Q15_tmp = silk_ADD_LSHIFT32( silk_DIV32_16( silk_LSHIFT( (opus_int32)res_Q10[ i ], 14 ), pCB_Wght_Q9[ i ] ), (opus_int16)pCB_element[ i ], 7 );
pNLSF_Q15[ i ] = (opus_int16)silk_LIMIT( NLSF_Q15_tmp, 0, 32767 );
}
/* NLSF stabilization */
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
}

View File

@@ -0,0 +1,215 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
/* Delayed-decision quantizer for NLSF residuals */
opus_int32 silk_NLSF_del_dec_quant( /* O Returns RD value in Q25 */
opus_int8 indices[], /* O Quantization indices [ order ] */
const opus_int16 x_Q10[], /* I Input [ order ] */
const opus_int16 w_Q5[], /* I Weights [ order ] */
const opus_uint8 pred_coef_Q8[], /* I Backward predictor coefs [ order ] */
const opus_int16 ec_ix[], /* I Indices to entropy coding tables [ order ] */
const opus_uint8 ec_rates_Q5[], /* I Rates [] */
const opus_int quant_step_size_Q16, /* I Quantization step size */
const opus_int16 inv_quant_step_size_Q6, /* I Inverse quantization step size */
const opus_int32 mu_Q20, /* I R/D tradeoff */
const opus_int16 order /* I Number of input values */
)
{
opus_int i, j, nStates, ind_tmp, ind_min_max, ind_max_min, in_Q10, res_Q10;
opus_int pred_Q10, diff_Q10, rate0_Q5, rate1_Q5;
opus_int16 out0_Q10, out1_Q10;
opus_int32 RD_tmp_Q25, min_Q25, min_max_Q25, max_min_Q25;
opus_int ind_sort[ NLSF_QUANT_DEL_DEC_STATES ];
opus_int8 ind[ NLSF_QUANT_DEL_DEC_STATES ][ MAX_LPC_ORDER ];
opus_int16 prev_out_Q10[ 2 * NLSF_QUANT_DEL_DEC_STATES ];
opus_int32 RD_Q25[ 2 * NLSF_QUANT_DEL_DEC_STATES ];
opus_int32 RD_min_Q25[ NLSF_QUANT_DEL_DEC_STATES ];
opus_int32 RD_max_Q25[ NLSF_QUANT_DEL_DEC_STATES ];
const opus_uint8 *rates_Q5;
opus_int out0_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT];
opus_int out1_Q10_table[2 * NLSF_QUANT_MAX_AMPLITUDE_EXT];
for (i = -NLSF_QUANT_MAX_AMPLITUDE_EXT; i <= NLSF_QUANT_MAX_AMPLITUDE_EXT-1; i++)
{
out0_Q10 = silk_LSHIFT( i, 10 );
out1_Q10 = silk_ADD16( out0_Q10, 1024 );
if( i > 0 ) {
out0_Q10 = silk_SUB16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( i == 0 ) {
out1_Q10 = silk_SUB16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else if( i == -1 ) {
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
} else {
out0_Q10 = silk_ADD16( out0_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
out1_Q10 = silk_ADD16( out1_Q10, SILK_FIX_CONST( NLSF_QUANT_LEVEL_ADJ, 10 ) );
}
out0_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out0_Q10, quant_step_size_Q16 ), 16 );
out1_Q10_table[ i + NLSF_QUANT_MAX_AMPLITUDE_EXT ] = silk_RSHIFT( silk_SMULBB( out1_Q10, quant_step_size_Q16 ), 16 );
}
silk_assert( (NLSF_QUANT_DEL_DEC_STATES & (NLSF_QUANT_DEL_DEC_STATES-1)) == 0 ); /* must be power of two */
nStates = 1;
RD_Q25[ 0 ] = 0;
prev_out_Q10[ 0 ] = 0;
for( i = order - 1; i >= 0; i-- ) {
rates_Q5 = &ec_rates_Q5[ ec_ix[ i ] ];
in_Q10 = x_Q10[ i ];
for( j = 0; j < nStates; j++ ) {
pred_Q10 = silk_RSHIFT( silk_SMULBB( (opus_int16)pred_coef_Q8[ i ], prev_out_Q10[ j ] ), 8 );
res_Q10 = silk_SUB16( in_Q10, pred_Q10 );
ind_tmp = silk_RSHIFT( silk_SMULBB( inv_quant_step_size_Q6, res_Q10 ), 16 );
ind_tmp = silk_LIMIT( ind_tmp, -NLSF_QUANT_MAX_AMPLITUDE_EXT, NLSF_QUANT_MAX_AMPLITUDE_EXT-1 );
ind[ j ][ i ] = (opus_int8)ind_tmp;
/* compute outputs for ind_tmp and ind_tmp + 1 */
out0_Q10 = out0_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ];
out1_Q10 = out1_Q10_table[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE_EXT ];
out0_Q10 = silk_ADD16( out0_Q10, pred_Q10 );
out1_Q10 = silk_ADD16( out1_Q10, pred_Q10 );
prev_out_Q10[ j ] = out0_Q10;
prev_out_Q10[ j + nStates ] = out1_Q10;
/* compute RD for ind_tmp and ind_tmp + 1 */
if( ind_tmp + 1 >= NLSF_QUANT_MAX_AMPLITUDE ) {
if( ind_tmp + 1 == NLSF_QUANT_MAX_AMPLITUDE ) {
rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ];
rate1_Q5 = 280;
} else {
rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, 43, ind_tmp );
rate1_Q5 = silk_ADD16( rate0_Q5, 43 );
}
} else if( ind_tmp <= -NLSF_QUANT_MAX_AMPLITUDE ) {
if( ind_tmp == -NLSF_QUANT_MAX_AMPLITUDE ) {
rate0_Q5 = 280;
rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ];
} else {
rate0_Q5 = silk_SMLABB( 280 - 43 * NLSF_QUANT_MAX_AMPLITUDE, -43, ind_tmp );
rate1_Q5 = silk_SUB16( rate0_Q5, 43 );
}
} else {
rate0_Q5 = rates_Q5[ ind_tmp + NLSF_QUANT_MAX_AMPLITUDE ];
rate1_Q5 = rates_Q5[ ind_tmp + 1 + NLSF_QUANT_MAX_AMPLITUDE ];
}
RD_tmp_Q25 = RD_Q25[ j ];
diff_Q10 = silk_SUB16( in_Q10, out0_Q10 );
RD_Q25[ j ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate0_Q5 );
diff_Q10 = silk_SUB16( in_Q10, out1_Q10 );
RD_Q25[ j + nStates ] = silk_SMLABB( silk_MLA( RD_tmp_Q25, silk_SMULBB( diff_Q10, diff_Q10 ), w_Q5[ i ] ), mu_Q20, rate1_Q5 );
}
if( nStates <= NLSF_QUANT_DEL_DEC_STATES/2 ) {
/* double number of states and copy */
for( j = 0; j < nStates; j++ ) {
ind[ j + nStates ][ i ] = ind[ j ][ i ] + 1;
}
nStates = silk_LSHIFT( nStates, 1 );
for( j = nStates; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
ind[ j ][ i ] = ind[ j - nStates ][ i ];
}
} else {
/* sort lower and upper half of RD_Q25, pairwise */
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
if( RD_Q25[ j ] > RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] ) {
RD_max_Q25[ j ] = RD_Q25[ j ];
RD_min_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ];
RD_Q25[ j ] = RD_min_Q25[ j ];
RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ] = RD_max_Q25[ j ];
/* swap prev_out values */
out0_Q10 = prev_out_Q10[ j ];
prev_out_Q10[ j ] = prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ];
prev_out_Q10[ j + NLSF_QUANT_DEL_DEC_STATES ] = out0_Q10;
ind_sort[ j ] = j + NLSF_QUANT_DEL_DEC_STATES;
} else {
RD_min_Q25[ j ] = RD_Q25[ j ];
RD_max_Q25[ j ] = RD_Q25[ j + NLSF_QUANT_DEL_DEC_STATES ];
ind_sort[ j ] = j;
}
}
/* compare the highest RD values of the winning half with the lowest one in the losing half, and copy if necessary */
/* afterwards ind_sort[] will contain the indices of the NLSF_QUANT_DEL_DEC_STATES winning RD values */
while( 1 ) {
min_max_Q25 = silk_int32_MAX;
max_min_Q25 = 0;
ind_min_max = 0;
ind_max_min = 0;
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
if( min_max_Q25 > RD_max_Q25[ j ] ) {
min_max_Q25 = RD_max_Q25[ j ];
ind_min_max = j;
}
if( max_min_Q25 < RD_min_Q25[ j ] ) {
max_min_Q25 = RD_min_Q25[ j ];
ind_max_min = j;
}
}
if( min_max_Q25 >= max_min_Q25 ) {
break;
}
/* copy ind_min_max to ind_max_min */
ind_sort[ ind_max_min ] = ind_sort[ ind_min_max ] ^ NLSF_QUANT_DEL_DEC_STATES;
RD_Q25[ ind_max_min ] = RD_Q25[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ];
prev_out_Q10[ ind_max_min ] = prev_out_Q10[ ind_min_max + NLSF_QUANT_DEL_DEC_STATES ];
RD_min_Q25[ ind_max_min ] = 0;
RD_max_Q25[ ind_min_max ] = silk_int32_MAX;
silk_memcpy( ind[ ind_max_min ], ind[ ind_min_max ], MAX_LPC_ORDER * sizeof( opus_int8 ) );
}
/* increment index if it comes from the upper half */
for( j = 0; j < NLSF_QUANT_DEL_DEC_STATES; j++ ) {
ind[ j ][ i ] += silk_RSHIFT( ind_sort[ j ], NLSF_QUANT_DEL_DEC_STATES_LOG2 );
}
}
}
/* last sample: find winner, copy indices and return RD value */
ind_tmp = 0;
min_Q25 = silk_int32_MAX;
for( j = 0; j < 2 * NLSF_QUANT_DEL_DEC_STATES; j++ ) {
if( min_Q25 > RD_Q25[ j ] ) {
min_Q25 = RD_Q25[ j ];
ind_tmp = j;
}
}
for( j = 0; j < order; j++ ) {
indices[ j ] = ind[ ind_tmp & ( NLSF_QUANT_DEL_DEC_STATES - 1 ) ][ j ];
silk_assert( indices[ j ] >= -NLSF_QUANT_MAX_AMPLITUDE_EXT );
silk_assert( indices[ j ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT );
}
indices[ 0 ] += silk_RSHIFT( ind_tmp, NLSF_QUANT_DEL_DEC_STATES_LOG2 );
silk_assert( indices[ 0 ] <= NLSF_QUANT_MAX_AMPLITUDE_EXT );
silk_assert( min_Q25 >= 0 );
return min_Q25;
}

View File

@@ -0,0 +1,124 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
#include "../celt/stack_alloc.h"
/***********************/
/* NLSF vector encoder */
/***********************/
opus_int32 silk_NLSF_encode( /* O Returns RD value in Q25 */
opus_int8 *NLSFIndices, /* I Codebook path vector [ LPC_ORDER + 1 ] */
opus_int16 *pNLSF_Q15, /* I/O (Un)quantized NLSF vector [ LPC_ORDER ] */
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
const opus_int16 *pW_Q2, /* I NLSF weight vector [ LPC_ORDER ] */
const opus_int NLSF_mu_Q20, /* I Rate weight for the RD optimization */
const opus_int nSurvivors, /* I Max survivors after first stage */
const opus_int signalType /* I Signal type: 0/1/2 */
)
{
opus_int i, s, ind1, bestIndex, prob_Q8, bits_q7;
opus_int32 W_tmp_Q9, ret;
VARDECL( opus_int32, err_Q24 );
VARDECL( opus_int32, RD_Q25 );
VARDECL( opus_int, tempIndices1 );
VARDECL( opus_int8, tempIndices2 );
opus_int16 res_Q10[ MAX_LPC_ORDER ];
opus_int16 NLSF_tmp_Q15[ MAX_LPC_ORDER ];
opus_int16 W_adj_Q5[ MAX_LPC_ORDER ];
opus_uint8 pred_Q8[ MAX_LPC_ORDER ];
opus_int16 ec_ix[ MAX_LPC_ORDER ];
const opus_uint8 *pCB_element, *iCDF_ptr;
const opus_int16 *pCB_Wght_Q9;
SAVE_STACK;
celt_assert( signalType >= 0 && signalType <= 2 );
silk_assert( NLSF_mu_Q20 <= 32767 && NLSF_mu_Q20 >= 0 );
/* NLSF stabilization */
silk_NLSF_stabilize( pNLSF_Q15, psNLSF_CB->deltaMin_Q15, psNLSF_CB->order );
/* First stage: VQ */
ALLOC( err_Q24, psNLSF_CB->nVectors, opus_int32 );
silk_NLSF_VQ( err_Q24, pNLSF_Q15, psNLSF_CB->CB1_NLSF_Q8, psNLSF_CB->CB1_Wght_Q9, psNLSF_CB->nVectors, psNLSF_CB->order );
/* Sort the quantization errors */
ALLOC( tempIndices1, nSurvivors, opus_int );
silk_insertion_sort_increasing( err_Q24, tempIndices1, psNLSF_CB->nVectors, nSurvivors );
ALLOC( RD_Q25, nSurvivors, opus_int32 );
ALLOC( tempIndices2, nSurvivors * MAX_LPC_ORDER, opus_int8 );
/* Loop over survivors */
for( s = 0; s < nSurvivors; s++ ) {
ind1 = tempIndices1[ s ];
/* Residual after first stage */
pCB_element = &psNLSF_CB->CB1_NLSF_Q8[ ind1 * psNLSF_CB->order ];
pCB_Wght_Q9 = &psNLSF_CB->CB1_Wght_Q9[ ind1 * psNLSF_CB->order ];
for( i = 0; i < psNLSF_CB->order; i++ ) {
NLSF_tmp_Q15[ i ] = silk_LSHIFT16( (opus_int16)pCB_element[ i ], 7 );
W_tmp_Q9 = pCB_Wght_Q9[ i ];
res_Q10[ i ] = (opus_int16)silk_RSHIFT( silk_SMULBB( pNLSF_Q15[ i ] - NLSF_tmp_Q15[ i ], W_tmp_Q9 ), 14 );
W_adj_Q5[ i ] = silk_DIV32_varQ( (opus_int32)pW_Q2[ i ], silk_SMULBB( W_tmp_Q9, W_tmp_Q9 ), 21 );
}
/* Unpack entropy table indices and predictor for current CB1 index */
silk_NLSF_unpack( ec_ix, pred_Q8, psNLSF_CB, ind1 );
/* Trellis quantizer */
RD_Q25[ s ] = silk_NLSF_del_dec_quant( &tempIndices2[ s * MAX_LPC_ORDER ], res_Q10, W_adj_Q5, pred_Q8, ec_ix,
psNLSF_CB->ec_Rates_Q5, psNLSF_CB->quantStepSize_Q16, psNLSF_CB->invQuantStepSize_Q6, NLSF_mu_Q20, psNLSF_CB->order );
/* Add rate for first stage */
iCDF_ptr = &psNLSF_CB->CB1_iCDF[ ( signalType >> 1 ) * psNLSF_CB->nVectors ];
if( ind1 == 0 ) {
prob_Q8 = 256 - iCDF_ptr[ ind1 ];
} else {
prob_Q8 = iCDF_ptr[ ind1 - 1 ] - iCDF_ptr[ ind1 ];
}
bits_q7 = ( 8 << 7 ) - silk_lin2log( prob_Q8 );
RD_Q25[ s ] = silk_SMLABB( RD_Q25[ s ], bits_q7, silk_RSHIFT( NLSF_mu_Q20, 2 ) );
}
/* Find the lowest rate-distortion error */
silk_insertion_sort_increasing( RD_Q25, &bestIndex, nSurvivors, 1 );
NLSFIndices[ 0 ] = (opus_int8)tempIndices1[ bestIndex ];
silk_memcpy( &NLSFIndices[ 1 ], &tempIndices2[ bestIndex * MAX_LPC_ORDER ], psNLSF_CB->order * sizeof( opus_int8 ) );
/* Decode */
silk_NLSF_decode( pNLSF_Q15, NLSFIndices, psNLSF_CB );
ret = RD_Q25[ 0 ];
RESTORE_STACK;
return ret;
}

View File

@@ -0,0 +1,142 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
/* NLSF stabilizer: */
/* */
/* - Moves NLSFs further apart if they are too close */
/* - Moves NLSFs away from borders if they are too close */
/* - High effort to achieve a modification with minimum */
/* Euclidean distance to input vector */
/* - Output are sorted NLSF coefficients */
/* */
#include "SigProc_FIX.h"
/* Constant Definitions */
#define MAX_LOOPS 20
/* NLSF stabilizer, for a single input data vector */
void silk_NLSF_stabilize(
opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */
const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */
const opus_int L /* I Number of NLSF parameters in the input vector */
)
{
opus_int i, I=0, k, loops;
opus_int16 center_freq_Q15;
opus_int32 diff_Q15, min_diff_Q15, min_center_Q15, max_center_Q15;
/* This is necessary to ensure an output within range of a opus_int16 */
silk_assert( NDeltaMin_Q15[L] >= 1 );
for( loops = 0; loops < MAX_LOOPS; loops++ ) {
/**************************/
/* Find smallest distance */
/**************************/
/* First element */
min_diff_Q15 = NLSF_Q15[0] - NDeltaMin_Q15[0];
I = 0;
/* Middle elements */
for( i = 1; i <= L-1; i++ ) {
diff_Q15 = NLSF_Q15[i] - ( NLSF_Q15[i-1] + NDeltaMin_Q15[i] );
if( diff_Q15 < min_diff_Q15 ) {
min_diff_Q15 = diff_Q15;
I = i;
}
}
/* Last element */
diff_Q15 = ( 1 << 15 ) - ( NLSF_Q15[L-1] + NDeltaMin_Q15[L] );
if( diff_Q15 < min_diff_Q15 ) {
min_diff_Q15 = diff_Q15;
I = L;
}
/***************************************************/
/* Now check if the smallest distance non-negative */
/***************************************************/
if( min_diff_Q15 >= 0 ) {
return;
}
if( I == 0 ) {
/* Move away from lower limit */
NLSF_Q15[0] = NDeltaMin_Q15[0];
} else if( I == L) {
/* Move away from higher limit */
NLSF_Q15[L-1] = ( 1 << 15 ) - NDeltaMin_Q15[L];
} else {
/* Find the lower extreme for the location of the current center frequency */
min_center_Q15 = 0;
for( k = 0; k < I; k++ ) {
min_center_Q15 += NDeltaMin_Q15[k];
}
min_center_Q15 += silk_RSHIFT( NDeltaMin_Q15[I], 1 );
/* Find the upper extreme for the location of the current center frequency */
max_center_Q15 = 1 << 15;
for( k = L; k > I; k-- ) {
max_center_Q15 -= NDeltaMin_Q15[k];
}
max_center_Q15 -= silk_RSHIFT( NDeltaMin_Q15[I], 1 );
/* Move apart, sorted by value, keeping the same center frequency */
center_freq_Q15 = (opus_int16)silk_LIMIT_32( silk_RSHIFT_ROUND( (opus_int32)NLSF_Q15[I-1] + (opus_int32)NLSF_Q15[I], 1 ),
min_center_Q15, max_center_Q15 );
NLSF_Q15[I-1] = center_freq_Q15 - silk_RSHIFT( NDeltaMin_Q15[I], 1 );
NLSF_Q15[I] = NLSF_Q15[I-1] + NDeltaMin_Q15[I];
}
}
/* Safe and simple fall back method, which is less ideal than the above */
if( loops == MAX_LOOPS )
{
/* Insertion sort (fast for already almost sorted arrays): */
/* Best case: O(n) for an already sorted array */
/* Worst case: O(n^2) for an inversely sorted array */
silk_insertion_sort_increasing_all_values_int16( &NLSF_Q15[0], L );
/* First NLSF should be no less than NDeltaMin[0] */
NLSF_Q15[0] = silk_max_int( NLSF_Q15[0], NDeltaMin_Q15[0] );
/* Keep delta_min distance between the NLSFs */
for( i = 1; i < L; i++ )
NLSF_Q15[i] = silk_max_int( NLSF_Q15[i], silk_ADD_SAT16( NLSF_Q15[i-1], NDeltaMin_Q15[i] ) );
/* Last NLSF should be no higher than 1 - NDeltaMin[L] */
NLSF_Q15[L-1] = silk_min_int( NLSF_Q15[L-1], (1<<15) - NDeltaMin_Q15[L] );
/* Keep NDeltaMin distance between the NLSFs */
for( i = L-2; i >= 0; i-- )
NLSF_Q15[i] = silk_min_int( NLSF_Q15[i], NLSF_Q15[i+1] - NDeltaMin_Q15[i+1] );
}
}

View File

@@ -0,0 +1,55 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
/* Unpack predictor values and indices for entropy coding tables */
void silk_NLSF_unpack(
opus_int16 ec_ix[], /* O Indices to entropy tables [ LPC_ORDER ] */
opus_uint8 pred_Q8[], /* O LSF predictor [ LPC_ORDER ] */
const silk_NLSF_CB_struct *psNLSF_CB, /* I Codebook object */
const opus_int CB1_index /* I Index of vector in first LSF codebook */
)
{
opus_int i;
opus_uint8 entry;
const opus_uint8 *ec_sel_ptr;
ec_sel_ptr = &psNLSF_CB->ec_sel[ CB1_index * psNLSF_CB->order / 2 ];
for( i = 0; i < psNLSF_CB->order; i += 2 ) {
entry = *ec_sel_ptr++;
ec_ix [ i ] = silk_SMULBB( silk_RSHIFT( entry, 1 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
pred_Q8[ i ] = psNLSF_CB->pred_Q8[ i + ( entry & 1 ) * ( psNLSF_CB->order - 1 ) ];
ec_ix [ i + 1 ] = silk_SMULBB( silk_RSHIFT( entry, 5 ) & 7, 2 * NLSF_QUANT_MAX_AMPLITUDE + 1 );
pred_Q8[ i + 1 ] = psNLSF_CB->pred_Q8[ i + ( silk_RSHIFT( entry, 4 ) & 1 ) * ( psNLSF_CB->order - 1 ) + 1 ];
}
}

View File

@@ -0,0 +1,437 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
#include "../celt/stack_alloc.h"
#include "NSQ.h"
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
const opus_int16 x16[], /* I input */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I subframe number */
const opus_int LTP_scale_Q14, /* I */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type /* I Signal type */
);
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE void silk_noise_shape_quantizer(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP state */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
int arch /* I Architecture */
);
#endif
void silk_NSQ_c
(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int16 x16[], /* I Input */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int k, lag, start_idx, LSF_interpolation_flag;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq;
VARDECL( opus_int32, sLTP_Q15 );
VARDECL( opus_int16, sLTP );
opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10;
VARDECL( opus_int32, x_sc_Q10 );
SAVE_STACK;
NSQ->rand_seed = psIndices->Seed;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
silk_assert( NSQ->prev_gain_Q16 != 0 );
offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
LSF_interpolation_flag = 0;
} else {
LSF_interpolation_flag = 1;
}
ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
/* Set up pointers to start of sub frame */
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ (( k >> 1 ) | ( 1 - LSF_interpolation_flag )) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
NSQ->rewhite_flag = 0;
if( psIndices->signalType == TYPE_VOICED ) {
/* Voiced */
lag = pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ->rewhite_flag = 1;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
}
}
silk_nsq_scale_states( psEncC, NSQ, x16, x_sc_Q10, sLTP, sLTP_Q15, k, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType );
silk_noise_shape_quantizer( NSQ, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15, A_Q12, B_Q14,
AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ], Gains_Q16[ k ], Lambda_Q10,
offset_Q10, psEncC->subfr_length, psEncC->shapingLPCOrder, psEncC->predictLPCOrder, psEncC->arch );
x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
/* Update lagPrev for next frame */
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech and noise shaping signals */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
/***********************************/
/* silk_noise_shape_quantizer */
/***********************************/
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE
#endif
void silk_noise_shape_quantizer(
silk_nsq_state *NSQ, /* I/O NSQ state */
opus_int signalType, /* I Signal type */
const opus_int32 x_sc_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP state */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping AR coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int shapingLPCOrder, /* I Noise shaping AR filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
int arch /* I Architecture */
)
{
opus_int i;
opus_int32 LTP_pred_Q13, LPC_pred_Q10, n_AR_Q12, n_LTP_Q13;
opus_int32 n_LF_Q12, r_Q10, rr_Q10, q1_Q0, q1_Q10, q2_Q10, rd1_Q20, rd2_Q20;
opus_int32 exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *psLPC_Q14, *shp_lag_ptr, *pred_lag_ptr;
#ifdef silk_short_prediction_create_arch_coef
opus_int32 a_Q12_arch[MAX_LPC_ORDER];
#endif
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
/* Set up short term AR state */
psLPC_Q14 = &NSQ->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 ];
#ifdef silk_short_prediction_create_arch_coef
silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder);
#endif
for( i = 0; i < length; i++ ) {
/* Generate dither */
NSQ->rand_seed = silk_RAND( NSQ->rand_seed );
/* Short-term prediction */
LPC_pred_Q10 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch);
/* Long-term prediction */
if( signalType == TYPE_VOICED ) {
/* Unrolled loop */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LTP_pred_Q13 = 2;
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
LTP_pred_Q13 = silk_SMLAWB( LTP_pred_Q13, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
pred_lag_ptr++;
} else {
LTP_pred_Q13 = 0;
}
/* Noise shape feedback */
celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
n_AR_Q12 = silk_NSQ_noise_shape_feedback_loop(&NSQ->sDiff_shp_Q14, NSQ->sAR2_Q14, AR_shp_Q13, shapingLPCOrder, arch);
n_AR_Q12 = silk_SMLAWB( n_AR_Q12, NSQ->sLF_AR_shp_Q14, Tilt_Q14 );
n_LF_Q12 = silk_SMULWB( NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - 1 ], LF_shp_Q14 );
n_LF_Q12 = silk_SMLAWT( n_LF_Q12, NSQ->sLF_AR_shp_Q14, LF_shp_Q14 );
celt_assert( lag > 0 || signalType != TYPE_VOICED );
/* Combine prediction and noise shaping signals */
tmp1 = silk_SUB32( silk_LSHIFT32( LPC_pred_Q10, 2 ), n_AR_Q12 ); /* Q12 */
tmp1 = silk_SUB32( tmp1, n_LF_Q12 ); /* Q12 */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q13 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_SMLAWT( n_LTP_Q13, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q13 = silk_LSHIFT( n_LTP_Q13, 1 );
shp_lag_ptr++;
tmp2 = silk_SUB32( LTP_pred_Q13, n_LTP_Q13 ); /* Q13 */
tmp1 = silk_ADD_LSHIFT32( tmp2, tmp1, 1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 3 ); /* Q10 */
} else {
tmp1 = silk_RSHIFT_ROUND( tmp1, 2 ); /* Q10 */
}
r_Q10 = silk_SUB32( x_sc_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
if( NSQ->rand_seed < 0 ) {
r_Q10 = -r_Q10;
}
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
if (Lambda_Q10 > 2048) {
/* For aggressive RDO, the bias becomes more than one pulse. */
int rdo_offset = Lambda_Q10/2 - 512;
if (q1_Q10 > rdo_offset) {
q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
} else if (q1_Q10 < -rdo_offset) {
q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
} else if (q1_Q10 < 0) {
q1_Q0 = -1;
} else {
q1_Q0 = 0;
}
}
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == 0 ) {
q1_Q10 = offset_Q10;
q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q20 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == -1 ) {
q2_Q10 = offset_Q10;
q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q20 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else { /* Q1_Q0 < -1 */
q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q20 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q20 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
}
rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
rd1_Q20 = silk_SMLABB( rd1_Q20, rr_Q10, rr_Q10 );
rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
rd2_Q20 = silk_SMLABB( rd2_Q20, rr_Q10, rr_Q10 );
if( rd2_Q20 < rd1_Q20 ) {
q1_Q10 = q2_Q10;
}
pulses[ i ] = (opus_int8)silk_RSHIFT_ROUND( q1_Q10, 10 );
/* Excitation */
exc_Q14 = silk_LSHIFT( q1_Q10, 4 );
if ( NSQ->rand_seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD_LSHIFT32( exc_Q14, LTP_pred_Q13, 1 );
xq_Q14 = silk_ADD_LSHIFT32( LPC_exc_Q14, LPC_pred_Q10, 4 );
/* Scale XQ back to normal level before saving */
xq[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( xq_Q14, Gain_Q10 ), 8 ) );
/* Update states */
psLPC_Q14++;
*psLPC_Q14 = xq_Q14;
NSQ->sDiff_shp_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_sc_Q10[ i ], 4 );
sLF_AR_shp_Q14 = silk_SUB_LSHIFT32( NSQ->sDiff_shp_Q14, n_AR_Q12, 2 );
NSQ->sLF_AR_shp_Q14 = sLF_AR_shp_Q14;
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx ] = silk_SUB_LSHIFT32( sLF_AR_shp_Q14, n_LF_Q12, 2 );
sLTP_Q15[ NSQ->sLTP_buf_idx ] = silk_LSHIFT( LPC_exc_Q14, 1 );
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Make dither dependent on quantized signal */
NSQ->rand_seed = silk_ADD32_ovflw( NSQ->rand_seed, pulses[ i ] );
}
/* Update LPC synth buffer */
silk_memcpy( NSQ->sLPC_Q14, &NSQ->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
}
static OPUS_INLINE void silk_nsq_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
const opus_int16 x16[], /* I input */
opus_int32 x_sc_Q10[], /* O input scaled with 1/Gain */
const opus_int16 sLTP[], /* I re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I subframe number */
const opus_int LTP_scale_Q14, /* I */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type /* I Signal type */
)
{
opus_int i, lag;
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
/* Scale input */
inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
/* Do LTP downscaling */
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
}
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
silk_assert( i < MAX_FRAME_LENGTH );
sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
}
}
/* Adjust for changing gain */
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
}
/* Scale long-term prediction state */
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
}
}
NSQ->sLF_AR_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sLF_AR_shp_Q14 );
NSQ->sDiff_shp_Q14 = silk_SMULWW( gain_adj_Q16, NSQ->sDiff_shp_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
NSQ->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLPC_Q14[ i ] );
}
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
NSQ->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sAR2_Q14[ i ] );
}
/* Save inverse gain */
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}

View File

@@ -0,0 +1,101 @@
/***********************************************************************
Copyright (c) 2014 Vidyo.
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
#ifndef SILK_NSQ_H
#define SILK_NSQ_H
#include "SigProc_FIX.h"
#undef silk_short_prediction_create_arch_coef
static OPUS_INLINE opus_int32 silk_noise_shape_quantizer_short_prediction_c(const opus_int32 *buf32, const opus_int16 *coef16, opus_int order)
{
opus_int32 out;
silk_assert( order == 10 || order == 16 );
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
out = silk_RSHIFT( order, 1 );
out = silk_SMLAWB( out, buf32[ 0 ], coef16[ 0 ] );
out = silk_SMLAWB( out, buf32[ -1 ], coef16[ 1 ] );
out = silk_SMLAWB( out, buf32[ -2 ], coef16[ 2 ] );
out = silk_SMLAWB( out, buf32[ -3 ], coef16[ 3 ] );
out = silk_SMLAWB( out, buf32[ -4 ], coef16[ 4 ] );
out = silk_SMLAWB( out, buf32[ -5 ], coef16[ 5 ] );
out = silk_SMLAWB( out, buf32[ -6 ], coef16[ 6 ] );
out = silk_SMLAWB( out, buf32[ -7 ], coef16[ 7 ] );
out = silk_SMLAWB( out, buf32[ -8 ], coef16[ 8 ] );
out = silk_SMLAWB( out, buf32[ -9 ], coef16[ 9 ] );
if( order == 16 )
{
out = silk_SMLAWB( out, buf32[ -10 ], coef16[ 10 ] );
out = silk_SMLAWB( out, buf32[ -11 ], coef16[ 11 ] );
out = silk_SMLAWB( out, buf32[ -12 ], coef16[ 12 ] );
out = silk_SMLAWB( out, buf32[ -13 ], coef16[ 13 ] );
out = silk_SMLAWB( out, buf32[ -14 ], coef16[ 14 ] );
out = silk_SMLAWB( out, buf32[ -15 ], coef16[ 15 ] );
}
return out;
}
#define silk_noise_shape_quantizer_short_prediction(in, coef, coefRev, order, arch) ((void)arch,silk_noise_shape_quantizer_short_prediction_c(in, coef, order))
static OPUS_INLINE opus_int32 silk_NSQ_noise_shape_feedback_loop_c(const opus_int32 *data0, opus_int32 *data1, const opus_int16 *coef, opus_int order)
{
opus_int32 out;
opus_int32 tmp1, tmp2;
opus_int j;
tmp2 = data0[0];
tmp1 = data1[0];
data1[0] = tmp2;
out = silk_RSHIFT(order, 1);
out = silk_SMLAWB(out, tmp2, coef[0]);
for (j = 2; j < order; j += 2) {
tmp2 = data1[j - 1];
data1[j - 1] = tmp1;
out = silk_SMLAWB(out, tmp1, coef[j - 1]);
tmp1 = data1[j + 0];
data1[j + 0] = tmp2;
out = silk_SMLAWB(out, tmp2, coef[j]);
}
data1[order - 1] = tmp1;
out = silk_SMLAWB(out, tmp1, coef[order - 1]);
/* Q11 -> Q12 */
out = silk_LSHIFT32( out, 1 );
return out;
}
#define silk_NSQ_noise_shape_feedback_loop(data0, data1, coef, order, arch) ((void)arch,silk_NSQ_noise_shape_feedback_loop_c(data0, data1, coef, order))
#if defined(OPUS_ARM_MAY_HAVE_NEON_INTR)
#include "arm/NSQ_neon.h"
#endif
#endif /* SILK_NSQ_H */

View File

@@ -0,0 +1,733 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
#include "../celt/stack_alloc.h"
#include "NSQ.h"
typedef struct {
opus_int32 sLPC_Q14[ MAX_SUB_FRAME_LENGTH + NSQ_LPC_BUF_LENGTH ];
opus_int32 RandState[ DECISION_DELAY ];
opus_int32 Q_Q10[ DECISION_DELAY ];
opus_int32 Xq_Q14[ DECISION_DELAY ];
opus_int32 Pred_Q15[ DECISION_DELAY ];
opus_int32 Shape_Q14[ DECISION_DELAY ];
opus_int32 sAR2_Q14[ MAX_SHAPE_LPC_ORDER ];
opus_int32 LF_AR_Q14;
opus_int32 Diff_Q14;
opus_int32 Seed;
opus_int32 SeedInit;
opus_int32 RD_Q10;
} NSQ_del_dec_struct;
typedef struct {
opus_int32 Q_Q10;
opus_int32 RD_Q10;
opus_int32 xq_Q14;
opus_int32 LF_AR_Q14;
opus_int32 Diff_Q14;
opus_int32 sLTP_shp_Q14;
opus_int32 LPC_exc_Q14;
} NSQ_sample_struct;
typedef NSQ_sample_struct NSQ_sample_pair[ 2 ];
#if defined(MIPSr1_ASM)
#include "mips/NSQ_del_dec_mipsr1.h"
#endif
static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
const opus_int16 x16[], /* I Input */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I Subframe number */
opus_int nStatesDelayedDecision, /* I Number of del dec states */
const opus_int LTP_scale_Q14, /* I LTP state scaling */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type, /* I Signal type */
const opus_int decisionDelay /* I Decision delay */
);
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
opus_int signalType, /* I Signal type */
const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int subfr, /* I Subframe number */
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
);
void silk_NSQ_del_dec_c(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
SideInfoIndices *psIndices, /* I/O Quantization Indices */
const opus_int16 x16[], /* I Input */
opus_int8 pulses[], /* O Quantized pulse signal */
const opus_int16 PredCoef_Q12[ 2 * MAX_LPC_ORDER ], /* I Short term prediction coefs */
const opus_int16 LTPCoef_Q14[ LTP_ORDER * MAX_NB_SUBFR ], /* I Long term prediction coefs */
const opus_int16 AR_Q13[ MAX_NB_SUBFR * MAX_SHAPE_LPC_ORDER ], /* I Noise shaping coefs */
const opus_int HarmShapeGain_Q14[ MAX_NB_SUBFR ], /* I Long term shaping coefs */
const opus_int Tilt_Q14[ MAX_NB_SUBFR ], /* I Spectral tilt */
const opus_int32 LF_shp_Q14[ MAX_NB_SUBFR ], /* I Low frequency shaping coefs */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I Quantization step sizes */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lags */
const opus_int Lambda_Q10, /* I Rate/distortion tradeoff */
const opus_int LTP_scale_Q14 /* I LTP state scaling */
)
{
opus_int i, k, lag, start_idx, LSF_interpolation_flag, Winner_ind, subfr;
opus_int last_smple_idx, smpl_buf_idx, decisionDelay;
const opus_int16 *A_Q12, *B_Q14, *AR_shp_Q13;
opus_int16 *pxq;
VARDECL( opus_int32, sLTP_Q15 );
VARDECL( opus_int16, sLTP );
opus_int32 HarmShapeFIRPacked_Q14;
opus_int offset_Q10;
opus_int32 RDmin_Q10, Gain_Q10;
VARDECL( opus_int32, x_sc_Q10 );
VARDECL( opus_int32, delayedGain_Q10 );
VARDECL( NSQ_del_dec_struct, psDelDec );
NSQ_del_dec_struct *psDD;
SAVE_STACK;
/* Set unvoiced lag to the previous one, overwrite later for voiced */
lag = NSQ->lagPrev;
silk_assert( NSQ->prev_gain_Q16 != 0 );
/* Initialize delayed decision states */
ALLOC( psDelDec, psEncC->nStatesDelayedDecision, NSQ_del_dec_struct );
silk_memset( psDelDec, 0, psEncC->nStatesDelayedDecision * sizeof( NSQ_del_dec_struct ) );
for( k = 0; k < psEncC->nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psDD->Seed = ( k + psIndices->Seed ) & 3;
psDD->SeedInit = psDD->Seed;
psDD->RD_Q10 = 0;
psDD->LF_AR_Q14 = NSQ->sLF_AR_shp_Q14;
psDD->Diff_Q14 = NSQ->sDiff_shp_Q14;
psDD->Shape_Q14[ 0 ] = NSQ->sLTP_shp_Q14[ psEncC->ltp_mem_length - 1 ];
silk_memcpy( psDD->sLPC_Q14, NSQ->sLPC_Q14, NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( psDD->sAR2_Q14, NSQ->sAR2_Q14, sizeof( NSQ->sAR2_Q14 ) );
}
offset_Q10 = silk_Quantization_Offsets_Q10[ psIndices->signalType >> 1 ][ psIndices->quantOffsetType ];
smpl_buf_idx = 0; /* index of oldest samples */
decisionDelay = silk_min_int( DECISION_DELAY, psEncC->subfr_length );
/* For voiced frames limit the decision delay to lower than the pitch lag */
if( psIndices->signalType == TYPE_VOICED ) {
for( k = 0; k < psEncC->nb_subfr; k++ ) {
decisionDelay = silk_min_int( decisionDelay, pitchL[ k ] - LTP_ORDER / 2 - 1 );
}
} else {
if( lag > 0 ) {
decisionDelay = silk_min_int( decisionDelay, lag - LTP_ORDER / 2 - 1 );
}
}
if( psIndices->NLSFInterpCoef_Q2 == 4 ) {
LSF_interpolation_flag = 0;
} else {
LSF_interpolation_flag = 1;
}
ALLOC( sLTP_Q15, psEncC->ltp_mem_length + psEncC->frame_length, opus_int32 );
ALLOC( sLTP, psEncC->ltp_mem_length + psEncC->frame_length, opus_int16 );
ALLOC( x_sc_Q10, psEncC->subfr_length, opus_int32 );
ALLOC( delayedGain_Q10, DECISION_DELAY, opus_int32 );
/* Set up pointers to start of sub frame */
pxq = &NSQ->xq[ psEncC->ltp_mem_length ];
NSQ->sLTP_shp_buf_idx = psEncC->ltp_mem_length;
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
subfr = 0;
for( k = 0; k < psEncC->nb_subfr; k++ ) {
A_Q12 = &PredCoef_Q12[ ( ( k >> 1 ) | ( 1 - LSF_interpolation_flag ) ) * MAX_LPC_ORDER ];
B_Q14 = &LTPCoef_Q14[ k * LTP_ORDER ];
AR_shp_Q13 = &AR_Q13[ k * MAX_SHAPE_LPC_ORDER ];
/* Noise shape parameters */
silk_assert( HarmShapeGain_Q14[ k ] >= 0 );
HarmShapeFIRPacked_Q14 = silk_RSHIFT( HarmShapeGain_Q14[ k ], 2 );
HarmShapeFIRPacked_Q14 |= silk_LSHIFT( (opus_int32)silk_RSHIFT( HarmShapeGain_Q14[ k ], 1 ), 16 );
NSQ->rewhite_flag = 0;
if( psIndices->signalType == TYPE_VOICED ) {
/* Voiced */
lag = pitchL[ k ];
/* Re-whitening */
if( ( k & ( 3 - silk_LSHIFT( LSF_interpolation_flag, 1 ) ) ) == 0 ) {
if( k == 2 ) {
/* RESET DELAYED DECISIONS */
/* Find winner */
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
Winner_ind = 0;
for( i = 1; i < psEncC->nStatesDelayedDecision; i++ ) {
if( psDelDec[ i ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psDelDec[ i ].RD_Q10;
Winner_ind = i;
}
}
for( i = 0; i < psEncC->nStatesDelayedDecision; i++ ) {
if( i != Winner_ind ) {
psDelDec[ i ].RD_Q10 += ( silk_int32_MAX >> 4 );
silk_assert( psDelDec[ i ].RD_Q10 >= 0 );
}
}
/* Copy final part of signals from winner state to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
last_smple_idx = smpl_buf_idx + decisionDelay;
for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gains_Q16[ 1 ] ), 14 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
}
subfr = 0;
}
/* Rewhiten with new A coefs */
start_idx = psEncC->ltp_mem_length - lag - psEncC->predictLPCOrder - LTP_ORDER / 2;
celt_assert( start_idx > 0 );
silk_LPC_analysis_filter( &sLTP[ start_idx ], &NSQ->xq[ start_idx + k * psEncC->subfr_length ],
A_Q12, psEncC->ltp_mem_length - start_idx, psEncC->predictLPCOrder, psEncC->arch );
NSQ->sLTP_buf_idx = psEncC->ltp_mem_length;
NSQ->rewhite_flag = 1;
}
}
silk_nsq_del_dec_scale_states( psEncC, NSQ, psDelDec, x16, x_sc_Q10, sLTP, sLTP_Q15, k,
psEncC->nStatesDelayedDecision, LTP_scale_Q14, Gains_Q16, pitchL, psIndices->signalType, decisionDelay );
silk_noise_shape_quantizer_del_dec( NSQ, psDelDec, psIndices->signalType, x_sc_Q10, pulses, pxq, sLTP_Q15,
delayedGain_Q10, A_Q12, B_Q14, AR_shp_Q13, lag, HarmShapeFIRPacked_Q14, Tilt_Q14[ k ], LF_shp_Q14[ k ],
Gains_Q16[ k ], Lambda_Q10, offset_Q10, psEncC->subfr_length, subfr++, psEncC->shapingLPCOrder,
psEncC->predictLPCOrder, psEncC->warping_Q16, psEncC->nStatesDelayedDecision, &smpl_buf_idx, decisionDelay, psEncC->arch );
x16 += psEncC->subfr_length;
pulses += psEncC->subfr_length;
pxq += psEncC->subfr_length;
}
/* Find winner */
RDmin_Q10 = psDelDec[ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < psEncC->nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psDelDec[ k ].RD_Q10;
Winner_ind = k;
}
}
/* Copy final part of signals from winner state to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
psIndices->Seed = psDD->SeedInit;
last_smple_idx = smpl_buf_idx + decisionDelay;
Gain_Q10 = silk_RSHIFT32( Gains_Q16[ psEncC->nb_subfr - 1 ], 6 );
for( i = 0; i < decisionDelay; i++ ) {
last_smple_idx = ( last_smple_idx - 1 ) % DECISION_DELAY;
if( last_smple_idx < 0 ) last_smple_idx += DECISION_DELAY;
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
pxq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], Gain_Q10 ), 8 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay + i ] = psDD->Shape_Q14[ last_smple_idx ];
}
silk_memcpy( NSQ->sLPC_Q14, &psDD->sLPC_Q14[ psEncC->subfr_length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
silk_memcpy( NSQ->sAR2_Q14, psDD->sAR2_Q14, sizeof( psDD->sAR2_Q14 ) );
/* Update states */
NSQ->sLF_AR_shp_Q14 = psDD->LF_AR_Q14;
NSQ->sDiff_shp_Q14 = psDD->Diff_Q14;
NSQ->lagPrev = pitchL[ psEncC->nb_subfr - 1 ];
/* Save quantized speech signal */
silk_memmove( NSQ->xq, &NSQ->xq[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int16 ) );
silk_memmove( NSQ->sLTP_shp_Q14, &NSQ->sLTP_shp_Q14[ psEncC->frame_length ], psEncC->ltp_mem_length * sizeof( opus_int32 ) );
RESTORE_STACK;
}
/******************************************/
/* Noise shape quantizer for one subframe */
/******************************************/
#ifndef OVERRIDE_silk_noise_shape_quantizer_del_dec
static OPUS_INLINE void silk_noise_shape_quantizer_del_dec(
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
opus_int signalType, /* I Signal type */
const opus_int32 x_Q10[], /* I */
opus_int8 pulses[], /* O */
opus_int16 xq[], /* O */
opus_int32 sLTP_Q15[], /* I/O LTP filter state */
opus_int32 delayedGain_Q10[], /* I/O Gain delay buffer */
const opus_int16 a_Q12[], /* I Short term prediction coefs */
const opus_int16 b_Q14[], /* I Long term prediction coefs */
const opus_int16 AR_shp_Q13[], /* I Noise shaping coefs */
opus_int lag, /* I Pitch lag */
opus_int32 HarmShapeFIRPacked_Q14, /* I */
opus_int Tilt_Q14, /* I Spectral tilt */
opus_int32 LF_shp_Q14, /* I */
opus_int32 Gain_Q16, /* I */
opus_int Lambda_Q10, /* I */
opus_int offset_Q10, /* I */
opus_int length, /* I Input length */
opus_int subfr, /* I Subframe number */
opus_int shapingLPCOrder, /* I Shaping LPC filter order */
opus_int predictLPCOrder, /* I Prediction filter order */
opus_int warping_Q16, /* I */
opus_int nStatesDelayedDecision, /* I Number of states in decision tree */
opus_int *smpl_buf_idx, /* I/O Index to newest samples in buffers */
opus_int decisionDelay, /* I */
int arch /* I */
)
{
opus_int i, j, k, Winner_ind, RDmin_ind, RDmax_ind, last_smple_idx;
opus_int32 Winner_rand_state;
opus_int32 LTP_pred_Q14, LPC_pred_Q14, n_AR_Q14, n_LTP_Q14;
opus_int32 n_LF_Q14, r_Q10, rr_Q10, rd1_Q10, rd2_Q10, RDmin_Q10, RDmax_Q10;
opus_int32 q1_Q0, q1_Q10, q2_Q10, exc_Q14, LPC_exc_Q14, xq_Q14, Gain_Q10;
opus_int32 tmp1, tmp2, sLF_AR_shp_Q14;
opus_int32 *pred_lag_ptr, *shp_lag_ptr, *psLPC_Q14;
#ifdef silk_short_prediction_create_arch_coef
opus_int32 a_Q12_arch[MAX_LPC_ORDER];
#endif
VARDECL( NSQ_sample_pair, psSampleState );
NSQ_del_dec_struct *psDD;
NSQ_sample_struct *psSS;
SAVE_STACK;
celt_assert( nStatesDelayedDecision > 0 );
ALLOC( psSampleState, nStatesDelayedDecision, NSQ_sample_pair );
shp_lag_ptr = &NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - lag + HARM_SHAPE_FIR_TAPS / 2 ];
pred_lag_ptr = &sLTP_Q15[ NSQ->sLTP_buf_idx - lag + LTP_ORDER / 2 ];
Gain_Q10 = silk_RSHIFT( Gain_Q16, 6 );
#ifdef silk_short_prediction_create_arch_coef
silk_short_prediction_create_arch_coef(a_Q12_arch, a_Q12, predictLPCOrder);
#endif
for( i = 0; i < length; i++ ) {
/* Perform common calculations used in all states */
/* Long-term prediction */
if( signalType == TYPE_VOICED ) {
/* Unrolled loop */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LTP_pred_Q14 = 2;
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ 0 ], b_Q14[ 0 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -1 ], b_Q14[ 1 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -2 ], b_Q14[ 2 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -3 ], b_Q14[ 3 ] );
LTP_pred_Q14 = silk_SMLAWB( LTP_pred_Q14, pred_lag_ptr[ -4 ], b_Q14[ 4 ] );
LTP_pred_Q14 = silk_LSHIFT( LTP_pred_Q14, 1 ); /* Q13 -> Q14 */
pred_lag_ptr++;
} else {
LTP_pred_Q14 = 0;
}
/* Long-term shaping */
if( lag > 0 ) {
/* Symmetric, packed FIR coefficients */
n_LTP_Q14 = silk_SMULWB( silk_ADD32( shp_lag_ptr[ 0 ], shp_lag_ptr[ -2 ] ), HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SMLAWT( n_LTP_Q14, shp_lag_ptr[ -1 ], HarmShapeFIRPacked_Q14 );
n_LTP_Q14 = silk_SUB_LSHIFT32( LTP_pred_Q14, n_LTP_Q14, 2 ); /* Q12 -> Q14 */
shp_lag_ptr++;
} else {
n_LTP_Q14 = 0;
}
for( k = 0; k < nStatesDelayedDecision; k++ ) {
/* Delayed decision state */
psDD = &psDelDec[ k ];
/* Sample state */
psSS = psSampleState[ k ];
/* Generate dither */
psDD->Seed = silk_RAND( psDD->Seed );
/* Pointer used in short term prediction and shaping */
psLPC_Q14 = &psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH - 1 + i ];
/* Short-term prediction */
LPC_pred_Q14 = silk_noise_shape_quantizer_short_prediction(psLPC_Q14, a_Q12, a_Q12_arch, predictLPCOrder, arch);
LPC_pred_Q14 = silk_LSHIFT( LPC_pred_Q14, 4 ); /* Q10 -> Q14 */
/* Noise shape feedback */
celt_assert( ( shapingLPCOrder & 1 ) == 0 ); /* check that order is even */
/* Output of lowpass section */
tmp2 = silk_SMLAWB( psDD->Diff_Q14, psDD->sAR2_Q14[ 0 ], warping_Q16 );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ 0 ], psDD->sAR2_Q14[ 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ 0 ] = tmp2;
n_AR_Q14 = silk_RSHIFT( shapingLPCOrder, 1 );
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ 0 ] );
/* Loop over allpass sections */
for( j = 2; j < shapingLPCOrder; j += 2 ) {
/* Output of allpass section */
tmp2 = silk_SMLAWB( psDD->sAR2_Q14[ j - 1 ], psDD->sAR2_Q14[ j + 0 ] - tmp1, warping_Q16 );
psDD->sAR2_Q14[ j - 1 ] = tmp1;
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ j - 1 ] );
/* Output of allpass section */
tmp1 = silk_SMLAWB( psDD->sAR2_Q14[ j + 0 ], psDD->sAR2_Q14[ j + 1 ] - tmp2, warping_Q16 );
psDD->sAR2_Q14[ j + 0 ] = tmp2;
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp2, AR_shp_Q13[ j ] );
}
psDD->sAR2_Q14[ shapingLPCOrder - 1 ] = tmp1;
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, tmp1, AR_shp_Q13[ shapingLPCOrder - 1 ] );
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 1 ); /* Q11 -> Q12 */
n_AR_Q14 = silk_SMLAWB( n_AR_Q14, psDD->LF_AR_Q14, Tilt_Q14 ); /* Q12 */
n_AR_Q14 = silk_LSHIFT( n_AR_Q14, 2 ); /* Q12 -> Q14 */
n_LF_Q14 = silk_SMULWB( psDD->Shape_Q14[ *smpl_buf_idx ], LF_shp_Q14 ); /* Q12 */
n_LF_Q14 = silk_SMLAWT( n_LF_Q14, psDD->LF_AR_Q14, LF_shp_Q14 ); /* Q12 */
n_LF_Q14 = silk_LSHIFT( n_LF_Q14, 2 ); /* Q12 -> Q14 */
/* Input minus prediction plus noise feedback */
/* r = x[ i ] - LTP_pred - LPC_pred + n_AR + n_Tilt + n_LF + n_LTP */
tmp1 = silk_ADD32( n_AR_Q14, n_LF_Q14 ); /* Q14 */
tmp2 = silk_ADD32( n_LTP_Q14, LPC_pred_Q14 ); /* Q13 */
tmp1 = silk_SUB32( tmp2, tmp1 ); /* Q13 */
tmp1 = silk_RSHIFT_ROUND( tmp1, 4 ); /* Q10 */
r_Q10 = silk_SUB32( x_Q10[ i ], tmp1 ); /* residual error Q10 */
/* Flip sign depending on dither */
if ( psDD->Seed < 0 ) {
r_Q10 = -r_Q10;
}
r_Q10 = silk_LIMIT_32( r_Q10, -(31 << 10), 30 << 10 );
/* Find two quantization level candidates and measure their rate-distortion */
q1_Q10 = silk_SUB32( r_Q10, offset_Q10 );
q1_Q0 = silk_RSHIFT( q1_Q10, 10 );
if (Lambda_Q10 > 2048) {
/* For aggressive RDO, the bias becomes more than one pulse. */
int rdo_offset = Lambda_Q10/2 - 512;
if (q1_Q10 > rdo_offset) {
q1_Q0 = silk_RSHIFT( q1_Q10 - rdo_offset, 10 );
} else if (q1_Q10 < -rdo_offset) {
q1_Q0 = silk_RSHIFT( q1_Q10 + rdo_offset, 10 );
} else if (q1_Q10 < 0) {
q1_Q0 = -1;
} else {
q1_Q0 = 0;
}
}
if( q1_Q0 > 0 ) {
q1_Q10 = silk_SUB32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == 0 ) {
q1_Q10 = offset_Q10;
q2_Q10 = silk_ADD32( q1_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q10 = silk_SMULBB( q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else if( q1_Q0 == -1 ) {
q2_Q10 = offset_Q10;
q1_Q10 = silk_SUB32( q2_Q10, 1024 - QUANT_LEVEL_ADJUST_Q10 );
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( q2_Q10, Lambda_Q10 );
} else { /* q1_Q0 < -1 */
q1_Q10 = silk_ADD32( silk_LSHIFT( q1_Q0, 10 ), QUANT_LEVEL_ADJUST_Q10 );
q1_Q10 = silk_ADD32( q1_Q10, offset_Q10 );
q2_Q10 = silk_ADD32( q1_Q10, 1024 );
rd1_Q10 = silk_SMULBB( -q1_Q10, Lambda_Q10 );
rd2_Q10 = silk_SMULBB( -q2_Q10, Lambda_Q10 );
}
rr_Q10 = silk_SUB32( r_Q10, q1_Q10 );
rd1_Q10 = silk_RSHIFT( silk_SMLABB( rd1_Q10, rr_Q10, rr_Q10 ), 10 );
rr_Q10 = silk_SUB32( r_Q10, q2_Q10 );
rd2_Q10 = silk_RSHIFT( silk_SMLABB( rd2_Q10, rr_Q10, rr_Q10 ), 10 );
if( rd1_Q10 < rd2_Q10 ) {
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 0 ].Q_Q10 = q1_Q10;
psSS[ 1 ].Q_Q10 = q2_Q10;
} else {
psSS[ 0 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd2_Q10 );
psSS[ 1 ].RD_Q10 = silk_ADD32( psDD->RD_Q10, rd1_Q10 );
psSS[ 0 ].Q_Q10 = q2_Q10;
psSS[ 1 ].Q_Q10 = q1_Q10;
}
/* Update states for best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 0 ].Q_Q10, 4 );
if ( psDD->Seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
psSS[ 0 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
sLF_AR_shp_Q14 = silk_SUB32( psSS[ 0 ].Diff_Q14, n_AR_Q14 );
psSS[ 0 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 0 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 0 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 0 ].xq_Q14 = xq_Q14;
/* Update states for second best quantization */
/* Quantized excitation */
exc_Q14 = silk_LSHIFT32( psSS[ 1 ].Q_Q10, 4 );
if ( psDD->Seed < 0 ) {
exc_Q14 = -exc_Q14;
}
/* Add predictions */
LPC_exc_Q14 = silk_ADD32( exc_Q14, LTP_pred_Q14 );
xq_Q14 = silk_ADD32( LPC_exc_Q14, LPC_pred_Q14 );
/* Update states */
psSS[ 1 ].Diff_Q14 = silk_SUB_LSHIFT32( xq_Q14, x_Q10[ i ], 4 );
sLF_AR_shp_Q14 = silk_SUB32( psSS[ 1 ].Diff_Q14, n_AR_Q14 );
psSS[ 1 ].sLTP_shp_Q14 = silk_SUB32( sLF_AR_shp_Q14, n_LF_Q14 );
psSS[ 1 ].LF_AR_Q14 = sLF_AR_shp_Q14;
psSS[ 1 ].LPC_exc_Q14 = LPC_exc_Q14;
psSS[ 1 ].xq_Q14 = xq_Q14;
}
*smpl_buf_idx = ( *smpl_buf_idx - 1 ) % DECISION_DELAY;
if( *smpl_buf_idx < 0 ) *smpl_buf_idx += DECISION_DELAY;
last_smple_idx = ( *smpl_buf_idx + decisionDelay ) % DECISION_DELAY;
/* Find winner */
RDmin_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
Winner_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
if( psSampleState[ k ][ 0 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
Winner_ind = k;
}
}
/* Increase RD values of expired states */
Winner_rand_state = psDelDec[ Winner_ind ].RandState[ last_smple_idx ];
for( k = 0; k < nStatesDelayedDecision; k++ ) {
if( psDelDec[ k ].RandState[ last_smple_idx ] != Winner_rand_state ) {
psSampleState[ k ][ 0 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 0 ].RD_Q10, silk_int32_MAX >> 4 );
psSampleState[ k ][ 1 ].RD_Q10 = silk_ADD32( psSampleState[ k ][ 1 ].RD_Q10, silk_int32_MAX >> 4 );
silk_assert( psSampleState[ k ][ 0 ].RD_Q10 >= 0 );
}
}
/* Find worst in first set and best in second set */
RDmax_Q10 = psSampleState[ 0 ][ 0 ].RD_Q10;
RDmin_Q10 = psSampleState[ 0 ][ 1 ].RD_Q10;
RDmax_ind = 0;
RDmin_ind = 0;
for( k = 1; k < nStatesDelayedDecision; k++ ) {
/* find worst in first set */
if( psSampleState[ k ][ 0 ].RD_Q10 > RDmax_Q10 ) {
RDmax_Q10 = psSampleState[ k ][ 0 ].RD_Q10;
RDmax_ind = k;
}
/* find best in second set */
if( psSampleState[ k ][ 1 ].RD_Q10 < RDmin_Q10 ) {
RDmin_Q10 = psSampleState[ k ][ 1 ].RD_Q10;
RDmin_ind = k;
}
}
/* Replace a state if best from second set outperforms worst in first set */
if( RDmin_Q10 < RDmax_Q10 ) {
silk_memcpy( ( (opus_int32 *)&psDelDec[ RDmax_ind ] ) + i,
( (opus_int32 *)&psDelDec[ RDmin_ind ] ) + i, sizeof( NSQ_del_dec_struct ) - i * sizeof( opus_int32) );
silk_memcpy( &psSampleState[ RDmax_ind ][ 0 ], &psSampleState[ RDmin_ind ][ 1 ], sizeof( NSQ_sample_struct ) );
}
/* Write samples from winner to output and long-term filter states */
psDD = &psDelDec[ Winner_ind ];
if( subfr > 0 || i >= decisionDelay ) {
pulses[ i - decisionDelay ] = (opus_int8)silk_RSHIFT_ROUND( psDD->Q_Q10[ last_smple_idx ], 10 );
xq[ i - decisionDelay ] = (opus_int16)silk_SAT16( silk_RSHIFT_ROUND(
silk_SMULWW( psDD->Xq_Q14[ last_smple_idx ], delayedGain_Q10[ last_smple_idx ] ), 8 ) );
NSQ->sLTP_shp_Q14[ NSQ->sLTP_shp_buf_idx - decisionDelay ] = psDD->Shape_Q14[ last_smple_idx ];
sLTP_Q15[ NSQ->sLTP_buf_idx - decisionDelay ] = psDD->Pred_Q15[ last_smple_idx ];
}
NSQ->sLTP_shp_buf_idx++;
NSQ->sLTP_buf_idx++;
/* Update states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
psSS = &psSampleState[ k ][ 0 ];
psDD->LF_AR_Q14 = psSS->LF_AR_Q14;
psDD->Diff_Q14 = psSS->Diff_Q14;
psDD->sLPC_Q14[ NSQ_LPC_BUF_LENGTH + i ] = psSS->xq_Q14;
psDD->Xq_Q14[ *smpl_buf_idx ] = psSS->xq_Q14;
psDD->Q_Q10[ *smpl_buf_idx ] = psSS->Q_Q10;
psDD->Pred_Q15[ *smpl_buf_idx ] = silk_LSHIFT32( psSS->LPC_exc_Q14, 1 );
psDD->Shape_Q14[ *smpl_buf_idx ] = psSS->sLTP_shp_Q14;
psDD->Seed = silk_ADD32_ovflw( psDD->Seed, silk_RSHIFT_ROUND( psSS->Q_Q10, 10 ) );
psDD->RandState[ *smpl_buf_idx ] = psDD->Seed;
psDD->RD_Q10 = psSS->RD_Q10;
}
delayedGain_Q10[ *smpl_buf_idx ] = Gain_Q10;
}
/* Update LPC states */
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
silk_memcpy( psDD->sLPC_Q14, &psDD->sLPC_Q14[ length ], NSQ_LPC_BUF_LENGTH * sizeof( opus_int32 ) );
}
RESTORE_STACK;
}
#endif /* OVERRIDE_silk_noise_shape_quantizer_del_dec */
static OPUS_INLINE void silk_nsq_del_dec_scale_states(
const silk_encoder_state *psEncC, /* I Encoder State */
silk_nsq_state *NSQ, /* I/O NSQ state */
NSQ_del_dec_struct psDelDec[], /* I/O Delayed decision states */
const opus_int16 x16[], /* I Input */
opus_int32 x_sc_Q10[], /* O Input scaled with 1/Gain in Q10 */
const opus_int16 sLTP[], /* I Re-whitened LTP state in Q0 */
opus_int32 sLTP_Q15[], /* O LTP state matching scaled input */
opus_int subfr, /* I Subframe number */
opus_int nStatesDelayedDecision, /* I Number of del dec states */
const opus_int LTP_scale_Q14, /* I LTP state scaling */
const opus_int32 Gains_Q16[ MAX_NB_SUBFR ], /* I */
const opus_int pitchL[ MAX_NB_SUBFR ], /* I Pitch lag */
const opus_int signal_type, /* I Signal type */
const opus_int decisionDelay /* I Decision delay */
)
{
opus_int i, k, lag;
opus_int32 gain_adj_Q16, inv_gain_Q31, inv_gain_Q26;
NSQ_del_dec_struct *psDD;
lag = pitchL[ subfr ];
inv_gain_Q31 = silk_INVERSE32_varQ( silk_max( Gains_Q16[ subfr ], 1 ), 47 );
silk_assert( inv_gain_Q31 != 0 );
/* Scale input */
inv_gain_Q26 = silk_RSHIFT_ROUND( inv_gain_Q31, 5 );
for( i = 0; i < psEncC->subfr_length; i++ ) {
x_sc_Q10[ i ] = silk_SMULWW( x16[ i ], inv_gain_Q26 );
}
/* After rewhitening the LTP state is un-scaled, so scale with inv_gain_Q16 */
if( NSQ->rewhite_flag ) {
if( subfr == 0 ) {
/* Do LTP downscaling */
inv_gain_Q31 = silk_LSHIFT( silk_SMULWB( inv_gain_Q31, LTP_scale_Q14 ), 2 );
}
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx; i++ ) {
silk_assert( i < MAX_FRAME_LENGTH );
sLTP_Q15[ i ] = silk_SMULWB( inv_gain_Q31, sLTP[ i ] );
}
}
/* Adjust for changing gain */
if( Gains_Q16[ subfr ] != NSQ->prev_gain_Q16 ) {
gain_adj_Q16 = silk_DIV32_varQ( NSQ->prev_gain_Q16, Gains_Q16[ subfr ], 16 );
/* Scale long-term shaping state */
for( i = NSQ->sLTP_shp_buf_idx - psEncC->ltp_mem_length; i < NSQ->sLTP_shp_buf_idx; i++ ) {
NSQ->sLTP_shp_Q14[ i ] = silk_SMULWW( gain_adj_Q16, NSQ->sLTP_shp_Q14[ i ] );
}
/* Scale long-term prediction state */
if( signal_type == TYPE_VOICED && NSQ->rewhite_flag == 0 ) {
for( i = NSQ->sLTP_buf_idx - lag - LTP_ORDER / 2; i < NSQ->sLTP_buf_idx - decisionDelay; i++ ) {
sLTP_Q15[ i ] = silk_SMULWW( gain_adj_Q16, sLTP_Q15[ i ] );
}
}
for( k = 0; k < nStatesDelayedDecision; k++ ) {
psDD = &psDelDec[ k ];
/* Scale scalar states */
psDD->LF_AR_Q14 = silk_SMULWW( gain_adj_Q16, psDD->LF_AR_Q14 );
psDD->Diff_Q14 = silk_SMULWW( gain_adj_Q16, psDD->Diff_Q14 );
/* Scale short-term prediction and shaping states */
for( i = 0; i < NSQ_LPC_BUF_LENGTH; i++ ) {
psDD->sLPC_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sLPC_Q14[ i ] );
}
for( i = 0; i < MAX_SHAPE_LPC_ORDER; i++ ) {
psDD->sAR2_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->sAR2_Q14[ i ] );
}
for( i = 0; i < DECISION_DELAY; i++ ) {
psDD->Pred_Q15[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Pred_Q15[ i ] );
psDD->Shape_Q14[ i ] = silk_SMULWW( gain_adj_Q16, psDD->Shape_Q14[ i ] );
}
}
/* Save inverse gain */
NSQ->prev_gain_Q16 = Gains_Q16[ subfr ];
}
}

View File

@@ -0,0 +1,448 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include "main.h"
#include "../celt/stack_alloc.h"
#include "PLC.h"
#define NB_ATT 2
static const opus_int16 HARM_ATT_Q15[NB_ATT] = { 32440, 31130 }; /* 0.99, 0.95 */
static const opus_int16 PLC_RAND_ATTENUATE_V_Q15[NB_ATT] = { 31130, 26214 }; /* 0.95, 0.8 */
static const opus_int16 PLC_RAND_ATTENUATE_UV_Q15[NB_ATT] = { 32440, 29491 }; /* 0.99, 0.9 */
static OPUS_INLINE void silk_PLC_update(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl /* I/O Decoder control */
);
static OPUS_INLINE void silk_PLC_conceal(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* O LPC residual signal */
int arch /* I Run-time architecture */
);
void silk_PLC_Reset(
silk_decoder_state *psDec /* I/O Decoder state */
)
{
psDec->sPLC.pitchL_Q8 = silk_LSHIFT( psDec->frame_length, 8 - 1 );
psDec->sPLC.prevGain_Q16[ 0 ] = SILK_FIX_CONST( 1, 16 );
psDec->sPLC.prevGain_Q16[ 1 ] = SILK_FIX_CONST( 1, 16 );
psDec->sPLC.subfr_length = 20;
psDec->sPLC.nb_subfr = 2;
}
void silk_PLC(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost, /* I Loss flag */
int arch /* I Run-time architecture */
)
{
/* PLC control function */
if( psDec->fs_kHz != psDec->sPLC.fs_kHz ) {
silk_PLC_Reset( psDec );
psDec->sPLC.fs_kHz = psDec->fs_kHz;
}
if( lost ) {
/****************************/
/* Generate Signal */
/****************************/
silk_PLC_conceal( psDec, psDecCtrl, frame, arch );
psDec->lossCnt++;
} else {
/****************************/
/* Update state */
/****************************/
silk_PLC_update( psDec, psDecCtrl );
}
}
/**************************************************/
/* Update state of PLC */
/**************************************************/
static OPUS_INLINE void silk_PLC_update(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl /* I/O Decoder control */
)
{
opus_int32 LTP_Gain_Q14, temp_LTP_Gain_Q14;
opus_int i, j;
silk_PLC_struct *psPLC;
psPLC = &psDec->sPLC;
/* Update parameters used in case of packet loss */
psDec->prevSignalType = psDec->indices.signalType;
LTP_Gain_Q14 = 0;
if( psDec->indices.signalType == TYPE_VOICED ) {
/* Find the parameters for the last subframe which contains a pitch pulse */
for( j = 0; j * psDec->subfr_length < psDecCtrl->pitchL[ psDec->nb_subfr - 1 ]; j++ ) {
if( j == psDec->nb_subfr ) {
break;
}
temp_LTP_Gain_Q14 = 0;
for( i = 0; i < LTP_ORDER; i++ ) {
temp_LTP_Gain_Q14 += psDecCtrl->LTPCoef_Q14[ ( psDec->nb_subfr - 1 - j ) * LTP_ORDER + i ];
}
if( temp_LTP_Gain_Q14 > LTP_Gain_Q14 ) {
LTP_Gain_Q14 = temp_LTP_Gain_Q14;
silk_memcpy( psPLC->LTPCoef_Q14,
&psDecCtrl->LTPCoef_Q14[ silk_SMULBB( psDec->nb_subfr - 1 - j, LTP_ORDER ) ],
LTP_ORDER * sizeof( opus_int16 ) );
psPLC->pitchL_Q8 = silk_LSHIFT( psDecCtrl->pitchL[ psDec->nb_subfr - 1 - j ], 8 );
}
}
silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ) );
psPLC->LTPCoef_Q14[ LTP_ORDER / 2 ] = LTP_Gain_Q14;
/* Limit LT coefs */
if( LTP_Gain_Q14 < V_PITCH_GAIN_START_MIN_Q14 ) {
opus_int scale_Q10;
opus_int32 tmp;
tmp = silk_LSHIFT( V_PITCH_GAIN_START_MIN_Q14, 10 );
scale_Q10 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
for( i = 0; i < LTP_ORDER; i++ ) {
psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q10 ), 10 );
}
} else if( LTP_Gain_Q14 > V_PITCH_GAIN_START_MAX_Q14 ) {
opus_int scale_Q14;
opus_int32 tmp;
tmp = silk_LSHIFT( V_PITCH_GAIN_START_MAX_Q14, 14 );
scale_Q14 = silk_DIV32( tmp, silk_max( LTP_Gain_Q14, 1 ) );
for( i = 0; i < LTP_ORDER; i++ ) {
psPLC->LTPCoef_Q14[ i ] = silk_RSHIFT( silk_SMULBB( psPLC->LTPCoef_Q14[ i ], scale_Q14 ), 14 );
}
}
} else {
psPLC->pitchL_Q8 = silk_LSHIFT( silk_SMULBB( psDec->fs_kHz, 18 ), 8 );
silk_memset( psPLC->LTPCoef_Q14, 0, LTP_ORDER * sizeof( opus_int16 ));
}
/* Save LPC coeficients */
silk_memcpy( psPLC->prevLPC_Q12, psDecCtrl->PredCoef_Q12[ 1 ], psDec->LPC_order * sizeof( opus_int16 ) );
psPLC->prevLTP_scale_Q14 = psDecCtrl->LTP_scale_Q14;
/* Save last two gains */
silk_memcpy( psPLC->prevGain_Q16, &psDecCtrl->Gains_Q16[ psDec->nb_subfr - 2 ], 2 * sizeof( opus_int32 ) );
psPLC->subfr_length = psDec->subfr_length;
psPLC->nb_subfr = psDec->nb_subfr;
}
static OPUS_INLINE void silk_PLC_energy(opus_int32 *energy1, opus_int *shift1, opus_int32 *energy2, opus_int *shift2,
const opus_int32 *exc_Q14, const opus_int32 *prevGain_Q10, int subfr_length, int nb_subfr)
{
int i, k;
VARDECL( opus_int16, exc_buf );
opus_int16 *exc_buf_ptr;
SAVE_STACK;
ALLOC( exc_buf, 2*subfr_length, opus_int16 );
/* Find random noise component */
/* Scale previous excitation signal */
exc_buf_ptr = exc_buf;
for( k = 0; k < 2; k++ ) {
for( i = 0; i < subfr_length; i++ ) {
exc_buf_ptr[ i ] = (opus_int16)silk_SAT16( silk_RSHIFT(
silk_SMULWW( exc_Q14[ i + ( k + nb_subfr - 2 ) * subfr_length ], prevGain_Q10[ k ] ), 8 ) );
}
exc_buf_ptr += subfr_length;
}
/* Find the subframe with lowest energy of the last two and use that as random noise generator */
silk_sum_sqr_shift( energy1, shift1, exc_buf, subfr_length );
silk_sum_sqr_shift( energy2, shift2, &exc_buf[ subfr_length ], subfr_length );
RESTORE_STACK;
}
static OPUS_INLINE void silk_PLC_conceal(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* O LPC residual signal */
int arch /* I Run-time architecture */
)
{
opus_int i, j, k;
opus_int lag, idx, sLTP_buf_idx, shift1, shift2;
opus_int32 rand_seed, harm_Gain_Q15, rand_Gain_Q15, inv_gain_Q30;
opus_int32 energy1, energy2, *rand_ptr, *pred_lag_ptr;
opus_int32 LPC_pred_Q10, LTP_pred_Q12;
opus_int16 rand_scale_Q14;
opus_int16 *B_Q14;
opus_int32 *sLPC_Q14_ptr;
opus_int16 A_Q12[ MAX_LPC_ORDER ];
#ifdef SMALL_FOOTPRINT
opus_int16 *sLTP;
#else
VARDECL( opus_int16, sLTP );
#endif
VARDECL( opus_int32, sLTP_Q14 );
silk_PLC_struct *psPLC = &psDec->sPLC;
opus_int32 prevGain_Q10[2];
SAVE_STACK;
ALLOC( sLTP_Q14, psDec->ltp_mem_length + psDec->frame_length, opus_int32 );
#ifdef SMALL_FOOTPRINT
/* Ugly hack that breaks aliasing rules to save stack: put sLTP at the very end of sLTP_Q14. */
sLTP = ((opus_int16*)&sLTP_Q14[psDec->ltp_mem_length + psDec->frame_length])-psDec->ltp_mem_length;
#else
ALLOC( sLTP, psDec->ltp_mem_length, opus_int16 );
#endif
prevGain_Q10[0] = silk_RSHIFT( psPLC->prevGain_Q16[ 0 ], 6);
prevGain_Q10[1] = silk_RSHIFT( psPLC->prevGain_Q16[ 1 ], 6);
if( psDec->first_frame_after_reset ) {
silk_memset( psPLC->prevLPC_Q12, 0, sizeof( psPLC->prevLPC_Q12 ) );
}
silk_PLC_energy(&energy1, &shift1, &energy2, &shift2, psDec->exc_Q14, prevGain_Q10, psDec->subfr_length, psDec->nb_subfr);
if( silk_RSHIFT( energy1, shift2 ) < silk_RSHIFT( energy2, shift1 ) ) {
/* First sub-frame has lowest energy */
rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, ( psPLC->nb_subfr - 1 ) * psPLC->subfr_length - RAND_BUF_SIZE ) ];
} else {
/* Second sub-frame has lowest energy */
rand_ptr = &psDec->exc_Q14[ silk_max_int( 0, psPLC->nb_subfr * psPLC->subfr_length - RAND_BUF_SIZE ) ];
}
/* Set up Gain to random noise component */
B_Q14 = psPLC->LTPCoef_Q14;
rand_scale_Q14 = psPLC->randScale_Q14;
/* Set up attenuation gains */
harm_Gain_Q15 = HARM_ATT_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
if( psDec->prevSignalType == TYPE_VOICED ) {
rand_Gain_Q15 = PLC_RAND_ATTENUATE_V_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
} else {
rand_Gain_Q15 = PLC_RAND_ATTENUATE_UV_Q15[ silk_min_int( NB_ATT - 1, psDec->lossCnt ) ];
}
/* LPC concealment. Apply BWE to previous LPC */
silk_bwexpander( psPLC->prevLPC_Q12, psDec->LPC_order, SILK_FIX_CONST( BWE_COEF, 16 ) );
/* Preload LPC coeficients to array on stack. Gives small performance gain */
silk_memcpy( A_Q12, psPLC->prevLPC_Q12, psDec->LPC_order * sizeof( opus_int16 ) );
/* First Lost frame */
if( psDec->lossCnt == 0 ) {
rand_scale_Q14 = 1 << 14;
/* Reduce random noise Gain for voiced frames */
if( psDec->prevSignalType == TYPE_VOICED ) {
for( i = 0; i < LTP_ORDER; i++ ) {
rand_scale_Q14 -= B_Q14[ i ];
}
rand_scale_Q14 = silk_max_16( 3277, rand_scale_Q14 ); /* 0.2 */
rand_scale_Q14 = (opus_int16)silk_RSHIFT( silk_SMULBB( rand_scale_Q14, psPLC->prevLTP_scale_Q14 ), 14 );
} else {
/* Reduce random noise for unvoiced frames with high LPC gain */
opus_int32 invGain_Q30, down_scale_Q30;
invGain_Q30 = silk_LPC_inverse_pred_gain( psPLC->prevLPC_Q12, psDec->LPC_order, arch );
down_scale_Q30 = silk_min_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_HIGH_THRES ), invGain_Q30 );
down_scale_Q30 = silk_max_32( silk_RSHIFT( (opus_int32)1 << 30, LOG2_INV_LPC_GAIN_LOW_THRES ), down_scale_Q30 );
down_scale_Q30 = silk_LSHIFT( down_scale_Q30, LOG2_INV_LPC_GAIN_HIGH_THRES );
rand_Gain_Q15 = silk_RSHIFT( silk_SMULWB( down_scale_Q30, rand_Gain_Q15 ), 14 );
}
}
rand_seed = psPLC->rand_seed;
lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
sLTP_buf_idx = psDec->ltp_mem_length;
/* Rewhiten LTP state */
idx = psDec->ltp_mem_length - lag - psDec->LPC_order - LTP_ORDER / 2;
celt_assert( idx > 0 );
silk_LPC_analysis_filter( &sLTP[ idx ], &psDec->outBuf[ idx ], A_Q12, psDec->ltp_mem_length - idx, psDec->LPC_order, arch );
/* Scale LTP state */
inv_gain_Q30 = silk_INVERSE32_varQ( psPLC->prevGain_Q16[ 1 ], 46 );
inv_gain_Q30 = silk_min( inv_gain_Q30, silk_int32_MAX >> 1 );
for( i = idx + psDec->LPC_order; i < psDec->ltp_mem_length; i++ ) {
sLTP_Q14[ i ] = silk_SMULWB( inv_gain_Q30, sLTP[ i ] );
}
/***************************/
/* LTP synthesis filtering */
/***************************/
for( k = 0; k < psDec->nb_subfr; k++ ) {
/* Set up pointer */
pred_lag_ptr = &sLTP_Q14[ sLTP_buf_idx - lag + LTP_ORDER / 2 ];
for( i = 0; i < psDec->subfr_length; i++ ) {
/* Unrolled loop */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LTP_pred_Q12 = 2;
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ 0 ], B_Q14[ 0 ] );
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -1 ], B_Q14[ 1 ] );
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -2 ], B_Q14[ 2 ] );
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -3 ], B_Q14[ 3 ] );
LTP_pred_Q12 = silk_SMLAWB( LTP_pred_Q12, pred_lag_ptr[ -4 ], B_Q14[ 4 ] );
pred_lag_ptr++;
/* Generate LPC excitation */
rand_seed = silk_RAND( rand_seed );
idx = silk_RSHIFT( rand_seed, 25 ) & RAND_BUF_MASK;
sLTP_Q14[ sLTP_buf_idx ] = silk_LSHIFT32( silk_SMLAWB( LTP_pred_Q12, rand_ptr[ idx ], rand_scale_Q14 ), 2 );
sLTP_buf_idx++;
}
/* Gradually reduce LTP gain */
for( j = 0; j < LTP_ORDER; j++ ) {
B_Q14[ j ] = silk_RSHIFT( silk_SMULBB( harm_Gain_Q15, B_Q14[ j ] ), 15 );
}
if ( psDec->indices.signalType != TYPE_NO_VOICE_ACTIVITY ) {
/* Gradually reduce excitation gain */
rand_scale_Q14 = silk_RSHIFT( silk_SMULBB( rand_scale_Q14, rand_Gain_Q15 ), 15 );
}
/* Slowly increase pitch lag */
psPLC->pitchL_Q8 = silk_SMLAWB( psPLC->pitchL_Q8, psPLC->pitchL_Q8, PITCH_DRIFT_FAC_Q16 );
psPLC->pitchL_Q8 = silk_min_32( psPLC->pitchL_Q8, silk_LSHIFT( silk_SMULBB( MAX_PITCH_LAG_MS, psDec->fs_kHz ), 8 ) );
lag = silk_RSHIFT_ROUND( psPLC->pitchL_Q8, 8 );
}
/***************************/
/* LPC synthesis filtering */
/***************************/
sLPC_Q14_ptr = &sLTP_Q14[ psDec->ltp_mem_length - MAX_LPC_ORDER ];
/* Copy LPC state */
silk_memcpy( sLPC_Q14_ptr, psDec->sLPC_Q14_buf, MAX_LPC_ORDER * sizeof( opus_int32 ) );
celt_assert( psDec->LPC_order >= 10 ); /* check that unrolling works */
for( i = 0; i < psDec->frame_length; i++ ) {
/* partly unrolled */
/* Avoids introducing a bias because silk_SMLAWB() always rounds to -inf */
LPC_pred_Q10 = silk_RSHIFT( psDec->LPC_order, 1 );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 1 ], A_Q12[ 0 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 2 ], A_Q12[ 1 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 3 ], A_Q12[ 2 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 4 ], A_Q12[ 3 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 5 ], A_Q12[ 4 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 6 ], A_Q12[ 5 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 7 ], A_Q12[ 6 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 8 ], A_Q12[ 7 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 9 ], A_Q12[ 8 ] );
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - 10 ], A_Q12[ 9 ] );
for( j = 10; j < psDec->LPC_order; j++ ) {
LPC_pred_Q10 = silk_SMLAWB( LPC_pred_Q10, sLPC_Q14_ptr[ MAX_LPC_ORDER + i - j - 1 ], A_Q12[ j ] );
}
/* Add prediction to LPC excitation */
sLPC_Q14_ptr[ MAX_LPC_ORDER + i ] = silk_ADD_SAT32( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ],
silk_LSHIFT_SAT32( LPC_pred_Q10, 4 ));
/* Scale with Gain */
frame[ i ] = (opus_int16)silk_SAT16( silk_SAT16( silk_RSHIFT_ROUND( silk_SMULWW( sLPC_Q14_ptr[ MAX_LPC_ORDER + i ], prevGain_Q10[ 1 ] ), 8 ) ) );
}
/* Save LPC state */
silk_memcpy( psDec->sLPC_Q14_buf, &sLPC_Q14_ptr[ psDec->frame_length ], MAX_LPC_ORDER * sizeof( opus_int32 ) );
/**************************************/
/* Update states */
/**************************************/
psPLC->rand_seed = rand_seed;
psPLC->randScale_Q14 = rand_scale_Q14;
for( i = 0; i < MAX_NB_SUBFR; i++ ) {
psDecCtrl->pitchL[ i ] = lag;
}
RESTORE_STACK;
}
/* Glues concealed frames with new good received frames */
void silk_PLC_glue_frames(
silk_decoder_state *psDec, /* I/O decoder state */
opus_int16 frame[], /* I/O signal */
opus_int length /* I length of signal */
)
{
opus_int i, energy_shift;
opus_int32 energy;
silk_PLC_struct *psPLC;
psPLC = &psDec->sPLC;
if( psDec->lossCnt ) {
/* Calculate energy in concealed residual */
silk_sum_sqr_shift( &psPLC->conc_energy, &psPLC->conc_energy_shift, frame, length );
psPLC->last_frame_lost = 1;
} else {
if( psDec->sPLC.last_frame_lost ) {
/* Calculate residual in decoded signal if last frame was lost */
silk_sum_sqr_shift( &energy, &energy_shift, frame, length );
/* Normalize energies */
if( energy_shift > psPLC->conc_energy_shift ) {
psPLC->conc_energy = silk_RSHIFT( psPLC->conc_energy, energy_shift - psPLC->conc_energy_shift );
} else if( energy_shift < psPLC->conc_energy_shift ) {
energy = silk_RSHIFT( energy, psPLC->conc_energy_shift - energy_shift );
}
/* Fade in the energy difference */
if( energy > psPLC->conc_energy ) {
opus_int32 frac_Q24, LZ;
opus_int32 gain_Q16, slope_Q16;
LZ = silk_CLZ32( psPLC->conc_energy );
LZ = LZ - 1;
psPLC->conc_energy = silk_LSHIFT( psPLC->conc_energy, LZ );
energy = silk_RSHIFT( energy, silk_max_32( 24 - LZ, 0 ) );
frac_Q24 = silk_DIV32( psPLC->conc_energy, silk_max( energy, 1 ) );
gain_Q16 = silk_LSHIFT( silk_SQRT_APPROX( frac_Q24 ), 4 );
slope_Q16 = silk_DIV32_16( ( (opus_int32)1 << 16 ) - gain_Q16, length );
/* Make slope 4x steeper to avoid missing onsets after DTX */
slope_Q16 = silk_LSHIFT( slope_Q16, 2 );
for( i = 0; i < length; i++ ) {
frame[ i ] = silk_SMULWB( gain_Q16, frame[ i ] );
gain_Q16 += slope_Q16;
if( gain_Q16 > (opus_int32)1 << 16 ) {
break;
}
}
}
}
psPLC->last_frame_lost = 0;
}
}

View File

@@ -0,0 +1,62 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
#ifndef SILK_PLC_H
#define SILK_PLC_H
#include "main.h"
#define BWE_COEF 0.99
#define V_PITCH_GAIN_START_MIN_Q14 11469 /* 0.7 in Q14 */
#define V_PITCH_GAIN_START_MAX_Q14 15565 /* 0.95 in Q14 */
#define MAX_PITCH_LAG_MS 18
#define RAND_BUF_SIZE 128
#define RAND_BUF_MASK ( RAND_BUF_SIZE - 1 )
#define LOG2_INV_LPC_GAIN_HIGH_THRES 3 /* 2^3 = 8 dB LPC gain */
#define LOG2_INV_LPC_GAIN_LOW_THRES 8 /* 2^8 = 24 dB LPC gain */
#define PITCH_DRIFT_FAC_Q16 655 /* 0.01 in Q16 */
void silk_PLC_Reset(
silk_decoder_state *psDec /* I/O Decoder state */
);
void silk_PLC(
silk_decoder_state *psDec, /* I/O Decoder state */
silk_decoder_control *psDecCtrl, /* I/O Decoder control */
opus_int16 frame[], /* I/O signal */
opus_int lost, /* I Loss flag */
int arch /* I Run-time architecture */
);
void silk_PLC_glue_frames(
silk_decoder_state *psDec, /* I/O decoder state */
opus_int16 frame[], /* I/O signal */
opus_int length /* I length of signal */
);
#endif

View File

@@ -0,0 +1,641 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
#ifndef SILK_SIGPROC_FIX_H
#define SILK_SIGPROC_FIX_H
#ifdef __cplusplus
extern "C"
{
#endif
/*#define silk_MACRO_COUNT */ /* Used to enable WMOPS counting */
#define SILK_MAX_ORDER_LPC 24 /* max order of the LPC analysis in schur() and k2a() */
#include <string.h> /* for memset(), memcpy(), memmove() */
#include "typedef.h"
#include "resampler_structs.h"
#include "macros.h"
#include "../celt/cpu_support.h"
#if defined(OPUS_X86_MAY_HAVE_SSE4_1)
#include "x86/SigProc_FIX_sse.h"
#endif
#if (defined(OPUS_ARM_ASM) || defined(OPUS_ARM_MAY_HAVE_NEON_INTR))
#include "arm/biquad_alt_arm.h"
#include "arm/LPC_inv_pred_gain_arm.h"
#endif
/********************************************************************/
/* SIGNAL PROCESSING FUNCTIONS */
/********************************************************************/
/*!
* Initialize/reset the resampler state for a given pair of input/output sampling rates
*/
opus_int silk_resampler_init(
silk_resampler_state_struct *S, /* I/O Resampler state */
opus_int32 Fs_Hz_in, /* I Input sampling rate (Hz) */
opus_int32 Fs_Hz_out, /* I Output sampling rate (Hz) */
opus_int forEnc /* I If 1: encoder; if 0: decoder */
);
/*!
* Resampler: convert from one sampling rate to another
*/
opus_int silk_resampler(
silk_resampler_state_struct *S, /* I/O Resampler state */
opus_int16 out[], /* O Output signal */
const opus_int16 in[], /* I Input signal */
opus_int32 inLen /* I Number of input samples */
);
/*!
* Downsample 2x, mediocre quality
*/
void silk_resampler_down2(
opus_int32 *S, /* I/O State vector [ 2 ] */
opus_int16 *out, /* O Output signal [ len ] */
const opus_int16 *in, /* I Input signal [ floor(len/2) ] */
opus_int32 inLen /* I Number of input samples */
);
/*!
* Downsample by a factor 2/3, low quality
*/
void silk_resampler_down2_3(
opus_int32 *S, /* I/O State vector [ 6 ] */
opus_int16 *out, /* O Output signal [ floor(2*inLen/3) ] */
const opus_int16 *in, /* I Input signal [ inLen ] */
opus_int32 inLen /* I Number of input samples */
);
/*!
* second order ARMA filter;
* slower than biquad() but uses more precise coefficients
* can handle (slowly) varying coefficients
*/
void silk_biquad_alt_stride1(
const opus_int16 *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [2] */
opus_int16 *out, /* O output signal */
const opus_int32 len /* I signal length (must be even) */
);
void silk_biquad_alt_stride2_c(
const opus_int16 *in, /* I input signal */
const opus_int32 *B_Q28, /* I MA coefficients [3] */
const opus_int32 *A_Q28, /* I AR coefficients [2] */
opus_int32 *S, /* I/O State vector [4] */
opus_int16 *out, /* O output signal */
const opus_int32 len /* I signal length (must be even) */
);
/* Variable order MA prediction error filter. */
void silk_LPC_analysis_filter(
opus_int16 *out, /* O Output signal */
const opus_int16 *in, /* I Input signal */
const opus_int16 *B, /* I MA prediction coefficients, Q12 [order] */
const opus_int32 len, /* I Signal length */
const opus_int32 d, /* I Filter order */
int arch /* I Run-time architecture */
);
/* Chirp (bandwidth expand) LP AR filter */
void silk_bwexpander(
opus_int16 *ar, /* I/O AR filter to be expanded (without leading 1) */
const opus_int d, /* I Length of ar */
opus_int32 chirp_Q16 /* I Chirp factor (typically in the range 0 to 1) */
);
/* Chirp (bandwidth expand) LP AR filter */
void silk_bwexpander_32(
opus_int32 *ar, /* I/O AR filter to be expanded (without leading 1) */
const opus_int d, /* I Length of ar */
opus_int32 chirp_Q16 /* I Chirp factor in Q16 */
);
/* Compute inverse of LPC prediction gain, and */
/* test if LPC coefficients are stable (all poles within unit circle) */
opus_int32 silk_LPC_inverse_pred_gain_c( /* O Returns inverse prediction gain in energy domain, Q30 */
const opus_int16 *A_Q12, /* I Prediction coefficients, Q12 [order] */
const opus_int order /* I Prediction order */
);
/* Split signal in two decimated bands using first-order allpass filters */
void silk_ana_filt_bank_1(
const opus_int16 *in, /* I Input signal [N] */
opus_int32 *S, /* I/O State vector [2] */
opus_int16 *outL, /* O Low band [N/2] */
opus_int16 *outH, /* O High band [N/2] */
const opus_int32 N /* I Number of input samples */
);
#if !defined(OVERRIDE_silk_biquad_alt_stride2)
#define silk_biquad_alt_stride2(in, B_Q28, A_Q28, S, out, len, arch) ((void)(arch), silk_biquad_alt_stride2_c(in, B_Q28, A_Q28, S, out, len))
#endif
#if !defined(OVERRIDE_silk_LPC_inverse_pred_gain)
#define silk_LPC_inverse_pred_gain(A_Q12, order, arch) ((void)(arch), silk_LPC_inverse_pred_gain_c(A_Q12, order))
#endif
/********************************************************************/
/* SCALAR FUNCTIONS */
/********************************************************************/
/* Approximation of 128 * log2() (exact inverse of approx 2^() below) */
/* Convert input to a log scale */
opus_int32 silk_lin2log(
const opus_int32 inLin /* I input in linear scale */
);
/* Approximation of a sigmoid function */
opus_int silk_sigm_Q15(
opus_int in_Q5 /* I */
);
/* Approximation of 2^() (exact inverse of approx log2() above) */
/* Convert input to a linear scale */
opus_int32 silk_log2lin(
const opus_int32 inLog_Q7 /* I input on log scale */
);
/* Compute number of bits to right shift the sum of squares of a vector */
/* of int16s to make it fit in an int32 */
void silk_sum_sqr_shift(
opus_int32 *energy, /* O Energy of x, after shifting to the right */
opus_int *shift, /* O Number of bits right shift applied to energy */
const opus_int16 *x, /* I Input vector */
opus_int len /* I Length of input vector */
);
/* Calculates the reflection coefficients from the correlation sequence */
/* Faster than schur64(), but much less accurate. */
/* uses SMLAWB(), requiring armv5E and higher. */
opus_int32 silk_schur( /* O Returns residual energy */
opus_int16 *rc_Q15, /* O reflection coefficients [order] Q15 */
const opus_int32 *c, /* I correlations [order+1] */
const opus_int32 order /* I prediction order */
);
/* Calculates the reflection coefficients from the correlation sequence */
/* Slower than schur(), but more accurate. */
/* Uses SMULL(), available on armv4 */
opus_int32 silk_schur64( /* O returns residual energy */
opus_int32 rc_Q16[], /* O Reflection coefficients [order] Q16 */
const opus_int32 c[], /* I Correlations [order+1] */
opus_int32 order /* I Prediction order */
);
/* Step up function, converts reflection coefficients to prediction coefficients */
void silk_k2a(
opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */
const opus_int16 *rc_Q15, /* I Reflection coefficients [order] Q15 */
const opus_int32 order /* I Prediction order */
);
/* Step up function, converts reflection coefficients to prediction coefficients */
void silk_k2a_Q16(
opus_int32 *A_Q24, /* O Prediction coefficients [order] Q24 */
const opus_int32 *rc_Q16, /* I Reflection coefficients [order] Q16 */
const opus_int32 order /* I Prediction order */
);
/* Apply sine window to signal vector. */
/* Window types: */
/* 1 -> sine window from 0 to pi/2 */
/* 2 -> sine window from pi/2 to pi */
/* every other sample of window is linearly interpolated, for speed */
void silk_apply_sine_window(
opus_int16 px_win[], /* O Pointer to windowed signal */
const opus_int16 px[], /* I Pointer to input signal */
const opus_int win_type, /* I Selects a window type */
const opus_int length /* I Window length, multiple of 4 */
);
/* Compute autocorrelation */
void silk_autocorr(
opus_int32 *results, /* O Result (length correlationCount) */
opus_int *scale, /* O Scaling of the correlation vector */
const opus_int16 *inputData, /* I Input data to correlate */
const opus_int inputDataSize, /* I Length of input */
const opus_int correlationCount, /* I Number of correlation taps to compute */
int arch /* I Run-time architecture */
);
void silk_decode_pitch(
opus_int16 lagIndex, /* I */
opus_int8 contourIndex, /* O */
opus_int pitch_lags[], /* O 4 pitch values */
const opus_int Fs_kHz, /* I sampling frequency (kHz) */
const opus_int nb_subfr /* I number of sub frames */
);
opus_int silk_pitch_analysis_core( /* O Voicing estimate: 0 voiced, 1 unvoiced */
const opus_int16 *frame, /* I Signal of length PE_FRAME_LENGTH_MS*Fs_kHz */
opus_int *pitch_out, /* O 4 pitch lag values */
opus_int16 *lagIndex, /* O Lag Index */
opus_int8 *contourIndex, /* O Pitch contour Index */
opus_int *LTPCorr_Q15, /* I/O Normalized correlation; input: value from previous frame */
opus_int prevLag, /* I Last lag of previous frame; set to zero is unvoiced */
const opus_int32 search_thres1_Q16, /* I First stage threshold for lag candidates 0 - 1 */
const opus_int search_thres2_Q13, /* I Final threshold for lag candidates 0 - 1 */
const opus_int Fs_kHz, /* I Sample frequency (kHz) */
const opus_int complexity, /* I Complexity setting, 0-2, where 2 is highest */
const opus_int nb_subfr, /* I number of 5 ms subframes */
int arch /* I Run-time architecture */
);
/* Compute Normalized Line Spectral Frequencies (NLSFs) from whitening filter coefficients */
/* If not all roots are found, the a_Q16 coefficients are bandwidth expanded until convergence. */
void silk_A2NLSF(
opus_int16 *NLSF, /* O Normalized Line Spectral Frequencies in Q15 (0..2^15-1) [d] */
opus_int32 *a_Q16, /* I/O Monic whitening filter coefficients in Q16 [d] */
const opus_int d /* I Filter order (must be even) */
);
/* compute whitening filter coefficients from normalized line spectral frequencies */
void silk_NLSF2A(
opus_int16 *a_Q12, /* O monic whitening filter coefficients in Q12, [ d ] */
const opus_int16 *NLSF, /* I normalized line spectral frequencies in Q15, [ d ] */
const opus_int d, /* I filter order (should be even) */
int arch /* I Run-time architecture */
);
/* Convert int32 coefficients to int16 coefs and make sure there's no wrap-around */
void silk_LPC_fit(
opus_int16 *a_QOUT, /* O Output signal */
opus_int32 *a_QIN, /* I/O Input signal */
const opus_int QOUT, /* I Input Q domain */
const opus_int QIN, /* I Input Q domain */
const opus_int d /* I Filter order */
);
void silk_insertion_sort_increasing(
opus_int32 *a, /* I/O Unsorted / Sorted vector */
opus_int *idx, /* O Index vector for the sorted elements */
const opus_int L, /* I Vector length */
const opus_int K /* I Number of correctly sorted positions */
);
void silk_insertion_sort_decreasing_int16(
opus_int16 *a, /* I/O Unsorted / Sorted vector */
opus_int *idx, /* O Index vector for the sorted elements */
const opus_int L, /* I Vector length */
const opus_int K /* I Number of correctly sorted positions */
);
void silk_insertion_sort_increasing_all_values_int16(
opus_int16 *a, /* I/O Unsorted / Sorted vector */
const opus_int L /* I Vector length */
);
/* NLSF stabilizer, for a single input data vector */
void silk_NLSF_stabilize(
opus_int16 *NLSF_Q15, /* I/O Unstable/stabilized normalized LSF vector in Q15 [L] */
const opus_int16 *NDeltaMin_Q15, /* I Min distance vector, NDeltaMin_Q15[L] must be >= 1 [L+1] */
const opus_int L /* I Number of NLSF parameters in the input vector */
);
/* Laroia low complexity NLSF weights */
void silk_NLSF_VQ_weights_laroia(
opus_int16 *pNLSFW_Q_OUT, /* O Pointer to input vector weights [D] */
const opus_int16 *pNLSF_Q15, /* I Pointer to input vector [D] */
const opus_int D /* I Input vector dimension (even) */
);
/* Compute reflection coefficients from input signal */
void silk_burg_modified_c(
opus_int32 *res_nrg, /* O Residual energy */
opus_int *res_nrg_Q, /* O Residual energy Q value */
opus_int32 A_Q16[], /* O Prediction coefficients (length order) */
const opus_int16 x[], /* I Input signal, length: nb_subfr * ( D + subfr_length ) */
const opus_int32 minInvGain_Q30, /* I Inverse of max prediction gain */
const opus_int subfr_length, /* I Input signal subframe length (incl. D preceding samples) */
const opus_int nb_subfr, /* I Number of subframes stacked in x */
const opus_int D, /* I Order */
int arch /* I Run-time architecture */
);
/* Copy and multiply a vector by a constant */
void silk_scale_copy_vector16(
opus_int16 *data_out,
const opus_int16 *data_in,
opus_int32 gain_Q16, /* I Gain in Q16 */
const opus_int dataSize /* I Length */
);
/* Some for the LTP related function requires Q26 to work.*/
void silk_scale_vector32_Q26_lshift_18(
opus_int32 *data1, /* I/O Q0/Q18 */
opus_int32 gain_Q26, /* I Q26 */
opus_int dataSize /* I length */
);
/********************************************************************/
/* INLINE ARM MATH */
/********************************************************************/
/* return sum( inVec1[i] * inVec2[i] ) */
opus_int32 silk_inner_prod_aligned(
const opus_int16 *const inVec1, /* I input vector 1 */
const opus_int16 *const inVec2, /* I input vector 2 */
const opus_int len, /* I vector lengths */
int arch /* I Run-time architecture */
);
opus_int32 silk_inner_prod_aligned_scale(
const opus_int16 *const inVec1, /* I input vector 1 */
const opus_int16 *const inVec2, /* I input vector 2 */
const opus_int scale, /* I number of bits to shift */
const opus_int len /* I vector lengths */
);
opus_int64 silk_inner_prod16_aligned_64_c(
const opus_int16 *inVec1, /* I input vector 1 */
const opus_int16 *inVec2, /* I input vector 2 */
const opus_int len /* I vector lengths */
);
/********************************************************************/
/* MACROS */
/********************************************************************/
/* Rotate a32 right by 'rot' bits. Negative rot values result in rotating
left. Output is 32bit int.
Note: contemporary compilers recognize the C expression below and
compile it into a 'ror' instruction if available. No need for OPUS_INLINE ASM! */
static OPUS_INLINE opus_int32 silk_ROR32( opus_int32 a32, opus_int rot )
{
opus_uint32 x = (opus_uint32) a32;
opus_uint32 r = (opus_uint32) rot;
opus_uint32 m = (opus_uint32) -rot;
if( rot == 0 ) {
return a32;
} else if( rot < 0 ) {
return (opus_int32) ((x << m) | (x >> (32 - m)));
} else {
return (opus_int32) ((x << (32 - r)) | (x >> r));
}
}
/* Allocate opus_int16 aligned to 4-byte memory address */
#if EMBEDDED_ARM
#define silk_DWORD_ALIGN __attribute__((aligned(4)))
#else
#define silk_DWORD_ALIGN
#endif
/* Useful Macros that can be adjusted to other platforms */
#define silk_memcpy(dest, src, size) memcpy((dest), (src), (size))
#define silk_memset(dest, src, size) memset((dest), (src), (size))
#define silk_memmove(dest, src, size) memmove((dest), (src), (size))
/* Fixed point macros */
/* (a32 * b32) output have to be 32bit int */
#define silk_MUL(a32, b32) ((a32) * (b32))
/* (a32 * b32) output have to be 32bit uint */
#define silk_MUL_uint(a32, b32) silk_MUL(a32, b32)
/* a32 + (b32 * c32) output have to be 32bit int */
#define silk_MLA(a32, b32, c32) silk_ADD32((a32),((b32) * (c32)))
/* a32 + (b32 * c32) output have to be 32bit uint */
#define silk_MLA_uint(a32, b32, c32) silk_MLA(a32, b32, c32)
/* ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
#define silk_SMULTT(a32, b32) (((a32) >> 16) * ((b32) >> 16))
/* a32 + ((a32 >> 16) * (b32 >> 16)) output have to be 32bit int */
#define silk_SMLATT(a32, b32, c32) silk_ADD32((a32),((b32) >> 16) * ((c32) >> 16))
#define silk_SMLALBB(a64, b16, c16) silk_ADD64((a64),(opus_int64)((opus_int32)(b16) * (opus_int32)(c16)))
/* (a32 * b32) */
#define silk_SMULL(a32, b32) ((opus_int64)(a32) * /*(opus_int64)*/(b32))
/* Adds two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
(just standard two's complement implementation-specific behaviour) */
#define silk_ADD32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) + (opus_uint32)(b)))
/* Subtractss two signed 32-bit values in a way that can overflow, while not relying on undefined behaviour
(just standard two's complement implementation-specific behaviour) */
#define silk_SUB32_ovflw(a, b) ((opus_int32)((opus_uint32)(a) - (opus_uint32)(b)))
/* Multiply-accumulate macros that allow overflow in the addition (ie, no asserts in debug mode) */
#define silk_MLA_ovflw(a32, b32, c32) silk_ADD32_ovflw((a32), (opus_uint32)(b32) * (opus_uint32)(c32))
#define silk_SMLABB_ovflw(a32, b32, c32) (silk_ADD32_ovflw((a32) , ((opus_int32)((opus_int16)(b32))) * (opus_int32)((opus_int16)(c32))))
#define silk_DIV32_16(a32, b16) ((opus_int32)((a32) / (b16)))
#define silk_DIV32(a32, b32) ((opus_int32)((a32) / (b32)))
/* These macros enables checking for overflow in silk_API_Debug.h*/
#define silk_ADD16(a, b) ((a) + (b))
#define silk_ADD32(a, b) ((a) + (b))
#define silk_ADD64(a, b) ((a) + (b))
#define silk_SUB16(a, b) ((a) - (b))
#define silk_SUB32(a, b) ((a) - (b))
#define silk_SUB64(a, b) ((a) - (b))
#define silk_SAT8(a) ((a) > silk_int8_MAX ? silk_int8_MAX : \
((a) < silk_int8_MIN ? silk_int8_MIN : (a)))
#define silk_SAT16(a) ((a) > silk_int16_MAX ? silk_int16_MAX : \
((a) < silk_int16_MIN ? silk_int16_MIN : (a)))
#define silk_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : \
((a) < silk_int32_MIN ? silk_int32_MIN : (a)))
#define silk_CHECK_FIT8(a) (a)
#define silk_CHECK_FIT16(a) (a)
#define silk_CHECK_FIT32(a) (a)
#define silk_ADD_SAT16(a, b) (opus_int16)silk_SAT16( silk_ADD32( (opus_int32)(a), (b) ) )
#define silk_ADD_SAT64(a, b) ((((a) + (b)) & 0x8000000000000000LL) == 0 ? \
((((a) & (b)) & 0x8000000000000000LL) != 0 ? silk_int64_MIN : (a)+(b)) : \
((((a) | (b)) & 0x8000000000000000LL) == 0 ? silk_int64_MAX : (a)+(b)) )
#define silk_SUB_SAT16(a, b) (opus_int16)silk_SAT16( silk_SUB32( (opus_int32)(a), (b) ) )
#define silk_SUB_SAT64(a, b) ((((a)-(b)) & 0x8000000000000000LL) == 0 ? \
(( (a) & ((b)^0x8000000000000000LL) & 0x8000000000000000LL) ? silk_int64_MIN : (a)-(b)) : \
((((a)^0x8000000000000000LL) & (b) & 0x8000000000000000LL) ? silk_int64_MAX : (a)-(b)) )
/* Saturation for positive input values */
#define silk_POS_SAT32(a) ((a) > silk_int32_MAX ? silk_int32_MAX : (a))
/* Add with saturation for positive input values */
#define silk_ADD_POS_SAT8(a, b) ((((a)+(b)) & 0x80) ? silk_int8_MAX : ((a)+(b)))
#define silk_ADD_POS_SAT16(a, b) ((((a)+(b)) & 0x8000) ? silk_int16_MAX : ((a)+(b)))
#define silk_ADD_POS_SAT32(a, b) ((((opus_uint32)(a)+(opus_uint32)(b)) & 0x80000000) ? silk_int32_MAX : ((a)+(b)))
#define silk_LSHIFT8(a, shift) ((opus_int8)((opus_uint8)(a)<<(shift))) /* shift >= 0, shift < 8 */
#define silk_LSHIFT16(a, shift) ((opus_int16)((opus_uint16)(a)<<(shift))) /* shift >= 0, shift < 16 */
#define silk_LSHIFT32(a, shift) ((opus_int32)((opus_uint32)(a)<<(shift))) /* shift >= 0, shift < 32 */
#define silk_LSHIFT64(a, shift) ((opus_int64)((opus_uint64)(a)<<(shift))) /* shift >= 0, shift < 64 */
#define silk_LSHIFT(a, shift) silk_LSHIFT32(a, shift) /* shift >= 0, shift < 32 */
#define silk_RSHIFT8(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 8 */
#define silk_RSHIFT16(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 16 */
#define silk_RSHIFT32(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 32 */
#define silk_RSHIFT64(a, shift) ((a)>>(shift)) /* shift >= 0, shift < 64 */
#define silk_RSHIFT(a, shift) silk_RSHIFT32(a, shift) /* shift >= 0, shift < 32 */
/* saturates before shifting */
#define silk_LSHIFT_SAT32(a, shift) (silk_LSHIFT32( silk_LIMIT( (a), silk_RSHIFT32( silk_int32_MIN, (shift) ), \
silk_RSHIFT32( silk_int32_MAX, (shift) ) ), (shift) ))
#define silk_LSHIFT_ovflw(a, shift) ((opus_int32)((opus_uint32)(a) << (shift))) /* shift >= 0, allowed to overflow */
#define silk_LSHIFT_uint(a, shift) ((a) << (shift)) /* shift >= 0 */
#define silk_RSHIFT_uint(a, shift) ((a) >> (shift)) /* shift >= 0 */
#define silk_ADD_LSHIFT(a, b, shift) ((a) + silk_LSHIFT((b), (shift))) /* shift >= 0 */
#define silk_ADD_LSHIFT32(a, b, shift) silk_ADD32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */
#define silk_ADD_LSHIFT_uint(a, b, shift) ((a) + silk_LSHIFT_uint((b), (shift))) /* shift >= 0 */
#define silk_ADD_RSHIFT(a, b, shift) ((a) + silk_RSHIFT((b), (shift))) /* shift >= 0 */
#define silk_ADD_RSHIFT32(a, b, shift) silk_ADD32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */
#define silk_ADD_RSHIFT_uint(a, b, shift) ((a) + silk_RSHIFT_uint((b), (shift))) /* shift >= 0 */
#define silk_SUB_LSHIFT32(a, b, shift) silk_SUB32((a), silk_LSHIFT32((b), (shift))) /* shift >= 0 */
#define silk_SUB_RSHIFT32(a, b, shift) silk_SUB32((a), silk_RSHIFT32((b), (shift))) /* shift >= 0 */
/* Requires that shift > 0 */
#define silk_RSHIFT_ROUND(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
#define silk_RSHIFT_ROUND64(a, shift) ((shift) == 1 ? ((a) >> 1) + ((a) & 1) : (((a) >> ((shift) - 1)) + 1) >> 1)
/* Number of rightshift required to fit the multiplication */
#define silk_NSHIFT_MUL_32_32(a, b) ( -(31- (32-silk_CLZ32(silk_abs(a)) + (32-silk_CLZ32(silk_abs(b))))) )
#define silk_NSHIFT_MUL_16_16(a, b) ( -(15- (16-silk_CLZ16(silk_abs(a)) + (16-silk_CLZ16(silk_abs(b))))) )
#define silk_min(a, b) (((a) < (b)) ? (a) : (b))
#define silk_max(a, b) (((a) > (b)) ? (a) : (b))
/* Macro to convert floating-point constants to fixed-point */
#define SILK_FIX_CONST( C, Q ) ((opus_int32)((C) * ((opus_int64)1 << (Q)) + 0.5))
/* silk_min() versions with typecast in the function call */
static OPUS_INLINE opus_int silk_min_int(opus_int a, opus_int b)
{
return (((a) < (b)) ? (a) : (b));
}
static OPUS_INLINE opus_int16 silk_min_16(opus_int16 a, opus_int16 b)
{
return (((a) < (b)) ? (a) : (b));
}
static OPUS_INLINE opus_int32 silk_min_32(opus_int32 a, opus_int32 b)
{
return (((a) < (b)) ? (a) : (b));
}
static OPUS_INLINE opus_int64 silk_min_64(opus_int64 a, opus_int64 b)
{
return (((a) < (b)) ? (a) : (b));
}
/* silk_min() versions with typecast in the function call */
static OPUS_INLINE opus_int silk_max_int(opus_int a, opus_int b)
{
return (((a) > (b)) ? (a) : (b));
}
static OPUS_INLINE opus_int16 silk_max_16(opus_int16 a, opus_int16 b)
{
return (((a) > (b)) ? (a) : (b));
}
static OPUS_INLINE opus_int32 silk_max_32(opus_int32 a, opus_int32 b)
{
return (((a) > (b)) ? (a) : (b));
}
static OPUS_INLINE opus_int64 silk_max_64(opus_int64 a, opus_int64 b)
{
return (((a) > (b)) ? (a) : (b));
}
#define silk_LIMIT( a, limit1, limit2) ((limit1) > (limit2) ? ((a) > (limit1) ? (limit1) : ((a) < (limit2) ? (limit2) : (a))) \
: ((a) > (limit2) ? (limit2) : ((a) < (limit1) ? (limit1) : (a))))
#define silk_LIMIT_int silk_LIMIT
#define silk_LIMIT_16 silk_LIMIT
#define silk_LIMIT_32 silk_LIMIT
#define silk_abs(a) (((a) > 0) ? (a) : -(a)) /* Be careful, silk_abs returns wrong when input equals to silk_intXX_MIN */
#define silk_abs_int(a) (((a) ^ ((a) >> (8 * sizeof(a) - 1))) - ((a) >> (8 * sizeof(a) - 1)))
#define silk_abs_int32(a) (((a) ^ ((a) >> 31)) - ((a) >> 31))
#define silk_abs_int64(a) (((a) > 0) ? (a) : -(a))
#define silk_sign(a) ((a) > 0 ? 1 : ( (a) < 0 ? -1 : 0 ))
/* PSEUDO-RANDOM GENERATOR */
/* Make sure to store the result as the seed for the next call (also in between */
/* frames), otherwise result won't be random at all. When only using some of the */
/* bits, take the most significant bits by right-shifting. */
#define RAND_MULTIPLIER 196314165
#define RAND_INCREMENT 907633515
#define silk_RAND(seed) (silk_MLA_ovflw((RAND_INCREMENT), (seed), (RAND_MULTIPLIER)))
/* Add some multiplication functions that can be easily mapped to ARM. */
/* silk_SMMUL: Signed top word multiply.
ARMv6 2 instruction cycles.
ARMv3M+ 3 instruction cycles. use SMULL and ignore LSB registers.(except xM)*/
/*#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT(silk_SMLAL(silk_SMULWB((a32), (b32)), (a32), silk_RSHIFT_ROUND((b32), 16)), 16)*/
/* the following seems faster on x86 */
#define silk_SMMUL(a32, b32) (opus_int32)silk_RSHIFT64(silk_SMULL((a32), (b32)), 32)
#if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
#define silk_burg_modified(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch) \
((void)(arch), silk_burg_modified_c(res_nrg, res_nrg_Q, A_Q16, x, minInvGain_Q30, subfr_length, nb_subfr, D, arch))
#define silk_inner_prod16_aligned_64(inVec1, inVec2, len, arch) \
((void)(arch),silk_inner_prod16_aligned_64_c(inVec1, inVec2, len))
#endif
#include "Inlines.h"
#include "MacroCount.h"
#include "MacroDebug.h"
#ifdef OPUS_ARM_INLINE_ASM
#include "arm/SigProc_FIX_armv4.h"
#endif
#ifdef OPUS_ARM_INLINE_EDSP
#include "arm/SigProc_FIX_armv5e.h"
#endif
#if defined(MIPSr1_ASM)
#include "mips/sigproc_fix_mipsr1.h"
#endif
#ifdef __cplusplus
}
#endif
#endif /* SILK_SIGPROC_FIX_H */

View File

@@ -0,0 +1,361 @@
/***********************************************************************
Copyright (c) 2006-2011, Skype Limited. All rights reserved.
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 Internet Society, IETF or IETF Trust, nor the
names of specific 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 COPYRIGHT OWNER 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.
***********************************************************************/
//#ifdef HAVE_CONFIG_H
#include "../config.h"
//#endif
#include <pgmspace.h>
#include "main.h"
#include "../celt/stack_alloc.h"
/* Silk VAD noise level estimation */
# if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE void silk_VAD_GetNoiseLevels(
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
);
#endif
/**********************************/
/* Initialization of the Silk VAD */
/**********************************/
opus_int silk_VAD_Init( /* O Return value, 0 if success */
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
)
{
opus_int b, ret = 0;
/* reset state memory */
silk_memset( psSilk_VAD, 0, sizeof( silk_VAD_state ) );
/* init noise levels */
/* Initialize array with approx pink noise levels (psd proportional to inverse of frequency) */
for( b = 0; b < VAD_N_BANDS; b++ ) {
psSilk_VAD->NoiseLevelBias[ b ] = silk_max_32( silk_DIV32_16( VAD_NOISE_LEVELS_BIAS, b + 1 ), 1 );
}
/* Initialize state */
for( b = 0; b < VAD_N_BANDS; b++ ) {
psSilk_VAD->NL[ b ] = silk_MUL( 100, psSilk_VAD->NoiseLevelBias[ b ] );
psSilk_VAD->inv_NL[ b ] = silk_DIV32( silk_int32_MAX, psSilk_VAD->NL[ b ] );
}
psSilk_VAD->counter = 15;
/* init smoothed energy-to-noise ratio*/
for( b = 0; b < VAD_N_BANDS; b++ ) {
psSilk_VAD->NrgRatioSmth_Q8[ b ] = 100 * 256; /* 100 * 256 --> 20 dB SNR */
}
return( ret );
}
/* Weighting factors for tilt measure */
static const opus_int32 tiltWeights[ VAD_N_BANDS ] PROGMEM = { 30000, 6000, -12000, -12000 };
/***************************************/
/* Get the speech activity level in Q8 */
/***************************************/
opus_int silk_VAD_GetSA_Q8_c( /* O Return value, 0 if success */
silk_encoder_state *psEncC, /* I/O Encoder state */
const opus_int16 pIn[] /* I PCM input */
)
{
opus_int SA_Q15, pSNR_dB_Q7, input_tilt;
opus_int decimated_framelength1, decimated_framelength2;
opus_int decimated_framelength;
opus_int dec_subframe_length, dec_subframe_offset, SNR_Q7, i, b, s;
opus_int32 sumSquared, smooth_coef_Q16;
opus_int16 HPstateTmp;
VARDECL( opus_int16, X );
opus_int32 Xnrg[ VAD_N_BANDS ];
opus_int32 NrgToNoiseRatio_Q8[ VAD_N_BANDS ];
opus_int32 speech_nrg, x_tmp;
opus_int X_offset[ VAD_N_BANDS ];
opus_int ret = 0;
silk_VAD_state *psSilk_VAD = &psEncC->sVAD;
SAVE_STACK;
/* Safety checks */
silk_assert( VAD_N_BANDS == 4 );
celt_assert( MAX_FRAME_LENGTH >= psEncC->frame_length );
celt_assert( psEncC->frame_length <= 512 );
celt_assert( psEncC->frame_length == 8 * silk_RSHIFT( psEncC->frame_length, 3 ) );
/***********************/
/* Filter and Decimate */
/***********************/
decimated_framelength1 = silk_RSHIFT( psEncC->frame_length, 1 );
decimated_framelength2 = silk_RSHIFT( psEncC->frame_length, 2 );
decimated_framelength = silk_RSHIFT( psEncC->frame_length, 3 );
/* Decimate into 4 bands:
0 L 3L L 3L 5L
- -- - -- --
8 8 2 4 4
[0-1 kHz| temp. |1-2 kHz| 2-4 kHz | 4-8 kHz |
They're arranged to allow the minimal ( frame_length / 4 ) extra
scratch space during the downsampling process */
X_offset[ 0 ] = 0;
X_offset[ 1 ] = decimated_framelength + decimated_framelength2;
X_offset[ 2 ] = X_offset[ 1 ] + decimated_framelength;
X_offset[ 3 ] = X_offset[ 2 ] + decimated_framelength2;
ALLOC( X, X_offset[ 3 ] + decimated_framelength1, opus_int16 );
/* 0-8 kHz to 0-4 kHz and 4-8 kHz */
silk_ana_filt_bank_1( pIn, &psSilk_VAD->AnaState[ 0 ],
X, &X[ X_offset[ 3 ] ], psEncC->frame_length );
/* 0-4 kHz to 0-2 kHz and 2-4 kHz */
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState1[ 0 ],
X, &X[ X_offset[ 2 ] ], decimated_framelength1 );
/* 0-2 kHz to 0-1 kHz and 1-2 kHz */
silk_ana_filt_bank_1( X, &psSilk_VAD->AnaState2[ 0 ],
X, &X[ X_offset[ 1 ] ], decimated_framelength2 );
/*********************************************/
/* HP filter on lowest band (differentiator) */
/*********************************************/
X[ decimated_framelength - 1 ] = silk_RSHIFT( X[ decimated_framelength - 1 ], 1 );
HPstateTmp = X[ decimated_framelength - 1 ];
for( i = decimated_framelength - 1; i > 0; i-- ) {
X[ i - 1 ] = silk_RSHIFT( X[ i - 1 ], 1 );
X[ i ] -= X[ i - 1 ];
}
X[ 0 ] -= psSilk_VAD->HPstate;
psSilk_VAD->HPstate = HPstateTmp;
/*************************************/
/* Calculate the energy in each band */
/*************************************/
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* Find the decimated framelength in the non-uniformly divided bands */
decimated_framelength = silk_RSHIFT( psEncC->frame_length, silk_min_int( VAD_N_BANDS - b, VAD_N_BANDS - 1 ) );
/* Split length into subframe lengths */
dec_subframe_length = silk_RSHIFT( decimated_framelength, VAD_INTERNAL_SUBFRAMES_LOG2 );
dec_subframe_offset = 0;
/* Compute energy per sub-frame */
/* initialize with summed energy of last subframe */
Xnrg[ b ] = psSilk_VAD->XnrgSubfr[ b ];
for( s = 0; s < VAD_INTERNAL_SUBFRAMES; s++ ) {
sumSquared = 0;
for( i = 0; i < dec_subframe_length; i++ ) {
/* The energy will be less than dec_subframe_length * ( silk_int16_MIN / 8 ) ^ 2. */
/* Therefore we can accumulate with no risk of overflow (unless dec_subframe_length > 128) */
x_tmp = silk_RSHIFT(
X[ X_offset[ b ] + i + dec_subframe_offset ], 3 );
sumSquared = silk_SMLABB( sumSquared, x_tmp, x_tmp );
/* Safety check */
silk_assert( sumSquared >= 0 );
}
/* Add/saturate summed energy of current subframe */
if( s < VAD_INTERNAL_SUBFRAMES - 1 ) {
Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], sumSquared );
} else {
/* Look-ahead subframe */
Xnrg[ b ] = silk_ADD_POS_SAT32( Xnrg[ b ], silk_RSHIFT( sumSquared, 1 ) );
}
dec_subframe_offset += dec_subframe_length;
}
psSilk_VAD->XnrgSubfr[ b ] = sumSquared;
}
/********************/
/* Noise estimation */
/********************/
silk_VAD_GetNoiseLevels( &Xnrg[ 0 ], psSilk_VAD );
/***********************************************/
/* Signal-plus-noise to noise ratio estimation */
/***********************************************/
sumSquared = 0;
input_tilt = 0;
for( b = 0; b < VAD_N_BANDS; b++ ) {
speech_nrg = Xnrg[ b ] - psSilk_VAD->NL[ b ];
if( speech_nrg > 0 ) {
/* Divide, with sufficient resolution */
if( ( Xnrg[ b ] & 0xFF800000 ) == 0 ) {
NrgToNoiseRatio_Q8[ b ] = silk_DIV32( silk_LSHIFT( Xnrg[ b ], 8 ), psSilk_VAD->NL[ b ] + 1 );
} else {
NrgToNoiseRatio_Q8[ b ] = silk_DIV32( Xnrg[ b ], silk_RSHIFT( psSilk_VAD->NL[ b ], 8 ) + 1 );
}
/* Convert to log domain */
SNR_Q7 = silk_lin2log( NrgToNoiseRatio_Q8[ b ] ) - 8 * 128;
/* Sum-of-squares */
sumSquared = silk_SMLABB( sumSquared, SNR_Q7, SNR_Q7 ); /* Q14 */
/* Tilt measure */
if( speech_nrg < ( (opus_int32)1 << 20 ) ) {
/* Scale down SNR value for small subband speech energies */
SNR_Q7 = silk_SMULWB( silk_LSHIFT( silk_SQRT_APPROX( speech_nrg ), 6 ), SNR_Q7 );
}
input_tilt = silk_SMLAWB( input_tilt, tiltWeights[ b ], SNR_Q7 );
} else {
NrgToNoiseRatio_Q8[ b ] = 256;
}
}
/* Mean-of-squares */
sumSquared = silk_DIV32_16( sumSquared, VAD_N_BANDS ); /* Q14 */
/* Root-mean-square approximation, scale to dBs, and write to output pointer */
pSNR_dB_Q7 = (opus_int16)( 3 * silk_SQRT_APPROX( sumSquared ) ); /* Q7 */
/*********************************/
/* Speech Probability Estimation */
/*********************************/
SA_Q15 = silk_sigm_Q15( silk_SMULWB( VAD_SNR_FACTOR_Q16, pSNR_dB_Q7 ) - VAD_NEGATIVE_OFFSET_Q5 );
/**************************/
/* Frequency Tilt Measure */
/**************************/
psEncC->input_tilt_Q15 = silk_LSHIFT( silk_sigm_Q15( input_tilt ) - 16384, 1 );
/**************************************************/
/* Scale the sigmoid output based on power levels */
/**************************************************/
speech_nrg = 0;
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* Accumulate signal-without-noise energies, higher frequency bands have more weight */
speech_nrg += ( b + 1 ) * silk_RSHIFT( Xnrg[ b ] - psSilk_VAD->NL[ b ], 4 );
}
if( psEncC->frame_length == 20 * psEncC->fs_kHz ) {
speech_nrg = silk_RSHIFT32( speech_nrg, 1 );
}
/* Power scaling */
if( speech_nrg <= 0 ) {
SA_Q15 = silk_RSHIFT( SA_Q15, 1 );
} else if( speech_nrg < 16384 ) {
speech_nrg = silk_LSHIFT32( speech_nrg, 16 );
/* square-root */
speech_nrg = silk_SQRT_APPROX( speech_nrg );
SA_Q15 = silk_SMULWB( 32768 + speech_nrg, SA_Q15 );
}
/* Copy the resulting speech activity in Q8 */
psEncC->speech_activity_Q8 = silk_min_int( silk_RSHIFT( SA_Q15, 7 ), silk_uint8_MAX );
/***********************************/
/* Energy Level and SNR estimation */
/***********************************/
/* Smoothing coefficient */
smooth_coef_Q16 = silk_SMULWB( VAD_SNR_SMOOTH_COEF_Q18, silk_SMULWB( (opus_int32)SA_Q15, SA_Q15 ) );
if( psEncC->frame_length == 10 * psEncC->fs_kHz ) {
smooth_coef_Q16 >>= 1;
}
for( b = 0; b < VAD_N_BANDS; b++ ) {
/* compute smoothed energy-to-noise ratio per band */
psSilk_VAD->NrgRatioSmth_Q8[ b ] = silk_SMLAWB( psSilk_VAD->NrgRatioSmth_Q8[ b ],
NrgToNoiseRatio_Q8[ b ] - psSilk_VAD->NrgRatioSmth_Q8[ b ], smooth_coef_Q16 );
/* signal to noise ratio in dB per band */
SNR_Q7 = 3 * ( silk_lin2log( psSilk_VAD->NrgRatioSmth_Q8[b] ) - 8 * 128 );
/* quality = sigmoid( 0.25 * ( SNR_dB - 16 ) ); */
psEncC->input_quality_bands_Q15[ b ] = silk_sigm_Q15( silk_RSHIFT( SNR_Q7 - 16 * 128, 4 ) );
}
RESTORE_STACK;
return( ret );
}
/**************************/
/* Noise level estimation */
/**************************/
# if !defined(OPUS_X86_MAY_HAVE_SSE4_1)
static OPUS_INLINE
#endif
void silk_VAD_GetNoiseLevels(
const opus_int32 pX[ VAD_N_BANDS ], /* I subband energies */
silk_VAD_state *psSilk_VAD /* I/O Pointer to Silk VAD state */
)
{
opus_int k;
opus_int32 nl, nrg, inv_nrg;
opus_int coef, min_coef;
/* Initially faster smoothing */
if( psSilk_VAD->counter < 1000 ) { /* 1000 = 20 sec */
min_coef = silk_DIV32_16( silk_int16_MAX, silk_RSHIFT( psSilk_VAD->counter, 4 ) + 1 );
/* Increment frame counter */
psSilk_VAD->counter++;
} else {
min_coef = 0;
}
for( k = 0; k < VAD_N_BANDS; k++ ) {
/* Get old noise level estimate for current band */
nl = psSilk_VAD->NL[ k ];
silk_assert( nl >= 0 );
/* Add bias */
nrg = silk_ADD_POS_SAT32( pX[ k ], psSilk_VAD->NoiseLevelBias[ k ] );
silk_assert( nrg > 0 );
/* Invert energies */
inv_nrg = silk_DIV32( silk_int32_MAX, nrg );
silk_assert( inv_nrg >= 0 );
/* Less update when subband energy is high */
if( nrg > silk_LSHIFT( nl, 3 ) ) {
coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 >> 3;
} else if( nrg < nl ) {
coef = VAD_NOISE_LEVEL_SMOOTH_COEF_Q16;
} else {
coef = silk_SMULWB( silk_SMULWW( inv_nrg, nl ), VAD_NOISE_LEVEL_SMOOTH_COEF_Q16 << 1 );
}
/* Initially faster smoothing */
coef = silk_max_int( coef, min_coef );
/* Smooth inverse energies */
psSilk_VAD->inv_NL[ k ] = silk_SMLAWB( psSilk_VAD->inv_NL[ k ], inv_nrg - psSilk_VAD->inv_NL[ k ], coef );
silk_assert( psSilk_VAD->inv_NL[ k ] >= 0 );
/* Compute noise level by inverting again */
nl = silk_DIV32( silk_int32_MAX, psSilk_VAD->inv_NL[ k ] );
silk_assert( nl >= 0 );
/* Limit noise levels (guarantee 7 bits of head room) */
nl = silk_min( nl, 0x00FFFFFF );
/* Store as part of state */
psSilk_VAD->NL[ k ] = nl;
}
}

Some files were not shown because too many files have changed in this diff Show More