A lot of updates
This commit is contained in:
@@ -1,33 +0,0 @@
|
||||
Makefile
|
||||
Makefile.in
|
||||
aclocal.m4
|
||||
autom4te.cache
|
||||
*.kdevelop.pcs
|
||||
*.kdevses
|
||||
config.guess
|
||||
config.h
|
||||
config.h.in
|
||||
config.log
|
||||
config.status
|
||||
config.sub
|
||||
configure
|
||||
depcomp
|
||||
install-sh
|
||||
.deps
|
||||
.libs
|
||||
*.la
|
||||
testcelt
|
||||
libtool
|
||||
ltmain.sh
|
||||
missing
|
||||
stamp-h1
|
||||
*.sw
|
||||
*.o
|
||||
*.lo
|
||||
*~
|
||||
tests/*test
|
||||
tools/celtdec
|
||||
tools/celtenc
|
||||
celt.pc
|
||||
libcelt.spec
|
||||
libcelt/dump_modes
|
||||
@@ -1,25 +0,0 @@
|
||||
Copyright 2001-2009 Jean-Marc Valin, Timothy B. Terriberry,
|
||||
CSIRO, and other contributors
|
||||
|
||||
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.
|
||||
@@ -1,283 +0,0 @@
|
||||
# Doxyfile 1.5.3
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = CELT
|
||||
PROJECT_NUMBER = 0.11.4
|
||||
OUTPUT_DIRECTORY = doc/API
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class " \
|
||||
"The $name widget " \
|
||||
"The $name file " \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = NO
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text "
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = libcelt/celt.h \
|
||||
libcelt/celt_types.h \
|
||||
libcelt/celt_header.h
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.d \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.idl \
|
||||
*.odl \
|
||||
*.cs \
|
||||
*.php \
|
||||
*.php3 \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.C \
|
||||
*.CC \
|
||||
*.C++ \
|
||||
*.II \
|
||||
*.I++ \
|
||||
*.H \
|
||||
*.HH \
|
||||
*.H++ \
|
||||
*.CS \
|
||||
*.PHP \
|
||||
*.PHP3 \
|
||||
*.M \
|
||||
*.MM \
|
||||
*.PY
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS = *.c
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = YES
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = YES
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = NO
|
||||
MSCGEN_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = NO
|
||||
INCLUDED_BY_GRAPH = NO
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
||||
@@ -1,281 +0,0 @@
|
||||
# Doxyfile 1.5.3
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Project related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
DOXYFILE_ENCODING = UTF-8
|
||||
PROJECT_NAME = CELT
|
||||
PROJECT_NUMBER = 0.11.4
|
||||
OUTPUT_DIRECTORY = doc/devel
|
||||
CREATE_SUBDIRS = NO
|
||||
OUTPUT_LANGUAGE = English
|
||||
BRIEF_MEMBER_DESC = YES
|
||||
REPEAT_BRIEF = YES
|
||||
ABBREVIATE_BRIEF = "The $name class " \
|
||||
"The $name widget " \
|
||||
"The $name file " \
|
||||
is \
|
||||
provides \
|
||||
specifies \
|
||||
contains \
|
||||
represents \
|
||||
a \
|
||||
an \
|
||||
the
|
||||
ALWAYS_DETAILED_SEC = NO
|
||||
INLINE_INHERITED_MEMB = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_INC_PATH =
|
||||
SHORT_NAMES = NO
|
||||
JAVADOC_AUTOBRIEF = NO
|
||||
QT_AUTOBRIEF = NO
|
||||
MULTILINE_CPP_IS_BRIEF = NO
|
||||
DETAILS_AT_TOP = NO
|
||||
INHERIT_DOCS = YES
|
||||
SEPARATE_MEMBER_PAGES = NO
|
||||
TAB_SIZE = 8
|
||||
ALIASES =
|
||||
OPTIMIZE_OUTPUT_FOR_C = YES
|
||||
OPTIMIZE_OUTPUT_JAVA = NO
|
||||
BUILTIN_STL_SUPPORT = NO
|
||||
CPP_CLI_SUPPORT = NO
|
||||
DISTRIBUTE_GROUP_DOC = NO
|
||||
SUBGROUPING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
EXTRACT_ALL = YES
|
||||
EXTRACT_PRIVATE = NO
|
||||
EXTRACT_STATIC = NO
|
||||
EXTRACT_LOCAL_CLASSES = YES
|
||||
EXTRACT_LOCAL_METHODS = NO
|
||||
EXTRACT_ANON_NSPACES = NO
|
||||
HIDE_UNDOC_MEMBERS = YES
|
||||
HIDE_UNDOC_CLASSES = YES
|
||||
HIDE_FRIEND_COMPOUNDS = NO
|
||||
HIDE_IN_BODY_DOCS = NO
|
||||
INTERNAL_DOCS = NO
|
||||
CASE_SENSE_NAMES = YES
|
||||
HIDE_SCOPE_NAMES = NO
|
||||
SHOW_INCLUDE_FILES = YES
|
||||
INLINE_INFO = YES
|
||||
SORT_MEMBER_DOCS = YES
|
||||
SORT_BRIEF_DOCS = NO
|
||||
SORT_BY_SCOPE_NAME = NO
|
||||
GENERATE_TODOLIST = YES
|
||||
GENERATE_TESTLIST = YES
|
||||
GENERATE_BUGLIST = YES
|
||||
GENERATE_DEPRECATEDLIST= YES
|
||||
ENABLED_SECTIONS =
|
||||
MAX_INITIALIZER_LINES = 30
|
||||
SHOW_USED_FILES = YES
|
||||
SHOW_DIRECTORIES = NO
|
||||
FILE_VERSION_FILTER =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to warning and progress messages
|
||||
#---------------------------------------------------------------------------
|
||||
QUIET = NO
|
||||
WARNINGS = YES
|
||||
WARN_IF_UNDOCUMENTED = YES
|
||||
WARN_IF_DOC_ERROR = YES
|
||||
WARN_NO_PARAMDOC = NO
|
||||
WARN_FORMAT = "$file:$line: $text "
|
||||
WARN_LOGFILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the input files
|
||||
#---------------------------------------------------------------------------
|
||||
INPUT = libcelt
|
||||
INPUT_ENCODING = UTF-8
|
||||
FILE_PATTERNS = *.c \
|
||||
*.cc \
|
||||
*.cxx \
|
||||
*.cpp \
|
||||
*.c++ \
|
||||
*.d \
|
||||
*.java \
|
||||
*.ii \
|
||||
*.ixx \
|
||||
*.ipp \
|
||||
*.i++ \
|
||||
*.inl \
|
||||
*.h \
|
||||
*.hh \
|
||||
*.hxx \
|
||||
*.hpp \
|
||||
*.h++ \
|
||||
*.idl \
|
||||
*.odl \
|
||||
*.cs \
|
||||
*.php \
|
||||
*.php3 \
|
||||
*.inc \
|
||||
*.m \
|
||||
*.mm \
|
||||
*.dox \
|
||||
*.py \
|
||||
*.C \
|
||||
*.CC \
|
||||
*.C++ \
|
||||
*.II \
|
||||
*.I++ \
|
||||
*.H \
|
||||
*.HH \
|
||||
*.H++ \
|
||||
*.CS \
|
||||
*.PHP \
|
||||
*.PHP3 \
|
||||
*.M \
|
||||
*.MM \
|
||||
*.PY
|
||||
RECURSIVE = NO
|
||||
EXCLUDE =
|
||||
EXCLUDE_SYMLINKS = NO
|
||||
EXCLUDE_PATTERNS =
|
||||
EXCLUDE_SYMBOLS =
|
||||
EXAMPLE_PATH =
|
||||
EXAMPLE_PATTERNS = *
|
||||
EXAMPLE_RECURSIVE = NO
|
||||
IMAGE_PATH =
|
||||
INPUT_FILTER =
|
||||
FILTER_PATTERNS =
|
||||
FILTER_SOURCE_FILES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to source browsing
|
||||
#---------------------------------------------------------------------------
|
||||
SOURCE_BROWSER = YES
|
||||
INLINE_SOURCES = NO
|
||||
STRIP_CODE_COMMENTS = YES
|
||||
REFERENCED_BY_RELATION = YES
|
||||
REFERENCES_RELATION = YES
|
||||
REFERENCES_LINK_SOURCE = YES
|
||||
USE_HTAGS = NO
|
||||
VERBATIM_HEADERS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the alphabetical class index
|
||||
#---------------------------------------------------------------------------
|
||||
ALPHABETICAL_INDEX = NO
|
||||
COLS_IN_ALPHA_INDEX = 5
|
||||
IGNORE_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the HTML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_HTML = YES
|
||||
HTML_OUTPUT = html
|
||||
HTML_FILE_EXTENSION = .html
|
||||
HTML_HEADER =
|
||||
HTML_FOOTER =
|
||||
HTML_STYLESHEET =
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
GENERATE_HTMLHELP = NO
|
||||
HTML_DYNAMIC_SECTIONS = NO
|
||||
CHM_FILE =
|
||||
HHC_LOCATION =
|
||||
GENERATE_CHI = NO
|
||||
BINARY_TOC = NO
|
||||
TOC_EXPAND = NO
|
||||
DISABLE_INDEX = NO
|
||||
ENUM_VALUES_PER_LINE = 4
|
||||
GENERATE_TREEVIEW = NO
|
||||
TREEVIEW_WIDTH = 250
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the LaTeX output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_LATEX = YES
|
||||
LATEX_OUTPUT = latex
|
||||
LATEX_CMD_NAME = latex
|
||||
MAKEINDEX_CMD_NAME = makeindex
|
||||
COMPACT_LATEX = NO
|
||||
PAPER_TYPE = a4wide
|
||||
EXTRA_PACKAGES =
|
||||
LATEX_HEADER =
|
||||
PDF_HYPERLINKS = YES
|
||||
USE_PDFLATEX = YES
|
||||
LATEX_BATCHMODE = NO
|
||||
LATEX_HIDE_INDICES = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the RTF output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_RTF = NO
|
||||
RTF_OUTPUT = rtf
|
||||
COMPACT_RTF = NO
|
||||
RTF_HYPERLINKS = NO
|
||||
RTF_STYLESHEET_FILE =
|
||||
RTF_EXTENSIONS_FILE =
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the man page output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_MAN = YES
|
||||
MAN_OUTPUT = man
|
||||
MAN_EXTENSION = .3
|
||||
MAN_LINKS = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the XML output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_XML = NO
|
||||
XML_OUTPUT = xml
|
||||
XML_SCHEMA =
|
||||
XML_DTD =
|
||||
XML_PROGRAMLISTING = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options for the AutoGen Definitions output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_AUTOGEN_DEF = NO
|
||||
#---------------------------------------------------------------------------
|
||||
# configuration options related to the Perl module output
|
||||
#---------------------------------------------------------------------------
|
||||
GENERATE_PERLMOD = NO
|
||||
PERLMOD_LATEX = NO
|
||||
PERLMOD_PRETTY = YES
|
||||
PERLMOD_MAKEVAR_PREFIX =
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the preprocessor
|
||||
#---------------------------------------------------------------------------
|
||||
ENABLE_PREPROCESSING = YES
|
||||
MACRO_EXPANSION = NO
|
||||
EXPAND_ONLY_PREDEF = NO
|
||||
SEARCH_INCLUDES = YES
|
||||
INCLUDE_PATH =
|
||||
INCLUDE_FILE_PATTERNS =
|
||||
PREDEFINED =
|
||||
EXPAND_AS_DEFINED =
|
||||
SKIP_FUNCTION_MACROS = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to external references
|
||||
#---------------------------------------------------------------------------
|
||||
TAGFILES =
|
||||
GENERATE_TAGFILE =
|
||||
ALLEXTERNALS = NO
|
||||
EXTERNAL_GROUPS = YES
|
||||
PERL_PATH = /usr/bin/perl
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration options related to the dot tool
|
||||
#---------------------------------------------------------------------------
|
||||
CLASS_DIAGRAMS = NO
|
||||
MSCGEN_PATH =
|
||||
HIDE_UNDOC_RELATIONS = YES
|
||||
HAVE_DOT = YES
|
||||
CLASS_GRAPH = YES
|
||||
COLLABORATION_GRAPH = YES
|
||||
GROUP_GRAPHS = YES
|
||||
UML_LOOK = NO
|
||||
TEMPLATE_RELATIONS = NO
|
||||
INCLUDE_GRAPH = NO
|
||||
INCLUDED_BY_GRAPH = NO
|
||||
CALL_GRAPH = NO
|
||||
CALLER_GRAPH = NO
|
||||
GRAPHICAL_HIERARCHY = YES
|
||||
DIRECTORY_GRAPH = YES
|
||||
DOT_IMAGE_FORMAT = png
|
||||
DOT_PATH =
|
||||
DOTFILE_DIRS =
|
||||
DOT_GRAPH_MAX_NODES = 50
|
||||
MAX_DOT_GRAPH_DEPTH = 1000
|
||||
DOT_TRANSPARENT = NO
|
||||
DOT_MULTI_TARGETS = NO
|
||||
GENERATE_LEGEND = YES
|
||||
DOT_CLEANUP = YES
|
||||
#---------------------------------------------------------------------------
|
||||
# Configuration::additions related to the search engine
|
||||
#---------------------------------------------------------------------------
|
||||
SEARCHENGINE = NO
|
||||
@@ -1,5 +0,0 @@
|
||||
To compile:
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in. -*-Makefile-*-
|
||||
|
||||
# To disable automatic dependency tracking if using other tools than
|
||||
# gcc and gmake, add the option 'no-dependencies'
|
||||
AUTOMAKE_OPTIONS = 1.6
|
||||
|
||||
#Fools KDevelop into including all files
|
||||
SUBDIRS = libcelt tests @tools@
|
||||
|
||||
DIST_SUBDIRS = libcelt tests tools
|
||||
|
||||
pkgconfigdir = $(libdir)/pkgconfig
|
||||
pkgconfig_DATA = celt.pc
|
||||
|
||||
EXTRA_DIST = celt.pc.in Doxyfile Doxyfile.devel msvc/config.h
|
||||
|
||||
rpm: dist
|
||||
rpmbuild -ta ${PACKAGE}-${VERSION}.tar.gz
|
||||
@@ -1,88 +0,0 @@
|
||||
CELT is a very low delay audio codec designed for high-quality communications.
|
||||
|
||||
Traditional full-bandwidth codecs such as Vorbis and AAC can offer high
|
||||
quality but they require codec delays of hundreds of milliseconds, which
|
||||
makes them unsuitable for real-time interactive applications like tele-
|
||||
conferencing. Speech targeted codecs, such as Speex or G.722, have lower
|
||||
20-40ms delays but their speech focus and limited sampling rates
|
||||
restricts their quality, especially for music.
|
||||
|
||||
Additionally, the other mandatory components of a full network audio system—
|
||||
audio interfaces, routers, jitter buffers— each add their own delay. For lower
|
||||
speed networks the time it takes to serialize a packet onto the network cable
|
||||
takes considerable time, and over the long distances the speed of light
|
||||
imposes a significant delay.
|
||||
|
||||
In teleconferencing— it is important to keep delay low so that the participants
|
||||
can communicate fluidly without talking on top of each other and so that their
|
||||
own voices don't return after a round trip as an annoying echo.
|
||||
|
||||
For network music performance— research has show that the total one way delay
|
||||
must be kept under 25ms to avoid degrading the musicians performance.
|
||||
|
||||
Since many of the sources of delay in a complete system are outside of the
|
||||
user's control (such as the speed of light) it is often only possible to
|
||||
reduce the total delay by reducing the codec delay.
|
||||
|
||||
Low delay has traditionally been considered a challenging area in audio codec
|
||||
design, because as a codec is forced to work on the smaller chunks of audio
|
||||
required for low delay it has access to less redundancy and less perceptual
|
||||
information which it can use to reduce the size of the transmitted audio.
|
||||
|
||||
CELT is designed to bridge the gap between "music" and "speech" codecs,
|
||||
permitting new very high quality teleconferencing applications, and to go
|
||||
further, permitting latencies much lower than speech codecs normally provide
|
||||
to enable applications such as remote musical collaboration even over long
|
||||
distances.
|
||||
|
||||
In keeping with the Xiph.Org mission— CELT is also designed to accomplish
|
||||
this without copyright or patent encumbrance. Only by keeping the formats
|
||||
that drive our Internet communication free and unencumbered can we maximize
|
||||
innovation, collaboration, and interoperability. Fortunately, CELT is ahead
|
||||
of the adoption curve in its target application space, so there should be
|
||||
no reason for someone who needs what CELT provides to go with a proprietary
|
||||
codec.
|
||||
|
||||
CELT has been tested on x86, x86_64, ARM, and the TI C55x DSPs, and should
|
||||
be portable to any platform with a working C compiler and on the order of
|
||||
100 MIPS of processing power.
|
||||
|
||||
The code is still in early stage, so it may be broken from time to time, and
|
||||
the bit-stream is not frozen yet, so it is different from one version to
|
||||
another. Oh, and don't complain if it sets your house on fire.
|
||||
|
||||
Complaints and accolades can be directed to the CELT mailing list:
|
||||
http://lists.xiph.org/mailman/listinfo/celt-dev/
|
||||
|
||||
To compile:
|
||||
% ./configure
|
||||
% make
|
||||
|
||||
For platforms without fast floating point support (such as ARM) use the
|
||||
--enable-fixed argument to configure to build a fixed-point version of CELT.
|
||||
|
||||
There are Ogg-based encode/decode tools in tools/. These are quite similar to
|
||||
the speexenc/speexdec tools. Use the --help option for details.
|
||||
|
||||
There is also a basic tool for testing the encoder and decoder called
|
||||
"testcelt" located in libcelt/:
|
||||
|
||||
% testcelt <rate> <channels> <frame size> <bytes per packet> input.sw output.sw
|
||||
|
||||
where input.sw is a 16-bit (machine endian) audio file sampled at 32000 Hz to
|
||||
96000 Hz. The output file is already decompressed.
|
||||
|
||||
For example, for a 44.1 kHz mono stream at ~64kbit/sec and with 256 sample
|
||||
frames:
|
||||
|
||||
% testcelt 44100 1 256 46 intput.sw output.sw
|
||||
|
||||
Since 44100/256*46*8 = 63393.74 bits/sec.
|
||||
|
||||
All even frame sizes from 64 to 512 are currently supported, although
|
||||
power-of-two sizes are recommended and most CELT development is done
|
||||
using a size of 256. The delay imposed by CELT is 1.25x - 1.5x the
|
||||
frame duration depending on the frame size and some details of CELT's
|
||||
internal operation. For 256 sample frames the delay is 1.5x or 384
|
||||
samples, so the total codec delay in the above example is 8.70ms
|
||||
(1000/(44100/384)).
|
||||
@@ -1,10 +0,0 @@
|
||||
Here are a few tips for building on Windows:
|
||||
|
||||
1) Create a config.h file that defines out things that defines out all the
|
||||
features that your compiler doesn't understand (e.g. inline, restrict).
|
||||
It also needs to define the CELT_BUILD macro
|
||||
|
||||
2) Define the HAVE_CONFIG_H macro in the project build options (NOT in config.h)
|
||||
|
||||
3) If you want things to be a lot easier, just use a compiler that supports
|
||||
C99, such as gcc
|
||||
@@ -1,10 +0,0 @@
|
||||
The celt codec design and implementation have been merged into
|
||||
the IETF Codec Working Group's "Opus" codec. As such, this
|
||||
repository is no longer under active development.
|
||||
|
||||
Please see https://git.xiph.org/?p=opus.git
|
||||
and https://git.xiph.org/?p=users/jm/opus-tools.git for more
|
||||
current work. Visit http://opus-codec.org/ for more
|
||||
information.
|
||||
|
||||
We apologize for any inconvenience this has caused.
|
||||
@@ -1,20 +0,0 @@
|
||||
- Check minimum width of bands
|
||||
- Revisit energy resolution based on the bit-rate
|
||||
- Revisit static bit allocation (as a function of frame size and channels)
|
||||
- Dynamic adjustment of energy quantisation
|
||||
- Psychacoustics
|
||||
* Error shaping within each band
|
||||
* Decisions on the rate
|
||||
- Intensity stereo decisions
|
||||
- Dynamic (intra-frame) bit allocation
|
||||
- Joint encoding of stereo energy
|
||||
|
||||
- Encode band shape (or just tilt)?
|
||||
- Make energy encoding more robust to losses?
|
||||
|
||||
|
||||
Misc:
|
||||
Detect uint decoding and flag them in the decoder directly
|
||||
If we attempt to write too many bits on the encoder side, set a flag instead of
|
||||
aborting
|
||||
Save "raw bytes" at the end of the stream
|
||||
@@ -1,111 +0,0 @@
|
||||
#!/bin/sh
|
||||
# Run this to set up the build system: configure, makefiles, etc.
|
||||
# (based on the version in enlightenment's cvs)
|
||||
|
||||
package="celt"
|
||||
|
||||
olddir=`pwd`
|
||||
srcdir=`dirname $0`
|
||||
test -z "$srcdir" && srcdir=.
|
||||
|
||||
cd "$srcdir"
|
||||
DIE=0
|
||||
|
||||
echo "checking for autoconf... "
|
||||
(autoconf --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have autoconf installed to compile $package."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
VERSIONGREP="sed -e s/.*[^0-9\.]\([0-9]\.[0-9]*\).*/\1/"
|
||||
VERSIONMKINT="sed -e s/[^0-9]//"
|
||||
|
||||
# do we need automake?
|
||||
if test -r Makefile.am; then
|
||||
AM_NEEDED=`fgrep AUTOMAKE_OPTIONS Makefile.am | $VERSIONGREP`
|
||||
if test -z $AM_NEEDED; then
|
||||
echo -n "checking for automake... "
|
||||
AUTOMAKE=automake
|
||||
ACLOCAL=aclocal
|
||||
if ($AUTOMAKE --version < /dev/null > /dev/null 2>&1); then
|
||||
echo "no"
|
||||
AUTOMAKE=
|
||||
else
|
||||
echo "yes"
|
||||
fi
|
||||
else
|
||||
echo -n "checking for automake $AM_NEEDED or later... "
|
||||
for am in automake-$AM_NEEDED automake$AM_NEEDED automake; do
|
||||
($am --version < /dev/null > /dev/null 2>&1) || continue
|
||||
ver=`$am --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT`
|
||||
verneeded=`echo $AM_NEEDED | $VERSIONMKINT`
|
||||
if test $ver -ge $verneeded; then
|
||||
AUTOMAKE=$am
|
||||
echo $AUTOMAKE
|
||||
break
|
||||
fi
|
||||
done
|
||||
test -z $AUTOMAKE && echo "no"
|
||||
echo -n "checking for aclocal $AM_NEEDED or later... "
|
||||
for ac in aclocal-$AM_NEEDED aclocal$AM_NEEDED aclocal; do
|
||||
($ac --version < /dev/null > /dev/null 2>&1) || continue
|
||||
ver=`$ac --version < /dev/null | head -n 1 | $VERSIONGREP | $VERSIONMKINT`
|
||||
verneeded=`echo $AM_NEEDED | $VERSIONMKINT`
|
||||
if test $ver -ge $verneeded; then
|
||||
ACLOCAL=$ac
|
||||
echo $ACLOCAL
|
||||
break
|
||||
fi
|
||||
done
|
||||
test -z $ACLOCAL && echo "no"
|
||||
fi
|
||||
test -z $AUTOMAKE || test -z $ACLOCAL && {
|
||||
echo
|
||||
echo "You must have automake installed to compile $package."
|
||||
echo "Download the appropriate package for your distribution,"
|
||||
echo "or get the source tarball at ftp://ftp.gnu.org/pub/gnu/"
|
||||
exit 1
|
||||
}
|
||||
fi
|
||||
|
||||
echo -n "checking for libtool... "
|
||||
for LIBTOOLIZE in libtoolize glibtoolize nope; do
|
||||
($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 && break
|
||||
done
|
||||
if test x$LIBTOOLIZE = xnope; then
|
||||
echo "nope."
|
||||
LIBTOOLIZE=libtoolize
|
||||
else
|
||||
echo $LIBTOOLIZE
|
||||
fi
|
||||
($LIBTOOLIZE --version) < /dev/null > /dev/null 2>&1 || {
|
||||
echo
|
||||
echo "You must have libtool installed to compile $package."
|
||||
echo "Download the appropriate package for your system,"
|
||||
echo "or get the source from one of the GNU ftp sites"
|
||||
echo "listed in http://www.gnu.org/order/ftp.html"
|
||||
DIE=1
|
||||
}
|
||||
|
||||
if test "$DIE" -eq 1; then
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Generating configuration files for $package, please wait...."
|
||||
|
||||
echo " $ACLOCAL $ACLOCAL_FLAGS"
|
||||
$ACLOCAL $ACLOCAL_FLAGS || exit 1
|
||||
echo " autoheader"
|
||||
autoheader || exit 1
|
||||
echo " $LIBTOOLIZE --automake"
|
||||
$LIBTOOLIZE --automake || exit 1
|
||||
echo " $AUTOMAKE --add-missing $AUTOMAKE_FLAGS"
|
||||
$AUTOMAKE --add-missing $AUTOMAKE_FLAGS || exit 1
|
||||
echo " autoconf"
|
||||
autoconf || exit 1
|
||||
|
||||
cd $olddir
|
||||
#$srcdir/configure "$@" && echo
|
||||
@@ -1,205 +0,0 @@
|
||||
<?xml version = '1.0'?>
|
||||
<kdevelop>
|
||||
<general>
|
||||
<author>Jean-Marc Valin</author>
|
||||
<email>Jean-Marc.Valin@USherbrooke.ca</email>
|
||||
<version>$VERSION</version>
|
||||
<projectmanagement>KDevAutoProject</projectmanagement>
|
||||
<primarylanguage>C</primarylanguage>
|
||||
<ignoreparts/>
|
||||
<projectname>celt</projectname>
|
||||
<projectdirectory>.</projectdirectory>
|
||||
<absoluteprojectpath>false</absoluteprojectpath>
|
||||
<description></description>
|
||||
<defaultencoding></defaultencoding>
|
||||
</general>
|
||||
<kdevautoproject>
|
||||
<general>
|
||||
<useconfiguration>default</useconfiguration>
|
||||
<activetarget>libcelt/libcelt.la</activetarget>
|
||||
</general>
|
||||
<run>
|
||||
<mainprogram/>
|
||||
<programargs/>
|
||||
<globaldebugarguments/>
|
||||
<globalcwd/>
|
||||
<useglobalprogram>true</useglobalprogram>
|
||||
<terminal>false</terminal>
|
||||
<autocompile>false</autocompile>
|
||||
<autoinstall>false</autoinstall>
|
||||
<autokdesu>false</autokdesu>
|
||||
<envvars/>
|
||||
</run>
|
||||
<configurations>
|
||||
<optimized>
|
||||
<builddir>optimized</builddir>
|
||||
<ccompiler>GccOptions</ccompiler>
|
||||
<cxxcompiler>GppOptions</cxxcompiler>
|
||||
<f77compiler>G77Options</f77compiler>
|
||||
<cflags>-O2 -g0</cflags>
|
||||
</optimized>
|
||||
<debug>
|
||||
<configargs>--enable-debug=full</configargs>
|
||||
<builddir>debug</builddir>
|
||||
<ccompiler>GccOptions</ccompiler>
|
||||
<cxxcompiler>GppOptions</cxxcompiler>
|
||||
<f77compiler>G77Options</f77compiler>
|
||||
<cflags>-O0 -g3</cflags>
|
||||
</debug>
|
||||
</configurations>
|
||||
<make>
|
||||
<envvars>
|
||||
<envvar value="1" name="WANT_AUTOCONF_2_5" />
|
||||
<envvar value="1" name="WANT_AUTOMAKE_1_6" />
|
||||
</envvars>
|
||||
<abortonerror>true</abortonerror>
|
||||
<runmultiplejobs>true</runmultiplejobs>
|
||||
<numberofjobs>4</numberofjobs>
|
||||
<dontact>false</dontact>
|
||||
<makebin></makebin>
|
||||
<prio>0</prio>
|
||||
</make>
|
||||
</kdevautoproject>
|
||||
<kdevdebugger>
|
||||
<general>
|
||||
<dbgshell>libtool</dbgshell>
|
||||
<gdbpath></gdbpath>
|
||||
<configGdbScript></configGdbScript>
|
||||
<runShellScript></runShellScript>
|
||||
<runGdbScript></runGdbScript>
|
||||
<breakonloadinglibs>true</breakonloadinglibs>
|
||||
<separatetty>false</separatetty>
|
||||
<floatingtoolbar>false</floatingtoolbar>
|
||||
<raiseGDBOnStart>false</raiseGDBOnStart>
|
||||
</general>
|
||||
<display>
|
||||
<staticmembers>false</staticmembers>
|
||||
<demanglenames>true</demanglenames>
|
||||
<outputradix>10</outputradix>
|
||||
</display>
|
||||
</kdevdebugger>
|
||||
<kdevdoctreeview>
|
||||
<ignoretocs>
|
||||
<toc>ada</toc>
|
||||
<toc>ada_bugs_gcc</toc>
|
||||
<toc>bash</toc>
|
||||
<toc>bash_bugs</toc>
|
||||
<toc>clanlib</toc>
|
||||
<toc>fortran_bugs_gcc</toc>
|
||||
<toc>gnome1</toc>
|
||||
<toc>gnustep</toc>
|
||||
<toc>gtk</toc>
|
||||
<toc>gtk_bugs</toc>
|
||||
<toc>haskell</toc>
|
||||
<toc>haskell_bugs_ghc</toc>
|
||||
<toc>java_bugs_gcc</toc>
|
||||
<toc>java_bugs_sun</toc>
|
||||
<toc>kde2book</toc>
|
||||
<toc>libstdc++</toc>
|
||||
<toc>opengl</toc>
|
||||
<toc>pascal_bugs_fp</toc>
|
||||
<toc>php</toc>
|
||||
<toc>php_bugs</toc>
|
||||
<toc>perl</toc>
|
||||
<toc>perl_bugs</toc>
|
||||
<toc>python</toc>
|
||||
<toc>python_bugs</toc>
|
||||
<toc>qt-kdev3</toc>
|
||||
<toc>ruby</toc>
|
||||
<toc>ruby_bugs</toc>
|
||||
<toc>sdl</toc>
|
||||
<toc>stl</toc>
|
||||
<toc>sw</toc>
|
||||
<toc>w3c-dom-level2-html</toc>
|
||||
<toc>w3c-svg</toc>
|
||||
<toc>w3c-uaag10</toc>
|
||||
<toc>wxwidgets_bugs</toc>
|
||||
</ignoretocs>
|
||||
<ignoreqt_xml>
|
||||
<toc>Guide to the Qt Translation Tools</toc>
|
||||
<toc>Qt Assistant Manual</toc>
|
||||
<toc>Qt Designer Manual</toc>
|
||||
<toc>Qt Reference Documentation</toc>
|
||||
<toc>qmake User Guide</toc>
|
||||
</ignoreqt_xml>
|
||||
<ignoredoxygen>
|
||||
<toc>KDE Libraries (Doxygen)</toc>
|
||||
</ignoredoxygen>
|
||||
</kdevdoctreeview>
|
||||
<kdevfilecreate>
|
||||
<filetypes/>
|
||||
<useglobaltypes>
|
||||
<type ext="c" />
|
||||
<type ext="h" />
|
||||
</useglobaltypes>
|
||||
</kdevfilecreate>
|
||||
<kdevcppsupport>
|
||||
<qt>
|
||||
<used>false</used>
|
||||
<version>3</version>
|
||||
<includestyle>3</includestyle>
|
||||
<root></root>
|
||||
<designerintegration>EmbeddedKDevDesigner</designerintegration>
|
||||
<qmake></qmake>
|
||||
<designer></designer>
|
||||
<designerpluginpaths/>
|
||||
</qt>
|
||||
<codecompletion>
|
||||
<automaticCodeCompletion>false</automaticCodeCompletion>
|
||||
<automaticArgumentsHint>true</automaticArgumentsHint>
|
||||
<automaticHeaderCompletion>true</automaticHeaderCompletion>
|
||||
<codeCompletionDelay>250</codeCompletionDelay>
|
||||
<argumentsHintDelay>400</argumentsHintDelay>
|
||||
<headerCompletionDelay>250</headerCompletionDelay>
|
||||
<showOnlyAccessibleItems>false</showOnlyAccessibleItems>
|
||||
<completionBoxItemOrder>0</completionBoxItemOrder>
|
||||
<howEvaluationContextMenu>true</howEvaluationContextMenu>
|
||||
<showCommentWithArgumentHint>true</showCommentWithArgumentHint>
|
||||
<statusBarTypeEvaluation>false</statusBarTypeEvaluation>
|
||||
<namespaceAliases>std=_GLIBCXX_STD;__gnu_cxx=std</namespaceAliases>
|
||||
<processPrimaryTypes>true</processPrimaryTypes>
|
||||
<processFunctionArguments>false</processFunctionArguments>
|
||||
<preProcessAllHeaders>false</preProcessAllHeaders>
|
||||
<parseMissingHeadersExperimental>false</parseMissingHeadersExperimental>
|
||||
<resolveIncludePathsUsingMakeExperimental>false</resolveIncludePathsUsingMakeExperimental>
|
||||
<alwaysParseInBackground>true</alwaysParseInBackground>
|
||||
<usePermanentCaching>true</usePermanentCaching>
|
||||
<alwaysIncludeNamespaces>false</alwaysIncludeNamespaces>
|
||||
<includePaths>.;</includePaths>
|
||||
</codecompletion>
|
||||
<creategettersetter>
|
||||
<prefixGet></prefixGet>
|
||||
<prefixSet>set</prefixSet>
|
||||
<prefixVariable>m_,_</prefixVariable>
|
||||
<parameterName>theValue</parameterName>
|
||||
<inlineGet>true</inlineGet>
|
||||
<inlineSet>true</inlineSet>
|
||||
</creategettersetter>
|
||||
<splitheadersource>
|
||||
<enabled>true</enabled>
|
||||
<synchronize>true</synchronize>
|
||||
<orientation>Horizontal</orientation>
|
||||
</splitheadersource>
|
||||
<references/>
|
||||
</kdevcppsupport>
|
||||
<cppsupportpart>
|
||||
<filetemplates>
|
||||
<interfacesuffix>.h</interfacesuffix>
|
||||
<implementationsuffix>.cpp</implementationsuffix>
|
||||
</filetemplates>
|
||||
</cppsupportpart>
|
||||
<kdevfileview>
|
||||
<groups/>
|
||||
<tree>
|
||||
<hidepatterns>*.o,*.lo,CVS</hidepatterns>
|
||||
<hidenonprojectfiles>false</hidenonprojectfiles>
|
||||
</tree>
|
||||
</kdevfileview>
|
||||
<kdevdocumentation>
|
||||
<projectdoc>
|
||||
<docsystem/>
|
||||
<docurl/>
|
||||
<usermanualurl/>
|
||||
</projectdoc>
|
||||
</kdevdocumentation>
|
||||
</kdevelop>
|
||||
@@ -1,15 +0,0 @@
|
||||
# libcelt pkg-config source file
|
||||
|
||||
prefix=@prefix@
|
||||
exec_prefix=@exec_prefix@
|
||||
libdir=@libdir@
|
||||
includedir=@includedir@
|
||||
|
||||
Name: celt
|
||||
Description: CELT is a low-delay audio codec
|
||||
Version: @CELT_VERSION@
|
||||
Requires:
|
||||
Conflicts:
|
||||
Libs: -L${libdir} -lcelt@LIBCELT_SUFFIX@
|
||||
Libs.private: -lm
|
||||
Cflags: -I${includedir}
|
||||
@@ -1,241 +0,0 @@
|
||||
dnl Process this file with autoconf to produce a configure script. -*-m4-*-
|
||||
|
||||
AC_INIT(libcelt/arch.h)
|
||||
|
||||
AM_CONFIG_HEADER([config.h])
|
||||
|
||||
CELT_MAJOR_VERSION=0
|
||||
CELT_MINOR_VERSION=11
|
||||
CELT_MICRO_VERSION=4
|
||||
CELT_EXTRA_VERSION=
|
||||
CELT_VERSION=$CELT_MAJOR_VERSION.$CELT_MINOR_VERSION.$CELT_MICRO_VERSION$CELT_EXTRA_VERSION
|
||||
LIBCELT_SUFFIX=0
|
||||
|
||||
CELT_LT_CURRENT=2
|
||||
CELT_LT_REVISION=0
|
||||
CELT_LT_AGE=0
|
||||
|
||||
AC_SUBST(CELT_LT_CURRENT)
|
||||
AC_SUBST(CELT_LT_REVISION)
|
||||
AC_SUBST(CELT_LT_AGE)
|
||||
AC_SUBST(LIBCELT_SUFFIX)
|
||||
|
||||
# For automake.
|
||||
VERSION=$CELT_VERSION
|
||||
PACKAGE=celt
|
||||
|
||||
AC_SUBST(CELT_VERSION)
|
||||
|
||||
AM_INIT_AUTOMAKE($PACKAGE, $VERSION, no-define)
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AM_PROG_LIBTOOL
|
||||
|
||||
AC_PROG_CC_C99
|
||||
AC_C_BIGENDIAN
|
||||
AC_C_CONST
|
||||
AC_C_INLINE
|
||||
AC_C_RESTRICT
|
||||
|
||||
AC_DEFINE([CELT_BUILD], [], [This is a build of CELT])
|
||||
|
||||
AC_MSG_CHECKING(for C99 variable-size arrays)
|
||||
AC_TRY_COMPILE( , [
|
||||
int foo=10;
|
||||
int array[foo];
|
||||
],
|
||||
[has_var_arrays=yes;AC_DEFINE([VAR_ARRAYS], [], [Use C99 variable-size arrays])
|
||||
],
|
||||
has_var_arrays=no
|
||||
)
|
||||
AC_MSG_RESULT($has_var_arrays)
|
||||
|
||||
AC_CHECK_HEADERS([alloca.h getopt.h])
|
||||
AC_MSG_CHECKING(for alloca)
|
||||
AC_TRY_COMPILE( [#include <alloca.h>], [
|
||||
int foo=10;
|
||||
int *array = alloca(foo);
|
||||
],
|
||||
[
|
||||
has_alloca=yes;
|
||||
if test x$has_var_arrays = "xno" ; then
|
||||
AC_DEFINE([USE_ALLOCA], [], [Make use of alloca])
|
||||
fi
|
||||
],
|
||||
has_alloca=no
|
||||
)
|
||||
AC_MSG_RESULT($has_alloca)
|
||||
|
||||
AC_CHECK_HEADERS(sys/soundcard.h sys/audioio.h)
|
||||
|
||||
AS_IF([test "x$with_ogg" != xno],
|
||||
[XIPH_PATH_OGG([tools="tools"], [tools=""])],
|
||||
[tools=""])
|
||||
AC_SUBST(tools)
|
||||
|
||||
AC_CHECK_LIB(m, sin)
|
||||
|
||||
# Check for getopt_long; if not found, use included source.
|
||||
AC_CHECK_FUNCS([getopt_long],,
|
||||
[# FreeBSD has a gnugetopt library.
|
||||
AC_CHECK_LIB([gnugetopt],[getopt_long],
|
||||
[AC_DEFINE([HAVE_GETOPT_LONG])],
|
||||
[# Use the GNU replacement.
|
||||
AC_LIBOBJ(getopt)
|
||||
AC_LIBOBJ(getopt1)])])
|
||||
|
||||
AC_CHECK_LIB(winmm, main)
|
||||
|
||||
AC_DEFINE_UNQUOTED(CELT_VERSION, "${CELT_VERSION}", [Complete version string])
|
||||
AC_DEFINE_UNQUOTED(CELT_MAJOR_VERSION, ${CELT_MAJOR_VERSION}, [Version major])
|
||||
AC_DEFINE_UNQUOTED(CELT_MINOR_VERSION, ${CELT_MINOR_VERSION}, [Version minor])
|
||||
AC_DEFINE_UNQUOTED(CELT_MICRO_VERSION, ${CELT_MICRO_VERSION}, [Version micro])
|
||||
AC_DEFINE_UNQUOTED(CELT_EXTRA_VERSION, "${CELT_EXTRA_VERSION}", [Version extra])
|
||||
|
||||
has_float_approx=no
|
||||
#case "$host_cpu" in
|
||||
#i[[3456]]86 | x86_64 | powerpc64 | powerpc32 | ia64)
|
||||
# has_float_approx=yes
|
||||
# ;;
|
||||
#esac
|
||||
|
||||
ac_enable_fixed="no";
|
||||
AC_ARG_ENABLE(fixed-point, [ --enable-fixed-point compile as fixed-point],
|
||||
[if test "$enableval" = yes; then
|
||||
ac_enable_fixed="yes";
|
||||
AC_DEFINE([FIXED_POINT], , [Compile as fixed-point])
|
||||
else
|
||||
AC_DEFINE([FLOATING_POINT], , [Compile as floating-point])
|
||||
fi],
|
||||
AC_DEFINE([FLOATING_POINT], , [Compile as floating-point]))
|
||||
|
||||
ac_enable_fixed_debug="no"
|
||||
AC_ARG_ENABLE(fixed-point-debug, [ --enable-fixed-point-debug debug fixed-point implementation],
|
||||
[if test "$enableval" = yes; then
|
||||
ac_enable_fixed_debug="yes"
|
||||
AC_DEFINE([FIXED_DEBUG], , [Debug fixed-point implementation])
|
||||
fi])
|
||||
|
||||
ac_enable_experimental_postfilter="no"
|
||||
AC_ARG_ENABLE(experimental-postfilter, [ --enable-experimental-postfilter Enable this for testing only if you know what you're doing ],
|
||||
[if test "$enableval" = yes; then
|
||||
ac_enable_experimental_postfilter="yes"
|
||||
AC_DEFINE([ENABLE_POSTFILTER], , [Postfilter])
|
||||
fi])
|
||||
|
||||
ac_enable_custom_modes="no"
|
||||
AC_ARG_ENABLE(custom-modes, [ --enable-custom-modes Enable non-Opus modes, like 44.1 kHz and powers of two ],
|
||||
[if test "$enableval" = yes; then
|
||||
ac_enable_custom_modes="yes"
|
||||
AC_DEFINE([CUSTOM_MODES], , [Custom modes])
|
||||
fi])
|
||||
|
||||
float_approx=$has_float_approx
|
||||
AC_ARG_ENABLE(float-approx, [ --enable-float-approx enable fast approximations for floating point],
|
||||
[ if test "$enableval" = yes; then
|
||||
AC_WARN([Floating point approximations are not supported on all platforms.])
|
||||
float_approx=yes
|
||||
else
|
||||
float_approx=no
|
||||
fi], [ float_approx=$has_float_approx ])
|
||||
|
||||
if test "x${float_approx}" = "xyes"; then
|
||||
AC_DEFINE([FLOAT_APPROX], , [Float approximations])
|
||||
fi
|
||||
|
||||
ac_enable_assertions="no"
|
||||
AC_ARG_ENABLE(assertions, [ --enable-assertions enable additional software error checking],
|
||||
[if test "$enableval" = yes; then
|
||||
ac_enable_assertions="yes"
|
||||
AC_DEFINE([ENABLE_ASSERTIONS], , [Assertions])
|
||||
fi])
|
||||
|
||||
if test "$OPUS_BUILD" != "true" ; then
|
||||
saved_CFLAGS="$CFLAGS"
|
||||
CFLAGS="$CFLAGS -fvisibility=hidden"
|
||||
AC_MSG_CHECKING([if ${CXX} supports -fvisibility=hidden])
|
||||
AC_COMPILE_IFELSE([char foo;],
|
||||
[ AC_MSG_RESULT([yes])
|
||||
SYMBOL_VISIBILITY="-fvisibility=hidden" ],
|
||||
AC_MSG_RESULT([no]))
|
||||
CFLAGS="$saved_CFLAGS $SYMBOL_VISIBILITY"
|
||||
AC_SUBST(SYMBOL_VISIBILITY)
|
||||
fi
|
||||
|
||||
if test $ac_cv_c_compiler_gnu = yes ; then
|
||||
CFLAGS="$CFLAGS -W -Wstrict-prototypes -Wall -Wextra -Wcast-align -Wnested-externs -Wshadow -Wno-parentheses -Wno-unused-parameter -Wno-sign-compare"
|
||||
fi
|
||||
|
||||
AC_CHECK_FUNCS([lrintf])
|
||||
AC_CHECK_FUNCS([lrint])
|
||||
|
||||
AC_CHECK_SIZEOF(short)
|
||||
AC_CHECK_SIZEOF(int)
|
||||
AC_CHECK_SIZEOF(long)
|
||||
AC_CHECK_SIZEOF(long long)
|
||||
|
||||
if test x$has_char16 = "xyes" ; then
|
||||
case 1 in
|
||||
$ac_cv_sizeof_short) SIZE16="short";;
|
||||
$ac_cv_sizeof_int) SIZE16="int";;
|
||||
esac
|
||||
else
|
||||
case 2 in
|
||||
$ac_cv_sizeof_short) SIZE16="short";;
|
||||
$ac_cv_sizeof_int) SIZE16="int";;
|
||||
esac
|
||||
fi
|
||||
|
||||
if test x$has_char16 = "xyes" ; then
|
||||
case 2 in
|
||||
$ac_cv_sizeof_int) SIZE32="int";;
|
||||
$ac_cv_sizeof_long) SIZE32="long";;
|
||||
$ac_cv_sizeof_short) SIZE32="short";;
|
||||
esac
|
||||
else
|
||||
case 4 in
|
||||
$ac_cv_sizeof_int) SIZE32="int";;
|
||||
$ac_cv_sizeof_long) SIZE32="long";;
|
||||
$ac_cv_sizeof_short) SIZE32="short";;
|
||||
esac
|
||||
fi
|
||||
|
||||
AC_SUBST(SIZE16)
|
||||
AC_SUBST(SIZE32)
|
||||
|
||||
if test "$OPUS_BUILD" = "true" ; then
|
||||
AC_DEFINE(OPUS_BUILD, [], [We're part of Opus])
|
||||
fi
|
||||
|
||||
AC_OUTPUT([Makefile libcelt/Makefile tests/Makefile
|
||||
celt.pc tools/Makefile libcelt.spec ])
|
||||
|
||||
AC_MSG_RESULT([
|
||||
------------------------------------------------------------------------
|
||||
$PACKAGE $VERSION: Automatic configuration OK.
|
||||
|
||||
Compiler support:
|
||||
|
||||
C99 var arrays: ................ ${has_var_arrays}
|
||||
C99 lrintf: .................... ${ac_cv_func_lrintf}
|
||||
Alloca: ........................ ${has_alloca}
|
||||
|
||||
General configuration:
|
||||
|
||||
Fast float approximations: ..... ${float_approx}
|
||||
Fixed point support: ........... ${ac_enable_fixed}
|
||||
Fixed point debugging: ......... ${ac_enable_fixed_debug}
|
||||
Custom modes: .................. ${ac_enable_custom_modes}
|
||||
Assertion checking: ............ ${ac_enable_assertions}
|
||||
------------------------------------------------------------------------
|
||||
])
|
||||
|
||||
if test "x$tools" = "x"; then
|
||||
echo "**IMPORTANT**"
|
||||
echo "You don't seem to have the development package for libogg (libogg-devel) available. Only the library will be built (no encoder/decoder executable)"
|
||||
echo "You can download libogg from http://www.vorbis.com/download.psp"
|
||||
fi
|
||||
|
||||
echo "Type \"make; make install\" to compile and install";
|
||||
echo "Type \"make check\" to run the test suite";
|
||||
@@ -1,16 +0,0 @@
|
||||
CC = gcc
|
||||
CFLAGS = -c -O2 -g
|
||||
LIBS = -lm
|
||||
|
||||
OBJS = bands.o celt.o cwrs.o entcode.o entdec.o entenc.o kiss_fft.o \
|
||||
kiss_fftr.o laplace.o mdct.o modes.o pitch.o \
|
||||
quant_bands.o rangedec.o rangeenc.o rate.o testcelt.o vq.o plc.o
|
||||
|
||||
.c.o:
|
||||
$(CC) $(CFLAGS) $<
|
||||
|
||||
testcelt: $(OBJS)
|
||||
$(CC) -o $@ $(OBJS) $(LIBS)
|
||||
|
||||
clean:
|
||||
rm -f testcelt *.o
|
||||
@@ -1,77 +0,0 @@
|
||||
/* Copyright (C) 2003-2008 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.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
#include "celt_types.h"
|
||||
|
||||
#define CELT_SIG_SCALE 32768.
|
||||
|
||||
#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
|
||||
#ifdef ENABLE_ASSERTIONS
|
||||
#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);}}
|
||||
#else
|
||||
#define celt_assert(cond)
|
||||
#define celt_assert2(cond, message)
|
||||
#endif
|
||||
|
||||
|
||||
#define ABS(x) ((x) < 0 ? (-(x)) : (x))
|
||||
#define ABS16(x) ((x) < 0 ? (-(x)) : (x))
|
||||
#define MIN16(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX16(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define ABS32(x) ((x) < 0 ? (-(x)) : (x))
|
||||
#define MIN32(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define MAX32(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define IMIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#define IMAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
|
||||
#define float2int(flt) ((int)(floor(.5+flt)))
|
||||
|
||||
#define SCALEIN(a) ((a)*CELT_SIG_SCALE)
|
||||
#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE))
|
||||
|
||||
#ifndef GLOBAL_STACK_SIZE
|
||||
#ifdef FIXED_POINT
|
||||
#define GLOBAL_STACK_SIZE 25000
|
||||
#else
|
||||
#define GLOBAL_STACK_SIZE 40000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_H */
|
||||
@@ -1,15 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
./convert_source.sh
|
||||
|
||||
./ietf_source.sh
|
||||
|
||||
#codec draft
|
||||
xml2rfc draft-valin-celt-codec.xml draft-valin-celt-codec.html
|
||||
|
||||
xml2rfc draft-valin-celt-codec.xml draft-valin-celt-codec.txt
|
||||
|
||||
#RTP draft
|
||||
xml2rfc draft-valin-celt-rtp-profile.xml draft-valin-celt-rtp-profile.html
|
||||
|
||||
xml2rfc draft-valin-celt-rtp-profile.xml draft-valin-celt-rtp-profile.txt
|
||||
@@ -1,11 +0,0 @@
|
||||
#ifndef _CELT_TYPES_H
|
||||
#define _CELT_TYPES_H
|
||||
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
typedef long long celt_int64;
|
||||
typedef unsigned long long celt_uint64;
|
||||
|
||||
#endif /* _CELT_TYPES_H */
|
||||
@@ -1,53 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p source
|
||||
|
||||
for i in `ls ../../libcelt | grep '\.[ch]$'`
|
||||
do
|
||||
|
||||
#echo "<section anchor=\"$i\" title=\"$i\">" > source/$i
|
||||
#echo '<t>' >> source/$i
|
||||
#echo '<figure><artwork><![CDATA[' >> source/$i
|
||||
|
||||
echo '#include "substitutions.h"' > tata.c
|
||||
echo 'SOURCE_CODE_BEGIN' >> tata.c
|
||||
|
||||
if echo $i | grep '\.h' > /dev/null; then
|
||||
cat ../../libcelt/$i | sed -e 's/=\*/= \*/' -e 's/=-/= -/' -e 's/\t/ /g' -e 's/^#/\/\/PREPROCESS_REMOVE#/' >> tata.c
|
||||
else
|
||||
cat ../../libcelt/$i | sed -e 's/=\*/= \*/' -e 's/=-/= -/' -e 's/\t/ /g' -e 's/^#include/\/\/PREPROCESS_REMOVE#include/' | sed 's/^#define/\/\/PREPROCESS_REMOVE#define/'>> tata.c
|
||||
fi
|
||||
|
||||
#cat ../../libcelt/$i | sed 's/^#/\/\/PREPROCESS_REMOVE#/' >> tata.c
|
||||
#cat ../../libcelt/$i | sed 's/^#include/\/\/PREPROCESS_REMOVE#include/' | sed 's/^#define/\/\/PREPROCESS_REMOVE#define/'>> tata.c
|
||||
gcc -DHAVE_CONFIG_H -C -E -nostdinc tata.c | grep -v '^#' | sed 's/\/\/PREPROCESS_REMOVE//' | perl -ne 'if ($begin) {print $_} if (/SOURCE_CODE_BEGIN/) {$begin=1}' > tata2.c
|
||||
|
||||
#cat ../../libcelt/$i >> tata.c
|
||||
#gcc -C -E -nostdinc tata.c -fdirectives-only | perl -ne 'if ($begin) {print $_} if (/SOURCE_CODE_BEGIN/) {$begin=1}' > tata2.c
|
||||
|
||||
indent -nsc -ncdb -original -sob -i2 -bl -bli0 --no-tabs -l69 --format-all-comments tata2.c -o tata.c
|
||||
cat tata.c | grep -v 'include.*float_cast' | ./wrap_lines > source/$i
|
||||
#cat tata.c > source/$i
|
||||
|
||||
|
||||
|
||||
#indent --no-tabs -l72 --format-all-comments ../../libcelt/$i -o tata.c
|
||||
#cat tata.c >> source/$i
|
||||
|
||||
|
||||
#echo ']]></artwork></figure>' >> source/$i
|
||||
#echo '</t>' >> source/$i
|
||||
#echo '</section>' >> source/$i
|
||||
|
||||
done
|
||||
|
||||
cp arch.h source/arch.h
|
||||
cp celt_types.h source/celt_types.h
|
||||
cp config.h source/config.h
|
||||
cp Makefile.ietf source/Makefile
|
||||
|
||||
rm source/mfrng*.c
|
||||
rm source/dump_modes*
|
||||
rm source/header*
|
||||
rm source/fixed*
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,816 +0,0 @@
|
||||
<?xml version='1.0'?>
|
||||
<!DOCTYPE rfc SYSTEM 'rfc2629.dtd'>
|
||||
<?rfc symrefs="yes" toc="yes" ?>
|
||||
|
||||
<rfc ipr="trust200902" docName="RTP Payload Format for the CELT Codec">
|
||||
|
||||
<front>
|
||||
<title>draft-valin-celt-rtp-profile-02</title>
|
||||
|
||||
|
||||
|
||||
<author initials="J-M" surname="Valin" fullname="Jean-Marc Valin">
|
||||
<organization>Octasic Semiconductor</organization>
|
||||
<address>
|
||||
<postal>
|
||||
<street>4101, Molson Street, suite 300</street>
|
||||
<city>Montreal</city>
|
||||
<region>Quebec</region>
|
||||
<code>H1Y 3L1</code>
|
||||
<country>Canada</country>
|
||||
</postal>
|
||||
<email>jean-marc.valin@octasic.com</email>
|
||||
</address>
|
||||
</author>
|
||||
|
||||
|
||||
<author initials="G" surname="Maxwell" fullname="Gregory Maxwell">
|
||||
<organization>Juniper Networks</organization>
|
||||
<address>
|
||||
<postal>
|
||||
<street>2251 Corporate Park Drive, Suite 100</street>
|
||||
<city>Herndon</city>
|
||||
<region>VA</region>
|
||||
<code>20171-1817</code>
|
||||
<country>USA</country>
|
||||
</postal>
|
||||
<email>gmaxwell@juniper.net</email>
|
||||
</address>
|
||||
</author>
|
||||
|
||||
<date day="13" month="July" year="2009" />
|
||||
|
||||
<area>General</area>
|
||||
<workgroup>AVT Working Group</workgroup>
|
||||
<keyword>I-D</keyword>
|
||||
|
||||
<keyword>Internet-Draft</keyword>
|
||||
<keyword>CELT</keyword>
|
||||
<keyword>RTP</keyword>
|
||||
<abstract>
|
||||
<t>
|
||||
CELT is an open-source voice codec suitable for use in very low delay
|
||||
audio communication applications, including Voice over IP (VoIP).
|
||||
This document describes the payload format for CELT generated bit
|
||||
streams within an RTP packet. Also included here are the necessary
|
||||
details for the use of CELT with the Session Description Protocol
|
||||
(SDP). At the time of this writing, the CELT bit-stream has NOT
|
||||
been finalized yet, and compatibility is usually broken with
|
||||
every new release of the codec.
|
||||
</t>
|
||||
</abstract>
|
||||
</front>
|
||||
|
||||
<middle>
|
||||
|
||||
<section anchor="Conventions used in this document" title="Conventions used in this document">
|
||||
<t>
|
||||
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
|
||||
"SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
|
||||
document are to be interpreted as described in RFC 2119 <xref target="rfc2119"></xref>.
|
||||
</t>
|
||||
</section>
|
||||
|
||||
<section anchor="Overview of the CELT Codec" title="Overview of the CELT Codec">
|
||||
|
||||
<t>
|
||||
CELT stands for "Constrained Energy Lapped Transform". It applies some of the CELP principles, but does everything in the frequency domain, which removes some of the limitations of CELP. CELT is suitable for both speech and music and currently features:
|
||||
</t>
|
||||
|
||||
<t>
|
||||
<list style="symbols">
|
||||
<t>Ultra-low algorithmic delay (as low as 2 ms)</t>
|
||||
<t>Full audio bandwidth (up to 20 kHz audio bandwidth)</t>
|
||||
<t>Support for both voice and music</t>
|
||||
<t>Stereo support</t>
|
||||
<t>Packet loss concealment</t>
|
||||
<t>Constant bitrates from under 32 kbps to 128 kbps and above</t>
|
||||
<t>Free software/open-source</t>
|
||||
</list>
|
||||
</t>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="RTP payload format for CELT" title="RTP payload format for CELT">
|
||||
|
||||
<t>
|
||||
For RTP based transportation of CELT encoded audio the standard
|
||||
RTP header <xref target="rfc3550"></xref> is followed by one or more payload data blocks.
|
||||
An optional padding terminator may also be used.
|
||||
</t>
|
||||
|
||||
<section anchor="RTP Header" title="RTP Header">
|
||||
|
||||
<t>
|
||||
<figure>
|
||||
<artwork><![CDATA[
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|V=2|P|X| CC |M| PT | sequence number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| timestamp |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| synchronization source (SSRC) identifier |
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
| contributing source (CSRC) identifiers |
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
]]></artwork>
|
||||
</figure>
|
||||
</t>
|
||||
|
||||
<t>
|
||||
The RTP header is defined in the RTP specification <xref target="rfc3550"></xref>. This
|
||||
section defines how fields in the RTP header are used.
|
||||
</t>
|
||||
|
||||
<t>Padding (P): 1 bit</t><t>
|
||||
If the padding bit is set, the packet contains one or more
|
||||
additional padding octets at the end which are not part of the
|
||||
payload. The last octet of the padding contains a count of how
|
||||
many padding octets should be ignored, including itself. Padding
|
||||
may be needed by some encryption algorithms with fixed block sizes
|
||||
or for carrying several RTP packets in a lower-layer protocol data
|
||||
unit.
|
||||
</t>
|
||||
|
||||
<t>Extension (X): 1 bit</t><t>
|
||||
If the extension, X, bit is set, the fixed header MUST be
|
||||
followed by exactly one header extension, with a format defined
|
||||
in Section 5.3.1. of <xref target="rfc3550"></xref>.
|
||||
</t>
|
||||
|
||||
<t>Marker (M): 1 bit</t><t>
|
||||
The M bit MUST be set to zero in all packets. The receiver MUST
|
||||
ignore the M bit.
|
||||
</t>
|
||||
|
||||
<t>Payload Type (PT): 7 bits</t><t>
|
||||
Payload Type (PT): The assignment of an RTP payload type for this
|
||||
packet format is outside the scope of this document; it is
|
||||
specified by the RTP profile under which this payload format is
|
||||
used, or signaled dynamically out-of-band (e.g., using SDP).
|
||||
</t>
|
||||
|
||||
<t>Timestamp: 32 bits</t><t>
|
||||
A timestamp representing the sampling time of the first sample of
|
||||
the first CELT frame in the RTP payload. The clock frequency
|
||||
MUST be set to the sample rate of the encoded audio data and is
|
||||
conveyed out-of-band (e.g., as an SDP parameter).
|
||||
</t>
|
||||
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="celt--payload" title="CELT payload">
|
||||
|
||||
<t>
|
||||
For the purposes of packetizing the bit stream in RTP, it is only
|
||||
necessary to consider the sequence of bits as output by the CELT
|
||||
encoder <xref target="celt-website"></xref>, and present the same
|
||||
sequence to the decoder. The payload format described here maintains
|
||||
this sequence.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
A typical CELT frame, encoded at a high bitrate, is approx.
|
||||
128 octets and the total size of the CELT frames SHOULD be kept
|
||||
below the path MTU to prevent fragmentation. CELT frames MUST
|
||||
NOT be split across multiple RTP packets,
|
||||
</t>
|
||||
|
||||
<t>
|
||||
An RTP packet MAY contain CELT frames of the same bit rate or of
|
||||
varying bit rates, since the bitrate for the frames is explicitly
|
||||
conveyed in band with the signal. The encoding and decoding algorithm
|
||||
can change the bit rate at any frame boundary, with the bit rate
|
||||
change notification provided in-band. No out-of-band notification
|
||||
is required for the decoder to process changes in the bit rate
|
||||
sent by the encoder.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
More than one frame may be encoded in the same RTP packet, and for
|
||||
the decoder it is not possible to determine the compressed size (bit-rate)
|
||||
of each encoded frame. Thus the compressed size information MUST be explicitly
|
||||
transmitted. There are two modes for conveying this information:
|
||||
either the compressed size(s) are encoded for each frame at the
|
||||
beginning of the RTP payload <xref target="multiple-frames"/>, or it is conveyed in the
|
||||
signaling and then fixed for the duration of the session
|
||||
(Low-Overhead Mode, <xref target="low-overhead"/>). Note that the compressed frame size
|
||||
information must be present either way even if only single frames
|
||||
are transmitted per RTP packet.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
It is RECOMMENDED that sampling rates 32000, 44100, or 48000 Hz be used
|
||||
for most applications, unless a specific reason exists -- such as
|
||||
requirements for a very specific packetization time. For example,
|
||||
51200 Hz sampling may be useful to obtain a 5 ms packetization time
|
||||
with 256-sample frames. For compatibility reasons, the sender and
|
||||
receiver MUST support 48000 Hz sampling rate.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
The CELT codec always produces an integer number of bytes and can
|
||||
produce any integer number of bytes, so no padding is ever required.
|
||||
Bitrate adjustment SHOULD be used instead of padding.
|
||||
</t>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="multiple-frames" title="Multiple CELT frames in a RTP packet">
|
||||
|
||||
<t>
|
||||
The bitrate used by CELT is implicitly determined by the size of the
|
||||
compressed data. When more than one frame is encoded in the same packet,
|
||||
it is not possible to determine the size of each encoded frame, so the
|
||||
information MUST be explicitly encoded. If N frames are present in a
|
||||
packet, N compressed frame sizes need to be encoded at the beginning of
|
||||
the packet. Each size that is less than 255 bytes is encoded in one byte
|
||||
(unsigned 8-bit integer). For sizes greater or equal to 255, a 0xff byte
|
||||
is encoded, followed by the size-255. Multiple 0xff bytes are allowed if
|
||||
there are more than 510 bytes transmitted. The length is always the size
|
||||
of the CELT frame excluding the length byte itself. The payload MUST NOT
|
||||
be padded, except in accordance with the padding bit definition in the
|
||||
RTP header.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Below is an example of two CELT frames contained within one RTP
|
||||
packet.
|
||||
</t>
|
||||
|
||||
<t><figure>
|
||||
<artwork><![CDATA[
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|V=2|P|X| CC |M| PT | sequence number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| timestamp |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| synchronization source (SSRC) identifier |
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
| contributing source (CSRC) identifiers |
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| length frame 1| length frame 2| CELT frame 1... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| (frame 1) | CELT frame 2... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| (frame 2) |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
]]></artwork>
|
||||
</figure></t>
|
||||
|
||||
<t>The following is an example of C code that interprets the length bytes:
|
||||
</t>
|
||||
|
||||
<t><figure>
|
||||
<artwork><![CDATA[
|
||||
int i, N, pos;
|
||||
int sizes[MAX_FRAMES][channels];
|
||||
unsigned int total_size;
|
||||
total_size=0;
|
||||
N = 0;
|
||||
pos = 0;
|
||||
while (total_size < payload_size) {
|
||||
for (i=0;i<channels;i++) {
|
||||
int s;
|
||||
int sum;
|
||||
sum = 0;
|
||||
do {
|
||||
s = payload[pos++];
|
||||
sum += s;
|
||||
total_size += s+1;
|
||||
} while (s == 255);
|
||||
sizes[N][i] = sum;
|
||||
}
|
||||
N++;
|
||||
}
|
||||
]]></artwork>
|
||||
</figure></t>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="Multiple channels" title="Multiple channels">
|
||||
|
||||
<t>CELT supports both mono streams and stereo streams. If more than two channels are desired, it is possible to use transmit multiple streams in the same packet. In this case, the number of streams S and the pairing must be agreed with out-of-band negotiation such as SDP. Each stream can be either mono or stereo, depending on whether the channels are assumed to be correlated. For example, a 5.1 surround could have the front-left and front-right channels in a stereo stream, the rear-left and rear-right channels in a separate stereo stream, while the center and low-frequency channels would be in separate mono streams. In that example, the RTP packet would be:</t>
|
||||
|
||||
<t><figure>
|
||||
<artwork><![CDATA[
|
||||
0 1 2 3
|
||||
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
|V=2|P|X| CC |M| PT | sequence number |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| timestamp |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| synchronization source (SSRC) identifier |
|
||||
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
|
||||
| contributing source (CSRC) identifiers |
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Front length | rear length | center length | LFE length |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Front stereo |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... | Rear stereo data... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| Center mono data... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| | LFE mono data... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
| ... |
|
||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
]]></artwork>
|
||||
</figure></t>
|
||||
|
||||
<t>In the case where streams for multiple channels are used with multiple frames of the same streams per packet, then all streams for a certain timestamp are encoded before all streams for the following timestamp. In the case of the 5.1 example above with two frames per packet, the number of compressed length fields would be S*N = 8.</t>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="MIME registration of CELT" title="MIME registration of CELT">
|
||||
|
||||
<t>
|
||||
Full definition of the MIME <xref target="rfc2045"></xref> type for CELT will be part of the Ogg
|
||||
Vorbis MIME type definition application <xref target="rfc3534"></xref>.
|
||||
</t>
|
||||
|
||||
<t>MIME media type name: audio</t>
|
||||
|
||||
<t>MIME subtype: celt</t>
|
||||
|
||||
<t>Optional parameters:</t>
|
||||
|
||||
<t>Required parameters: to be included in the Ogg MIME specification.</t>
|
||||
|
||||
<t>Encoding considerations:</t>
|
||||
|
||||
<t>Security Considerations:</t>
|
||||
<t>See Section 6 of RFC 3047.</t>
|
||||
|
||||
<t>Interoperability considerations: none</t>
|
||||
|
||||
<t>Published specification: </t>
|
||||
|
||||
<t>Applications which use this media type:</t>
|
||||
|
||||
<t>Additional information: none</t>
|
||||
|
||||
<t>Person & email address to contact for further information:<vspace blankLines="1" />
|
||||
<list style="empty">
|
||||
<t>Jean-Marc Valin <jean-marc.valin@octasic.com></t>
|
||||
</list>
|
||||
</t>
|
||||
|
||||
<t>Intended usage: COMMON</t>
|
||||
|
||||
<t>Author/Change controller:</t>
|
||||
|
||||
<t>
|
||||
<list style="empty">
|
||||
<t>Author: Jean-Marc Valin <jean-marc.valin@octasic.com></t>
|
||||
<t>Change controller: Jean-Marc Valin <jean-marc.valin@octasic.com></t>
|
||||
<t>Change controller: IETF AVT Working Group</t>
|
||||
</list>
|
||||
</t>
|
||||
|
||||
<t>
|
||||
This transport type signifies that the content is to be interpreted
|
||||
according to this document if the contents are transmitted over RTP.
|
||||
Should this transport type appear over a lossless streaming protocol
|
||||
such as TCP, the content encapsulation should be interpreted as an
|
||||
Ogg Stream in accordance with <xref target="rfc3534"></xref>, with the exception that the
|
||||
content of the Ogg Stream may be assumed to be CELT audio and
|
||||
CELT audio only.
|
||||
</t>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="SDP usage of CELT" title="SDP usage of CELT">
|
||||
|
||||
<t>
|
||||
When conveying information by SDP <xref target="rfc4566"></xref>, the encoding name MUST be
|
||||
set to "CELT". The sampling frequency is typically between 32000 and 48000 Hz.
|
||||
Implementations MUST support 48000 Hz and SHOULD also support 44100 Hz.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
The SDP parameters have the following interpretation with respect to CELT:
|
||||
</t>
|
||||
|
||||
<t>
|
||||
<list style="empty">
|
||||
<t>ptime: The desired packetization time. The sender SHOULD choose a number of frames per packet that corresponds to the smallest packetization time greater or equal to the specified ptime for the selected frame size. The default is 20 ms as specified in <xref target="rfc3551"></xref></t>
|
||||
|
||||
<t>maxptime: The maximum packetization time desired. As specified in <xref target="rfc4566"></xref>, if the maximum is lower than the smallest packetization time determined from the chosen frame size (as described above), then that packtization time SHOULD be used despite the maxptime value. The default is "no maximum".</t>
|
||||
|
||||
</list>
|
||||
</t>
|
||||
|
||||
<t>
|
||||
CELT-specific parameters can be given via the "a=fmtp:" directive.
|
||||
Several parameters can be given in a single a=fmtp line provided
|
||||
that they are separated by a semi-colon. The following parameters
|
||||
are defined for use in this way:
|
||||
</t>
|
||||
|
||||
<t>
|
||||
<list style="empty">
|
||||
<t>bitrate: The desired bit-rate in kbit/s for the codec only (excluding
|
||||
headers and the length bytes). The value MUST be rounded to an integer number
|
||||
of bytes per frame. The round-to-nearest method is RECOMMENDED. The default
|
||||
bit-rate value is 64 kbit/s per channel.</t>
|
||||
|
||||
<t>frame-size: The frame size is the duration of each frame in samples and has to be even.
|
||||
The default is 480.</t>
|
||||
|
||||
<t>mapping: Optional string describing the multi-channel mapping.</t>
|
||||
</list>
|
||||
</t>
|
||||
|
||||
<t>
|
||||
The selected frame-size values MUST be even. For quality and complexity
|
||||
reasons, they SHOULD also be divisible by 8 and have a prime factorization
|
||||
which consists only of 2, 3, or 5 factors.
|
||||
For example, powers-of-two and values such as 160, 320, 240, and 480 are
|
||||
recommended. Implementations MUST support receiving and sending the default
|
||||
value of 480. Implementations
|
||||
SHOULD also support frame sizes of 256 and 512 since these are the ones that lead
|
||||
to the lowest complexity. When frame sizes that are powers-of-two are supported,
|
||||
they SHOULD be listed first in the offer and chosen over non-powers-of-two in the
|
||||
answer.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Care must be taken when setting the value of ptime: and bitrate: so that the
|
||||
RTP packet size does not exceed the path MTU.
|
||||
</t>
|
||||
|
||||
<t>An example of the media representation in SDP for offering a single
|
||||
channel of CELT at 48000 samples per second might be:
|
||||
</t>
|
||||
|
||||
<t>
|
||||
<vspace blankLines="1" />
|
||||
<list style="empty">
|
||||
<t>m=audio 8088 RTP/AVP 97</t>
|
||||
<t>a=rtpmap:97 CELT/48000/1</t>
|
||||
</list>
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Note that the RTP payload type code of 97 is defined in this media
|
||||
definition to be 'mapped' to the CELT codec at a 48 kHz sampling
|
||||
frequency using the 'a=rtpmap' line. Any number from 96 to 127
|
||||
could have been chosen (the allowed range for dynamic types). If there
|
||||
is more than one channel being encoded the rtpmap MUST specify the channel
|
||||
count. When no channel count is included, the default is one channel.
|
||||
</t>
|
||||
|
||||
|
||||
<t>The following example demonstrates the use of the a=fmtp: parameters:</t>
|
||||
|
||||
<t>
|
||||
<vspace blankLines="1" />
|
||||
<list style="empty">
|
||||
<t>m=audio 8008 RTP/AVP 97</t>
|
||||
<t>a=ptime: 25</t>
|
||||
<t>a=rtpmap:97 CELT/44100</t>
|
||||
<t>a=fmtp:97 frame-size=512;bitrate=48</t>
|
||||
</list>
|
||||
</t>
|
||||
|
||||
<t>
|
||||
This examples illustrate an offerer that wishes to receive a CELT stream at
|
||||
44100 Hz, by packing two 512-sample frames in each packet (less than 25 ms)
|
||||
at around 48 kbps (70 bytes per frame).
|
||||
</t>
|
||||
|
||||
<section anchor="Multichannel Mapping" title="Multichannel Mapping">
|
||||
<t>
|
||||
When more than two channels are used, a mapping parameter MUST be provided.
|
||||
The mapping parameter is defined as comma separated list of integers which specify the
|
||||
number of channels contained in each CELT stream, OPTIONALLY followed by a '/' and a
|
||||
comma separated list of channel identifiers, then OPTIONALLY another '/' and a string
|
||||
which provides an application specific elaboration on any speaker-feed definitions.
|
||||
The channels per stream entries MUST be either 1 or 2. The total number of
|
||||
channels is indicated by the sum of the channels per stream entries. The sum
|
||||
of the channel counts MUST be equal to the total number of channels.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Channel identifiers are short alphanumeric strings.
|
||||
Each identifier MUST begin with a letter indicating the type of channel. 'A' MUST be
|
||||
used to indicate an ambisonic channel, 'S' to indicate a speaker-feed channel, or 'O'
|
||||
indicating other usage.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
A channel identifier MAY be repeated, but the meaning of such repetition is application specific.
|
||||
Applications SHOULD attempt to utilize channel identifiers such that mixing all identical identifiers
|
||||
would produce a reasonable result.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Non-surround usage such as individual performer tracks, effect send, "order wire", or
|
||||
other administrative channels may be given application specific identifiers
|
||||
which MUST not conflict with the identifiers defined in this draft. These
|
||||
identifiers SHOULD begin with S if it would be sensible to include them in a
|
||||
mono-downmix, or O if it would be most sensible to exclude them from a
|
||||
mono-downmix.
|
||||
An example usage might be
|
||||
mapping=2,1,2,1,1/SLguitar,SRguitar,OheadsetG,SLkeyboard,SRkeyboard,OheadsetK,SMbass,OheadsetB"
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Ambisonic channels MUST follow the Furse-Malham naming and weighing
|
||||
conventions for up to third order spherical<xref target="Ambisonic"></xref>.
|
||||
Higher order ambisonic support is application defined but MUST NOT reuse any of WXYZRSTUVKLMNOPQ
|
||||
for higher order components. For example, second order spherical ambisonics SHOULD use the
|
||||
mapping "mapping=1,1,1,1,1,1,1,1,1/AW,AX,AY,AZ,AR,AS,AT,AU,AV". Any set of Ambisonic channels
|
||||
MUST contain at least one "AW" channel.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Speaker-feed identifiers are named based on the intended speaker locations. "L", "R" for the left and
|
||||
right speakers, respectively, in conventional stereo or the front left and right in 4, 5,
|
||||
5.1, or 7.1 channel surround. "LR", "RR" for the left and right rear speakers in 4,5 or 5.1 channel surround. C" is used for a center channel, "MLFE" for a low frequency extension channel. "LS", "RS" for the side
|
||||
channels in 7.1 channel surround. Additional speaker-feeds are application specific but should not
|
||||
reuse the prior identifiers.
|
||||
For 5.1 surround in non-ambisonic form the mapping SHOULD be "mapping=2,2,1,1/L,R,LR,RR,C,MLFE/ITU-RBS.775-1".
|
||||
When only one or two channels are used, the mapping parameter MAY be omitted, in which case the
|
||||
default mapping is used. For one channel, the default is "mapping=1/C", while for two channels,
|
||||
the default is "mapping=2/L,R".
|
||||
</t>
|
||||
|
||||
<t>
|
||||
For example a stereo configuration might signal:
|
||||
<vspace blankLines="1" />
|
||||
<list style="empty">
|
||||
<t>m=audio 8008 RTP/AVP 97</t>
|
||||
<t>a=ptime: 5</t>
|
||||
<t>a=rtpmap:97 CELT/44100/2</t>
|
||||
<t>a=fmtp:97 frame-size=256</t>
|
||||
</list>
|
||||
Which specifies a single two-channel CELT stream according to the default
|
||||
mapping.
|
||||
</t>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="low-overhead" title="Low-Overhead Mode">
|
||||
|
||||
<t>A low-overhead mode is defined to make more efficient use of bandwidth
|
||||
when transmitting CELT frames. In that mode none of the length values need to be transmitted.
|
||||
One the a=fmtp: parameter low-overhead:
|
||||
is defined and contains a single frame size, followed by a '/', followed by a comma-separated
|
||||
list of the number of bytes per frame for each stream defined in the channel mapping. The number of frames per channel can thus be computed as the payload size divided by the sum of the bytes-per-frame values.
|
||||
The frame-size: parameter MUST not be specified and SHOULD be ignored if encountered
|
||||
in an SDP offer or answer. The bitrate: parameter MUST also be
|
||||
ignored since the low-overhead: parameter makes it redundant. When the low-overhead:
|
||||
parameter is specified, the length of each frame MUST NOT be encoded in the payload and
|
||||
the bit-rate MUST NOT be changed during the session.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
For example a low-overhead 64 kbit/s mono stream could be signaled as:
|
||||
<list style="empty">
|
||||
<t>m=audio 8008 RTP/AVP 97</t>
|
||||
<t>a=ptime: 5</t>
|
||||
<t>a=rtpmap:97 CELT/48000/1</t>
|
||||
<t>a=fmtp:97 low-overhead=256/43</t>
|
||||
</list>
|
||||
|
||||
and a low-overhead 360 kbit/s 5.1 surround configuration could be signaled as:
|
||||
<list style="empty">
|
||||
<t>m=audio 8008 RTP/AVP 97</t>
|
||||
<t>a=ptime: 5</t>
|
||||
<t>a=rtpmap:97 CELT/48000/6</t>
|
||||
<t>a=fmtp:97 low-overhead=256/86,86,43,25;mapping=2,2,1,1/L,R,LR,RR,C,MLFE/ITU-RBS.775-1</t>
|
||||
</list>
|
||||
|
||||
In this last example, 4 bytes per packet would be saved. This corresponds to a 6 kbit/s
|
||||
reduction in the overhead, although the 60 kbit/s overhead of the IP, UDP and RTP
|
||||
headers is still present.
|
||||
</t>
|
||||
|
||||
</section>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="Congestion Control" title="Congestion Control">
|
||||
|
||||
<t>
|
||||
CELT allows any bitrate, with a one byte per frame
|
||||
resolution, without any signaling requirement or overhead.
|
||||
Applications SHOULD utilize congestion control to regulate the transmitted bitrate.
|
||||
In some applications it may make sense to increase the packetization
|
||||
interval rather than decreasing the codec bitrate. Congestion control
|
||||
implementations should consider the users differential tolerance for high
|
||||
latency and low quality.
|
||||
</t>
|
||||
</section>
|
||||
|
||||
<section anchor="Security Considerations" title="Security Considerations">
|
||||
|
||||
<t>
|
||||
RTP packets using the payload format defined in this specification
|
||||
are subject to the security considerations discussed in the RTP
|
||||
specification <xref target="rfc3550"></xref>, and in any applicable RTP profile. The
|
||||
main security considerations for the RTP packet carrying the RTP
|
||||
payload format defined within this memo are confidentiality,
|
||||
integrity and source authenticity. Confidentiality is achieved by
|
||||
encryption of the RTP payload. Integrity of the RTP packets through
|
||||
suitable cryptographic integrity protection mechanism. Cryptographic
|
||||
system may also allow the authentication of the source of the
|
||||
payload. A suitable security mechanism for this RTP payload format
|
||||
should provide confidentiality, integrity protection and at least
|
||||
source authentication capable of determining if an RTP packet is from
|
||||
a member of the RTP session or not.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Note that the appropriate mechanism to provide security to RTP and
|
||||
payloads following this memo may vary. It is dependent on the
|
||||
application, the transport, and the signalling protocol employed.
|
||||
Therefore a single mechanism is not sufficient, although if suitable
|
||||
the usage of SRTP <xref target="rfc3711"></xref> is recommended. Other mechanism that may
|
||||
be used are IPsec <xref target="rfc4301"></xref> and TLS <xref target="rfc5246"></xref> (RTP over TCP), but also other alternatives may exist.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
This RTP payload format and its media decoder do not exhibit any
|
||||
significant non-uniformity in the receiver-side computational
|
||||
complexity for packet processing, and thus are unlikely to pose a
|
||||
denial-of-service threat due to the receipt of pathological data.
|
||||
Nor does the RTP payload format contain any active content.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
Because this format supports VBR operation small amounts of information
|
||||
about the transmitted audio may be leaked by a length preserving
|
||||
cryptographic transport. Accordingly, when CELT is used inside a secure
|
||||
transport the sender SHOULD restrict the use of VBR to congestion control purposes.
|
||||
</t>
|
||||
|
||||
<t>
|
||||
CELT implementations will typically exhibit tiny content-sensitive encoding
|
||||
time variances. Since transmission is usually triggered by an accurate
|
||||
hardware clock and the encoded data is typically transmitted as soon as
|
||||
encoding is complete this variance may result in a small amount of
|
||||
additional frame to frame jitter which could be measured by a third-party.
|
||||
Encrypted implementations SHOULD transmit packets at fixed intervals to
|
||||
avoid the possible information leak.
|
||||
</t>
|
||||
|
||||
</section>
|
||||
|
||||
<section anchor="Acknowledgments" title="Acknowledgments">
|
||||
|
||||
<t>
|
||||
The authors would also like to thank the following people for their input:
|
||||
Timothy B. Terriberry, Ben Schwartz, Alexander Carot, Thorvald Natvig,
|
||||
Brian West, Steve Underwood, and Anthony Minessale.
|
||||
|
||||
</t>
|
||||
</section>
|
||||
|
||||
</middle>
|
||||
|
||||
<back>
|
||||
|
||||
<references title="Normative References">
|
||||
|
||||
<reference anchor="rfc2119">
|
||||
<front>
|
||||
<title>Key words for use in RFCs to Indicate Requirement Levels </title>
|
||||
<author initials="S." surname="Bradner" fullname="Scott Bradner"><organization/></author>
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="2119" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc3550">
|
||||
<front>
|
||||
<title>RTP: A Transport Protocol for real-time applications</title>
|
||||
<author initials="H." surname="Schulzrinne" fullname=""><organization/></author>
|
||||
<author initials="S." surname="Casner" fullname=""><organization/></author>
|
||||
<author initials="R." surname="Frederick" fullname=""><organization/></author>
|
||||
<author initials="V." surname="Jacobson" fullname=""><organization/></author>
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="3550" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc2045">
|
||||
<front>
|
||||
<title>Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies</title>
|
||||
<author initials="" surname="" fullname=""><organization/></author>
|
||||
<date month="November" year="1998" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="2045" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc4566">
|
||||
<front>
|
||||
<title>SDP: Session Description Protocol</title>
|
||||
<author initials="M." surname="Handley" fullname=""><organization/></author>
|
||||
<author initials="V." surname="Jacobson" fullname=""><organization/></author>
|
||||
<author initials="C." surname="Perkins" fullname=""><organization/></author>
|
||||
<date month="July" year="2006" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="4566" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc3551">
|
||||
<front>
|
||||
<title>RTP Profile for Audio and Video Conferences with Minimal Control.</title>
|
||||
<author initials="H." surname="Schulzrinne" fullname=""><organization/></author>
|
||||
<author initials="S." surname="Casner" fullname=""><organization/></author>
|
||||
<date month="July" year="2003" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="3551" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc3534">
|
||||
<front>
|
||||
<title>The application/ogg Media Type</title>
|
||||
<author initials="L." surname="Walleij" fullname=""><organization/></author>
|
||||
<date month="May" year="2003" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="3534" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc3711">
|
||||
<front>
|
||||
<title>The Secure Real-time Transport Protocol (SRTP)</title>
|
||||
<author initials="M." surname="Baugher" fullname=""><organization/></author>
|
||||
<author initials="D." surname="McGrew" fullname=""><organization/></author>
|
||||
<author initials="M." surname="Naslund" fullname=""><organization/></author>
|
||||
<author initials="E." surname="Carrara" fullname=""><organization/></author>
|
||||
<author initials="K." surname="Norrman" fullname=""><organization/></author>
|
||||
<date month="March" year="2004" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="3711" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc4301">
|
||||
<front>
|
||||
<title>Security Architecture for the Internet Protocol</title>
|
||||
<author initials="S." surname="Kent" fullname=""><organization/></author>
|
||||
<author initials="K." surname="Seo" fullname=""><organization/></author>
|
||||
<date month="December" year="2005" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="4301" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="rfc5246">
|
||||
<front>
|
||||
<title>The Transport Layer Security (TLS) Protocol Version 1.2</title>
|
||||
<author initials="T." surname="Dierks" fullname=""><organization/></author>
|
||||
<author initials="E." surname="Rescorla" fullname=""><organization/></author>
|
||||
<date month="August" year="2008" />
|
||||
</front>
|
||||
<seriesInfo name="RFC" value="5246" />
|
||||
</reference>
|
||||
|
||||
|
||||
</references>
|
||||
|
||||
<references title="Informative References">
|
||||
|
||||
<reference anchor="celt-website">
|
||||
<front>
|
||||
<title>The CELT ultra-low delay audio codec</title>
|
||||
<author initials="" surname="Xiph.Org Foundation" fullname="Xiph.Org Foundation"><organization/></author>
|
||||
</front>
|
||||
<seriesInfo name="CELT website" value="http://www.celt-codec.org/" />
|
||||
</reference>
|
||||
|
||||
<reference anchor="Ambisonic">
|
||||
<front>
|
||||
<title>Higher order Ambisonic systems</title>
|
||||
<author initials="D." surname="Malham" fullname="Dave
|
||||
Malham"><organization/></author>
|
||||
<date month="December" year="2003" />
|
||||
</front>
|
||||
<seriesInfo name="Paper"
|
||||
value="http://www.york.ac.uk/inst/mustech/3d_audio/higher_order_ambisonics.pdf" />
|
||||
</reference>
|
||||
|
||||
</references>
|
||||
|
||||
</back>
|
||||
</rfc>
|
||||
@@ -1,18 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
mkdir -p xml_source
|
||||
|
||||
for i in `ls source/ | grep '\.[ch]$'` Makefile
|
||||
do
|
||||
|
||||
echo "<section anchor=\"$i\" title=\"$i\">" > xml_source/$i
|
||||
echo '<t>' >> xml_source/$i
|
||||
echo '<figure><artwork><![CDATA[' >> xml_source/$i
|
||||
|
||||
cat source/$i >> xml_source/$i
|
||||
|
||||
echo ']]></artwork></figure>' >> xml_source/$i
|
||||
echo '</t>' >> xml_source/$i
|
||||
echo '</section>' >> xml_source/$i
|
||||
|
||||
done
|
||||
@@ -1,99 +0,0 @@
|
||||
#define IMUL32(a,b) ((a)*(b))
|
||||
#define UMUL32(a,b) ((a)*(b))
|
||||
#define UMUL16_16(a,b) ((a)*(b))
|
||||
|
||||
#define celt_word16 float
|
||||
#define celt_word32 float
|
||||
|
||||
#define celt_sig float
|
||||
#define celt_norm float
|
||||
#define celt_ener float
|
||||
#define celt_pgain float
|
||||
#define celt_mask float
|
||||
|
||||
#define UADD32(a,b) ((a)+(b))
|
||||
#define USUB32(a,b) ((a)-(b))
|
||||
|
||||
|
||||
#define Q15ONE 1.0f
|
||||
#define Q30ONE 1.0f
|
||||
|
||||
#define NORM_SCALING 1.f
|
||||
#define NORM_SCALING_1 1.f
|
||||
#define ENER_SCALING 1.f
|
||||
#define ENER_SCALING_1 1.f
|
||||
#define PGAIN_SCALING 1.f
|
||||
#define PGAIN_SCALING_1 1.f
|
||||
|
||||
#define DB_SCALING 1.f
|
||||
#define DB_SCALING_1 1.f
|
||||
|
||||
#define EPSILON 1e-15f
|
||||
#define VERY_SMALL 1e-15f
|
||||
#define VERY_LARGE32 1e15f
|
||||
#define VERY_LARGE16 1e15f
|
||||
#define Q15_ONE 1.f
|
||||
#define Q15_ONE_1 1.f
|
||||
|
||||
#define QCONST16(x,bits) (x)
|
||||
#define QCONST32(x,bits) (x)
|
||||
|
||||
#define NEG16(x) (-(x))
|
||||
#define NEG32(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 PSHR16(a,shift) (a)
|
||||
#define PSHR32(a,shift) (a)
|
||||
#define VSHR32(a,shift) (a)
|
||||
#define SATURATE16(x,a) (x)
|
||||
#define SATURATE32(x,a) (x)
|
||||
|
||||
#define PSHR(a,shift) (a)
|
||||
#define SHR(a,shift) (a)
|
||||
#define SHL(a,shift) (a)
|
||||
#define SATURATE(x,a) (x)
|
||||
|
||||
#define ROUND16(a,shift) (a)
|
||||
#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 MULT16_16_16(a,b) ((a)*(b))
|
||||
#define MULT16_16(a,b) ((a)*(b))
|
||||
#define MAC16_16(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
#define MULT16_32_Q11(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q13(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q14(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q16(a,b) ((a)*(b))
|
||||
#define MULT16_32_P15(a,b) ((a)*(b))
|
||||
|
||||
#define MULT32_32_Q31(a,b) ((a)*(b))
|
||||
|
||||
#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_16_P13(c,a,b) ((c)+(a)*(b))
|
||||
#define MULT16_16_Q11_32(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 DIV32_16(a,b) ((a)/(b))
|
||||
#define PDIV32_16(a,b) ((a)/(b))
|
||||
#define DIV32(a,b) ((a)/(b))
|
||||
#define PDIV32(a,b) ((a)/(b))
|
||||
|
||||
#define PRINT_MIPS(x)
|
||||
@@ -1,34 +0,0 @@
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int main()
|
||||
{
|
||||
int comment = 0;
|
||||
int col = 0;
|
||||
char c0, c1;
|
||||
c0 = getchar();
|
||||
while (!feof(stdin))
|
||||
{
|
||||
c1 = getchar();
|
||||
if (c1==9)
|
||||
c1 = 32;
|
||||
if (col < 71 || c0 == 10) {
|
||||
putchar(c0);
|
||||
} else {
|
||||
if (c1 == 10 || c1 == 13)
|
||||
{
|
||||
putchar(c0);
|
||||
} else {
|
||||
putchar ('\\');
|
||||
/*printf ("%d %d %d", col, c0, c1);*/
|
||||
putchar (10);
|
||||
putchar (c0);
|
||||
col=0;
|
||||
}
|
||||
}
|
||||
col++;
|
||||
if (c0 == 10)
|
||||
col=0;
|
||||
c0 = c1;
|
||||
}
|
||||
}
|
||||
@@ -1,84 +0,0 @@
|
||||
Summary: The CELT Low-Latency Audio Compression Codec.
|
||||
Name: libcelt
|
||||
Version: @CELT_VERSION@
|
||||
Release: 0%{?dist}
|
||||
Epoch: 0
|
||||
Group: System Environment/Libraries
|
||||
License: BSD
|
||||
URL: http://www.xiph.org/
|
||||
Source: http://downloads.xiph.org/releases/celt/celt-%{version}.tar.gz
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
BuildRequires: libogg-devel >= 2:1.1
|
||||
Requires: pkg-config
|
||||
|
||||
%description
|
||||
CELT is a fully open, non-proprietary, patent- and royalty-free,
|
||||
low-latency compressed audio format for voice and music.
|
||||
|
||||
The libcelt package contains runtime libraries for use in programs
|
||||
that support Ogg CELT.
|
||||
|
||||
%package devel
|
||||
Summary: Files for CELT application development.
|
||||
Group: Development/Libraries
|
||||
Requires: libogg-devel >= 2:1.1
|
||||
Requires: libcelt = %{epoch}:%{version}-%{release}
|
||||
|
||||
%description devel
|
||||
The libcelt-devel package contains the header files and documentation
|
||||
needed to develop applications with Ogg CELT.
|
||||
|
||||
%package utils
|
||||
Summary: CELT codec utilities.
|
||||
Group: Applications/Multimedia
|
||||
Requires: libcelt = %{epoch}:%{version}-%{release}
|
||||
|
||||
%description utils
|
||||
Basic utilities for encoding, decoding and manipulating Ogg CELT streams.
|
||||
|
||||
%prep
|
||||
|
||||
%setup -q -n celt-%{version}
|
||||
|
||||
%build
|
||||
%configure --with-ogg-libraries=%{_libdir}
|
||||
make
|
||||
|
||||
%check
|
||||
make check
|
||||
|
||||
%install
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
make DESTDIR=$RPM_BUILD_ROOT install
|
||||
|
||||
# remove unpackaged files from the buildroot
|
||||
rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
|
||||
rm -f $RPM_BUILD_ROOT%{_libdir}/*.a
|
||||
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%doc AUTHORS COPYING README
|
||||
%{_libdir}/libcelt.so.*
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root)
|
||||
%{_includedir}/celt
|
||||
%{_libdir}/libcelt.so
|
||||
%{_libdir}/pkgconfig/*.pc
|
||||
|
||||
%files utils
|
||||
%defattr(-,root,root)
|
||||
%{_bindir}/celtenc
|
||||
%{_bindir}/celtdec
|
||||
|
||||
%clean
|
||||
rm -rf $RPM_BUILD_ROOT
|
||||
|
||||
%post -p /sbin/ldconfig
|
||||
|
||||
%postun -p /sbin/ldconfig
|
||||
|
||||
%changelog
|
||||
* Mon Dec 22 2008 Monty Montgomery <monty@xiph.org> 0.5.1-0
|
||||
- initial spec file created
|
||||
@@ -1,39 +0,0 @@
|
||||
# Disable automatic dependency tracking if using other tools than gcc and gmake
|
||||
#AUTOMAKE_OPTIONS = no-dependencies
|
||||
|
||||
|
||||
pkginclude_HEADERS = celt.h celt_types.h celt_header.h
|
||||
EXTRA_DIST= match-test.sh libcelt.vcxproj libcelt.vcxproj.filters
|
||||
|
||||
#INCLUDES = -I$(top_srcdir)/include -I$(top_builddir)/include -I$(top_builddir) @OGG_CFLAGS@
|
||||
|
||||
TESTS = match-test.sh
|
||||
|
||||
noinst_SCRIPTS = match-test.sh
|
||||
|
||||
lib_LTLIBRARIES = libcelt@LIBCELT_SUFFIX@.la
|
||||
|
||||
# Sources for compilation in the library
|
||||
libcelt@LIBCELT_SUFFIX@_la_SOURCES = bands.c celt.c cwrs.c ecintrin.h entcode.c \
|
||||
entdec.c entenc.c header.c kiss_fft.c laplace.c mathops.c mdct.c \
|
||||
modes.c pitch.c plc.c quant_bands.c rate.c vq.c
|
||||
|
||||
libcelt@LIBCELT_SUFFIX@_la_LDFLAGS = \
|
||||
-version-info @CELT_LT_CURRENT@:@CELT_LT_REVISION@:@CELT_LT_AGE@ \
|
||||
-no-undefined
|
||||
|
||||
noinst_HEADERS = _kiss_fft_guts.h arch.h bands.h fixed_c5x.h fixed_c6x.h \
|
||||
cwrs.h ecintrin.h entcode.h entdec.h entenc.h fixed_generic.h float_cast.h \
|
||||
kiss_fft.h laplace.h mdct.h mfrngcod.h \
|
||||
mathops.h modes.h os_support.h pitch.h \
|
||||
quant_bands.h rate.h stack_alloc.h \
|
||||
static_modes_fixed.c static_modes_float.c vq.h plc.h
|
||||
|
||||
noinst_PROGRAMS = testcelt dump_modes
|
||||
testcelt_SOURCES = testcelt.c
|
||||
testcelt_LDADD = libcelt@LIBCELT_SUFFIX@.la
|
||||
INCLUDES =
|
||||
#libcelt@LIBCELT_SUFFIX@_la_LIBADD =
|
||||
|
||||
dump_modes_SOURCES = dump_modes.c
|
||||
dump_modes_LDADD = libcelt@LIBCELT_SUFFIX@.la
|
||||
@@ -1,197 +0,0 @@
|
||||
/*
|
||||
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 DOUBLE_PRECISION
|
||||
|
||||
#ifdef DOUBLE_PRECISION
|
||||
|
||||
# define FRACBITS 31
|
||||
# define SAMPPROD long long
|
||||
#define SAMP_MAX 2147483647
|
||||
#define TWID_MAX 32767
|
||||
#define TRIG_UPSCALE 1
|
||||
#define EXT32(a) (a)
|
||||
|
||||
#else /* DOUBLE_PRECISION */
|
||||
|
||||
# define FRACBITS 15
|
||||
# define SAMPPROD celt_int32
|
||||
#define SAMP_MAX 32767
|
||||
#define TRIG_UPSCALE 1
|
||||
#define EXT32(a) EXTEND32(a)
|
||||
|
||||
#endif /* !DOUBLE_PRECISION */
|
||||
|
||||
#define SAMP_MIN -SAMP_MAX
|
||||
|
||||
#if defined(CHECK_OVERFLOW)
|
||||
# define CHECK_OVERFLOW_OP(a,op,b) \
|
||||
if ( (SAMPPROD)(a) op (SAMPPROD)(b) > SAMP_MAX || (SAMPPROD)(a) op (SAMPPROD)(b) < SAMP_MIN ) { \
|
||||
fprintf(stderr,"WARNING:overflow @ " __FILE__ "(%d): (%d " #op" %d) = %ld\n",__LINE__,(a),(b),(SAMPPROD)(a) op (SAMPPROD)(b) ); }
|
||||
#endif
|
||||
|
||||
# define smul(a,b) ( (SAMPPROD)(a)*(b) )
|
||||
# define sround( x ) (kiss_fft_scalar)( ( (x) + ((SAMPPROD)1<<(FRACBITS-1)) ) >> FRACBITS )
|
||||
|
||||
|
||||
# define S_MUL(a,b) MULT16_32_Q15(b, a)
|
||||
|
||||
# define C_MUL(m,a,b) \
|
||||
do{ (m).r = SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)); }while(0)
|
||||
|
||||
# define C_MULC(m,a,b) \
|
||||
do{ (m).r = ADD32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)); \
|
||||
(m).i = SUB32(S_MUL((a).i,(b).r) , S_MUL((a).r,(b).i)); }while(0)
|
||||
|
||||
# define C_MUL4(m,a,b) \
|
||||
do{ (m).r = SHR(SUB32(S_MUL((a).r,(b).r) , S_MUL((a).i,(b).i)),2); \
|
||||
(m).i = SHR(ADD32(S_MUL((a).r,(b).i) , S_MUL((a).i,(b).r)),2); }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((a).r,(b).r); (res).i=ADD32((a).i,(b).i); \
|
||||
}while(0)
|
||||
#define C_SUB( res, a,b)\
|
||||
do {(res).r=SUB32((a).r,(b).r); (res).i=SUB32((a).i,(b).i); \
|
||||
}while(0)
|
||||
#define C_ADDTO( res , a)\
|
||||
do {(res).r = ADD32((res).r, (a).r); (res).i = ADD32((res).i,(a).i);\
|
||||
}while(0)
|
||||
|
||||
#define C_SUBFROM( res , a)\
|
||||
do {(res).r = ADD32((res).r,(a).r); (res).i = SUB32((res).i,(a).i); \
|
||||
}while(0)
|
||||
|
||||
|
||||
|
||||
|
||||
#else /* not FIXED_POINT*/
|
||||
|
||||
#define EXT32(a) (a)
|
||||
|
||||
# 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 */
|
||||
@@ -1,253 +0,0 @@
|
||||
/* 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 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 ARCH_H
|
||||
#define ARCH_H
|
||||
|
||||
#include "celt_types.h"
|
||||
|
||||
#define CELT_SIG_SCALE 32768.f
|
||||
|
||||
#define celt_fatal(str) _celt_fatal(str, __FILE__, __LINE__);
|
||||
#ifdef ENABLE_ASSERTIONS
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
static inline 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();
|
||||
}
|
||||
#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);}}
|
||||
#else
|
||||
#define celt_assert(cond)
|
||||
#define celt_assert2(cond, message)
|
||||
#endif
|
||||
|
||||
#define IMUL32(a,b) ((a)*(b))
|
||||
#define UMUL32(a,b) ((celt_int32)(a)*(celt_int32)(b))
|
||||
#define UMUL16_16(a,b) ((celt_int32)(a)*(celt_int32)(b))
|
||||
|
||||
#define ABS(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute integer value. */
|
||||
#define ABS16(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 16-bit value. */
|
||||
#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 ABS32(x) ((x) < 0 ? (-(x)) : (x)) /**< Absolute 32-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))
|
||||
|
||||
#define PRINT_MIPS(file)
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
typedef celt_int16 celt_word16;
|
||||
typedef celt_int32 celt_word32;
|
||||
|
||||
typedef celt_word32 celt_sig;
|
||||
typedef celt_word16 celt_norm;
|
||||
typedef celt_word32 celt_ener;
|
||||
typedef celt_word32 celt_mask;
|
||||
|
||||
#define Q15ONE 32767
|
||||
#define Q30ONE 1073741823
|
||||
|
||||
#define SIG_SHIFT 12
|
||||
|
||||
#define NORM_SCALING 16384
|
||||
#define NORM_SCALING_1 (1.f/16384.f)
|
||||
#define NORM_SHIFT 14
|
||||
|
||||
#define ENER_SCALING 16384.f
|
||||
#define ENER_SCALING_1 (1.f/16384.f)
|
||||
#define ENER_SHIFT 14
|
||||
|
||||
#define PGAIN_SCALING 32768.f
|
||||
#define PGAIN_SCALING_1 (1.f/32768.f)
|
||||
#define PGAIN_SHIFT 15
|
||||
|
||||
#define DB_SHIFT 10
|
||||
|
||||
#define EPSILON 1
|
||||
#define VERY_SMALL 0
|
||||
#define VERY_LARGE32 ((celt_word32)2147483647)
|
||||
#define VERY_LARGE16 ((celt_word16)32767)
|
||||
#define Q15_ONE ((celt_word16)32767)
|
||||
#define Q15_ONE_1 (1.f/32768.f)
|
||||
|
||||
#define SCALEIN(a) (a)
|
||||
#define SCALEOUT(a) (a)
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
#include "fixed_debug.h"
|
||||
#else
|
||||
|
||||
#include "fixed_generic.h"
|
||||
|
||||
#ifdef ARM5E_ASM
|
||||
#include "fixed_arm5e.h"
|
||||
#elif defined (ARM4_ASM)
|
||||
#include "fixed_arm4.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 celt_word16;
|
||||
typedef float celt_word32;
|
||||
|
||||
typedef float celt_sig;
|
||||
typedef float celt_norm;
|
||||
typedef float celt_ener;
|
||||
typedef float celt_pgain;
|
||||
typedef float celt_mask;
|
||||
|
||||
#define Q15ONE 1.0f
|
||||
#define Q30ONE 1.0f
|
||||
|
||||
#define NORM_SCALING 1.f
|
||||
#define NORM_SCALING_1 1.f
|
||||
#define ENER_SCALING 1.f
|
||||
#define ENER_SCALING_1 1.f
|
||||
#define PGAIN_SCALING 1.f
|
||||
#define PGAIN_SCALING_1 1.f
|
||||
|
||||
#define EPSILON 1e-15f
|
||||
#define VERY_SMALL 1e-15f
|
||||
#define VERY_LARGE32 1e15f
|
||||
#define VERY_LARGE16 1e15f
|
||||
#define Q15_ONE ((celt_word16)1.f)
|
||||
#define Q15_ONE_1 ((celt_word16)1.f)
|
||||
|
||||
#define QCONST16(x,bits) (x)
|
||||
#define QCONST32(x,bits) (x)
|
||||
|
||||
#define NEG16(x) (-(x))
|
||||
#define NEG32(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 PSHR16(a,shift) (a)
|
||||
#define PSHR32(a,shift) (a)
|
||||
#define VSHR32(a,shift) (a)
|
||||
#define SATURATE16(x,a) (x)
|
||||
#define SATURATE32(x,a) (x)
|
||||
|
||||
#define PSHR(a,shift) (a)
|
||||
#define SHR(a,shift) (a)
|
||||
#define SHL(a,shift) (a)
|
||||
#define SATURATE(x,a) (x)
|
||||
|
||||
#define ROUND16(a,shift) (a)
|
||||
#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 MULT16_16_16(a,b) ((a)*(b))
|
||||
#define MULT16_16(a,b) ((celt_word32)(a)*(celt_word32)(b))
|
||||
#define MAC16_16(c,a,b) ((c)+(celt_word32)(a)*(celt_word32)(b))
|
||||
|
||||
#define MULT16_32_Q11(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q13(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q14(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q15(a,b) ((a)*(b))
|
||||
#define MULT16_32_Q16(a,b) ((a)*(b))
|
||||
#define MULT16_32_P15(a,b) ((a)*(b))
|
||||
|
||||
#define MULT32_32_Q31(a,b) ((a)*(b))
|
||||
|
||||
#define MAC16_32_Q11(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_32_Q15(c,a,b) ((c)+(a)*(b))
|
||||
|
||||
#define MAC16_16_Q11(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_16_Q13(c,a,b) ((c)+(a)*(b))
|
||||
#define MAC16_16_P13(c,a,b) ((c)+(a)*(b))
|
||||
#define MULT16_16_Q11_32(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 DIV32_16(a,b) (((celt_word32)(a))/(celt_word16)(b))
|
||||
#define PDIV32_16(a,b) (((celt_word32)(a))/(celt_word16)(b))
|
||||
#define DIV32(a,b) (((celt_word32)(a))/(celt_word32)(b))
|
||||
#define PDIV32(a,b) (((celt_word32)(a))/(celt_word32)(b))
|
||||
|
||||
#define SCALEIN(a) ((a)*CELT_SIG_SCALE)
|
||||
#define SCALEOUT(a) ((a)*(1/CELT_SIG_SCALE))
|
||||
|
||||
#endif /* !FIXED_POINT */
|
||||
|
||||
|
||||
#if defined (CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
|
||||
/* 2 on TI C5x DSP */
|
||||
#define BYTES_PER_CHAR 2
|
||||
#define BITS_PER_CHAR 16
|
||||
#define LOG2_BITS_PER_CHAR 4
|
||||
|
||||
#else /* CONFIG_TI_C54X */
|
||||
|
||||
#define BYTES_PER_CHAR 1
|
||||
#define BITS_PER_CHAR 8
|
||||
#define LOG2_BITS_PER_CHAR 3
|
||||
|
||||
#endif /* !CONFIG_TI_C54X */
|
||||
|
||||
#ifndef GLOBAL_STACK_SIZE
|
||||
#ifdef FIXED_POINT
|
||||
#define GLOBAL_STACK_SIZE 100000
|
||||
#else
|
||||
#define GLOBAL_STACK_SIZE 100000
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ARCH_H */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,98 +0,0 @@
|
||||
/* 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 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 BANDS_H
|
||||
#define BANDS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "modes.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "rate.h"
|
||||
|
||||
/** Compute the amplitude (sqrt energy) in each of the bands
|
||||
* @param m Mode data
|
||||
* @param X Spectrum
|
||||
* @param bands Square root of the energy for each band (returned)
|
||||
*/
|
||||
void compute_band_energies(const CELTMode *m, const celt_sig *X, celt_ener *bands, int end, int _C, int M);
|
||||
|
||||
/*void compute_noise_energies(const CELTMode *m, const celt_sig *X, const celt_word16 *tonality, celt_ener *bank);*/
|
||||
|
||||
/** 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 bands Square root of the energy for each band
|
||||
*/
|
||||
void normalise_bands(const CELTMode *m, const celt_sig * restrict freq, celt_norm * restrict X, const celt_ener *bands, 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 bands Square root of the energy for each band
|
||||
*/
|
||||
void denormalise_bands(const CELTMode *m, const celt_norm * restrict X, celt_sig * restrict freq, const celt_ener *bands, int end, int _C, int M);
|
||||
|
||||
#define SPREAD_NONE (0)
|
||||
#define SPREAD_LIGHT (1)
|
||||
#define SPREAD_NORMAL (2)
|
||||
#define SPREAD_AGGRESSIVE (3)
|
||||
|
||||
int spreading_decision(const CELTMode *m, celt_norm *X, int *average,
|
||||
int last_decision, int *hf_average, int *tapset_decision, int update_hf,
|
||||
int end, int _C, int M);
|
||||
|
||||
#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 m Mode data
|
||||
* @param X Residual (normalised)
|
||||
* @param total_bits Total number of bits that can be used for the frame (including the ones already spent)
|
||||
* @param enc Entropy encoder
|
||||
*/
|
||||
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 time_domain, int fold, int dual_stereo, int intensity, int *tf_res, int resynth,
|
||||
celt_int32 total_bits, celt_int32 balance, ec_ctx *ec, int M, int codedBands, celt_uint32 *seed);
|
||||
|
||||
|
||||
void stereo_decision(const CELTMode *m, celt_norm * restrict X, int *stereo_mode, int len, int M);
|
||||
|
||||
void anti_collapse(const CELTMode *m, celt_norm *_X, unsigned char *collapse_masks, int LM, int C, int CC, int size,
|
||||
int start, int end, celt_word16 *logE, celt_word16 *prev1logE,
|
||||
celt_word16 *prev2logE, int *pulses, celt_uint32 seed);
|
||||
|
||||
celt_uint32 lcg_rand(celt_uint32 seed);
|
||||
|
||||
#endif /* BANDS_H */
|
||||
@@ -1,340 +0,0 @@
|
||||
/* (c) Copyright 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 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.
|
||||
*/
|
||||
|
||||
#include "c64_fft.h"
|
||||
|
||||
#include "dsp_fft16x16t.h"
|
||||
#include "dsp_fft32x32s.h"
|
||||
#include "dsp_ifft32x32.h"
|
||||
|
||||
#ifndef PI
|
||||
# ifdef M_PI
|
||||
# define PI M_PI
|
||||
# else
|
||||
# define PI 3.14159265358979323846
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* D2S -- Truncate a 'double' to a 'short', with clamping. */
|
||||
/* ======================================================================== */
|
||||
static short d2s(double d)
|
||||
{
|
||||
if (d >= 32767.0) return 32767;
|
||||
if (d <= -32768.0) return -32768;
|
||||
return (short)d;
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* D2S -- Truncate a 'double' to a 'int', with clamping. */
|
||||
/* ======================================================================== */
|
||||
static int d2i(double d)
|
||||
{
|
||||
if (d >= 2147483647.0) return (int)0x7FFFFFFF;
|
||||
if (d <= -2147483648.0) return (int)0x80000000;
|
||||
return (int)d;
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* GEN_TWIDDLE -- Generate twiddle factors for TI's custom FFTs. */
|
||||
/* */
|
||||
/* USAGE */
|
||||
/* This routine is called as follows: */
|
||||
/* */
|
||||
/* int gen_twiddle(short *w, int n, double scale) */
|
||||
/* */
|
||||
/* short *w Pointer to twiddle-factor array */
|
||||
/* int n Size of FFT */
|
||||
/* double scale Scale factor to apply to values. */
|
||||
/* */
|
||||
/* The routine will generate the twiddle-factors directly into the */
|
||||
/* array you specify. The array needs to be approximately 2*N */
|
||||
/* elements long. (The actual size, which is slightly smaller, is */
|
||||
/* returned by the function.) */
|
||||
/* ======================================================================== */
|
||||
int gen_twiddle16(short *w, int n, double scale)
|
||||
{
|
||||
int i, j, k;
|
||||
|
||||
for (j = 1, k = 0; j < n >> 2; j = j << 2)
|
||||
{
|
||||
for (i = 0; i < n >> 2; i += j << 1)
|
||||
{
|
||||
w[k + 11] = d2s(scale * cos(6.0 * PI * (i + j) / n));
|
||||
w[k + 10] = d2s(scale * sin(6.0 * PI * (i + j) / n));
|
||||
w[k + 9] = d2s(scale * cos(6.0 * PI * (i ) / n));
|
||||
w[k + 8] = d2s(scale * sin(6.0 * PI * (i ) / n));
|
||||
|
||||
w[k + 7] = d2s(scale * cos(4.0 * PI * (i + j) / n));
|
||||
w[k + 6] = d2s(scale * sin(4.0 * PI * (i + j) / n));
|
||||
w[k + 5] = d2s(scale * cos(4.0 * PI * (i ) / n));
|
||||
w[k + 4] = d2s(scale * sin(4.0 * PI * (i ) / n));
|
||||
|
||||
w[k + 3] = d2s(scale * cos(2.0 * PI * (i + j) / n));
|
||||
w[k + 2] = d2s(scale * sin(2.0 * PI * (i + j) / n));
|
||||
w[k + 1] = d2s(scale * cos(2.0 * PI * (i ) / n));
|
||||
w[k + 0] = d2s(scale * sin(2.0 * PI * (i ) / n));
|
||||
|
||||
k += 12;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
|
||||
/* ======================================================================== */
|
||||
/* GEN_TWIDDLE -- Generate twiddle factors for TI's custom FFTs. */
|
||||
/* */
|
||||
/* USAGE */
|
||||
/* This routine is called as follows: */
|
||||
/* */
|
||||
/* int gen_twiddle(int *w, int n, double scale) */
|
||||
/* */
|
||||
/* int *w Pointer to twiddle-factor array */
|
||||
/* int n Size of FFT */
|
||||
/* double scale Scale factor to apply to values. */
|
||||
/* */
|
||||
/* The routine will generate the twiddle-factors directly into the */
|
||||
/* array you specify. The array needs to be approximately 2*N */
|
||||
/* elements long. (The actual size, which is slightly smaller, is */
|
||||
/* returned by the function.) */
|
||||
/* ======================================================================== */
|
||||
int gen_twiddle32(int *w, int n, double scale)
|
||||
{
|
||||
int i, j, k, s=0, t;
|
||||
|
||||
for (j = 1, k = 0; j < n >> 2; j = j << 2, s++)
|
||||
{
|
||||
for (i = t=0; i < n >> 2; i += j, t++)
|
||||
{
|
||||
w[k + 5] = d2i(scale * cos(6.0 * PI * i / n));
|
||||
w[k + 4] = d2i(scale * sin(6.0 * PI * i / n));
|
||||
|
||||
w[k + 3] = d2i(scale * cos(4.0 * PI * i / n));
|
||||
w[k + 2] = d2i(scale * sin(4.0 * PI * i / n));
|
||||
|
||||
w[k + 1] = d2i(scale * cos(2.0 * PI * i / n));
|
||||
w[k + 0] = d2i(scale * sin(2.0 * PI * i / n));
|
||||
|
||||
k += 6;
|
||||
}
|
||||
}
|
||||
|
||||
return k;
|
||||
}
|
||||
|
||||
#define NBCACHE 3
|
||||
static c64_fft_t *cache16[NBCACHE] = {NULL,};
|
||||
static c64_fft_t *cache32[NBCACHE] = {NULL,};
|
||||
|
||||
c64_fft_t *c64_fft16_alloc(int length, int x, int y)
|
||||
{
|
||||
c64_fft_t *state;
|
||||
celt_int16 *w, *iw;
|
||||
|
||||
int i, c;
|
||||
|
||||
for (c = 0; c < NBCACHE; c++) {
|
||||
if (cache16[c] == NULL)
|
||||
break;
|
||||
if (cache16[c]->nfft == length)
|
||||
return cache16[c];
|
||||
}
|
||||
|
||||
state = (c64_fft_t *)celt_alloc(sizeof(c64_fft_t));
|
||||
state->shift = log(length)/log(2) - ceil(log(length)/log(4)-1);
|
||||
state->nfft = length;
|
||||
state->twiddle = celt_alloc(length*2*sizeof(celt_int16));
|
||||
state->itwiddle = celt_alloc(length*2*sizeof(celt_int16));
|
||||
|
||||
gen_twiddle16((celt_int16 *)state->twiddle, length, 32767.0);
|
||||
|
||||
w = (celt_int16 *)state->twiddle;
|
||||
iw = (celt_int16 *)state->itwiddle;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
iw[2*i+0] = w[2*i+0];
|
||||
iw[2*i+1] = - w[2*i+1];
|
||||
}
|
||||
|
||||
if (c < NBCACHE)
|
||||
cache16[c++] = state;
|
||||
if (c < NBCACHE)
|
||||
cache16[c] = NULL;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
c64_fft_t *c64_fft32_alloc(int length, int x, int y)
|
||||
{
|
||||
c64_fft_t *state;
|
||||
int i, c;
|
||||
|
||||
for (c = 0; c < NBCACHE; c++) {
|
||||
if (cache32[c] == NULL)
|
||||
break;
|
||||
if (cache32[c]->nfft == length)
|
||||
return cache32[c];
|
||||
}
|
||||
|
||||
state = (c64_fft_t *)celt_alloc(sizeof(c64_fft_t));
|
||||
state->shift = log(length)/log(2) - ceil(log(length)/log(4)-1);
|
||||
state->nfft = length;
|
||||
state->twiddle = celt_alloc(length*2*sizeof(celt_int32));
|
||||
state->itwiddle = celt_alloc(length*2*sizeof(celt_int32));
|
||||
|
||||
// Generate the inverse twiddle first because it does not need scaling
|
||||
gen_twiddle32(state->itwiddle, length, 2147483647.000000000);
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
state->twiddle[2*i+0] = state->itwiddle[2*i+0] >> 1;
|
||||
state->twiddle[2*i+1] = state->itwiddle[2*i+1] >> 1;
|
||||
}
|
||||
|
||||
if (c < NBCACHE)
|
||||
cache32[c++] = state;
|
||||
if (c < NBCACHE)
|
||||
cache32[c] = NULL;
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
void c64_fft16_free(c64_fft_t *state)
|
||||
{
|
||||
c64_fft32_free(state);
|
||||
}
|
||||
|
||||
|
||||
void c64_fft32_free(c64_fft_t *state)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
void c64_fft16_inplace(c64_fft_t * restrict state, celt_int16 *X)
|
||||
{
|
||||
int i;
|
||||
VARDECL(celt_int16, cin);
|
||||
VARDECL(celt_int16, cout);
|
||||
SAVE_STACK;
|
||||
|
||||
ALLOC(cin, state->nfft*2, celt_int16);
|
||||
ALLOC(cout, state->nfft*2, celt_int16);
|
||||
|
||||
for (i = 0; i < state->nfft; i++) {
|
||||
cin[2*i+0] = X[2*i+0];
|
||||
cin[2*i+1] = X[2*i+1];
|
||||
}
|
||||
|
||||
DSP_fft16x16t((celt_int16 *)state->twiddle, state->nfft, cin, cout);
|
||||
|
||||
for (i = 0; i < state->nfft; i++) {
|
||||
X[2*i+0] = cout[2*i+0];
|
||||
X[2*i+1] = cout[2*i+1];
|
||||
}
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void c64_fft32(c64_fft_t * restrict state, const celt_int32 *X, celt_int32 *Y)
|
||||
{
|
||||
int i;
|
||||
VARDECL(celt_int32, cin);
|
||||
SAVE_STACK;
|
||||
ALLOC(cin, state->nfft*2, celt_int32);
|
||||
|
||||
for (i = 0; i < state->nfft; i++) {
|
||||
cin[2*i+0] = X[2*i+0] >> state->shift;
|
||||
cin[2*i+1] = X[2*i+1] >> state->shift;
|
||||
}
|
||||
|
||||
DSP_fft32x32s(state->twiddle, state->nfft, cin, Y);
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
||||
void c64_ifft16(c64_fft_t * restrict state, const celt_int16 *X, celt_int16 *Y)
|
||||
{
|
||||
int i;
|
||||
VARDECL(celt_int16, cin);
|
||||
VARDECL(celt_int16, cout);
|
||||
SAVE_STACK;
|
||||
|
||||
ALLOC(cin, state->nfft*2, celt_int16);
|
||||
if ((celt_int32)Y & 7)
|
||||
ALLOC(cout, state->nfft*2, celt_int16);
|
||||
else
|
||||
cout = Y;
|
||||
|
||||
for (i = 0; i < state->nfft; i++) {
|
||||
// No need to scale for this one but still need to save the input
|
||||
// because the fft is going to change it!
|
||||
cin[2*i+0] = X[2*i+0];
|
||||
cin[2*i+1] = X[2*i+1];
|
||||
}
|
||||
|
||||
DSP_fft16x16t((celt_int16 *)state->itwiddle, state->nfft, cin, cout);
|
||||
|
||||
if ((celt_int32)Y & 7)
|
||||
for (i = 0; i < state->nfft; i++) {
|
||||
Y[2*i+0] = cout[2*i+0];
|
||||
Y[2*i+1] = cout[2*i+1];
|
||||
}
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
||||
void c64_ifft32(c64_fft_t * restrict state, const celt_int32 *X, celt_int32 *Y)
|
||||
{
|
||||
int i;
|
||||
VARDECL(celt_int32, cin);
|
||||
SAVE_STACK;
|
||||
ALLOC(cin, state->nfft*2, celt_int32);
|
||||
|
||||
celt_assert(Y & 7 == 0);
|
||||
|
||||
for (i = 0; i < state->nfft; i++) {
|
||||
// No need to scale for this one but still need to save the input
|
||||
// because the fft is going to change it!
|
||||
cin[2*i+0] = X[2*i+0];
|
||||
cin[2*i+1] = X[2*i+1];
|
||||
}
|
||||
|
||||
DSP_ifft32x32(state->itwiddle, state->nfft, cin, Y);
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,54 +0,0 @@
|
||||
/* (c) Copyright 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 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 _dsp_fft_h_
|
||||
#define _dsp_fft_h_
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "arch.h"
|
||||
#include "os_support.h"
|
||||
#include "mathops.h"
|
||||
#include "stack_alloc.h"
|
||||
|
||||
typedef struct {
|
||||
int nfft;
|
||||
int shift;
|
||||
celt_int32 *twiddle;
|
||||
celt_int32 *itwiddle;
|
||||
} c64_fft_t;
|
||||
|
||||
extern c64_fft_t *c64_fft16_alloc(int length, int x, int y);
|
||||
extern void c64_fft16_free(c64_fft_t *state);
|
||||
extern void c64_fft16_inplace(c64_fft_t *state, celt_int16 *X);
|
||||
extern void c64_ifft16(c64_fft_t *state, const celt_int16 *X, celt_int16 *Y);
|
||||
|
||||
extern c64_fft_t *c64_fft32_alloc(int length, int x, int y);
|
||||
extern void c64_fft32_free(c64_fft_t *state);
|
||||
extern void c64_fft32(c64_fft_t *state, const celt_int32 *X, celt_int32 *Y);
|
||||
extern void c64_ifft32(c64_fft_t *state, const celt_int32 *X, celt_int32 *Y);
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,325 +0,0 @@
|
||||
/* 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 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 CELT_H
|
||||
#define CELT_H
|
||||
|
||||
#include "celt_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__) && defined(CELT_BUILD)
|
||||
#define EXPORT __attribute__ ((visibility ("default")))
|
||||
#elif defined(WIN32)
|
||||
#define EXPORT __declspec(dllexport)
|
||||
#else
|
||||
#define EXPORT
|
||||
#endif
|
||||
|
||||
#define _celt_check_int(x) (((void)((x) == (celt_int32)0)), (celt_int32)(x))
|
||||
#define _celt_check_mode_ptr_ptr(ptr) ((ptr) + ((ptr) - (const CELTMode**)(ptr)))
|
||||
#define _celt_check_int_ptr(ptr) ((ptr) + ((ptr) - (int*)(ptr)))
|
||||
|
||||
/* Error codes */
|
||||
/** No error */
|
||||
#define CELT_OK 0
|
||||
/** An (or more) invalid argument (e.g. out of range) */
|
||||
#define CELT_BAD_ARG -1
|
||||
/** The mode struct passed is invalid */
|
||||
#define CELT_BUFFER_TOO_SMALL -2
|
||||
/** An internal error was detected */
|
||||
#define CELT_INTERNAL_ERROR -3
|
||||
/** The data passed (e.g. compressed data to decoder) is corrupted */
|
||||
#define CELT_CORRUPTED_DATA -4
|
||||
/** Invalid/unsupported request number */
|
||||
#define CELT_UNIMPLEMENTED -5
|
||||
/** An encoder or decoder structure is invalid or already freed */
|
||||
#define CELT_INVALID_STATE -6
|
||||
/** Memory allocation has failed */
|
||||
#define CELT_ALLOC_FAIL -7
|
||||
|
||||
|
||||
/* Encoder/decoder Requests */
|
||||
|
||||
#define CELT_SET_COMPLEXITY_REQUEST 2
|
||||
/** Controls the complexity from 0-10 (int) */
|
||||
#define CELT_SET_COMPLEXITY(x) CELT_SET_COMPLEXITY_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_SET_PREDICTION_REQUEST 4
|
||||
/** 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, _celt_check_int(x)
|
||||
|
||||
#define CELT_SET_BITRATE_REQUEST 6
|
||||
/** Set the target VBR rate in bits per second(int); 0=CBR (default) */
|
||||
#define CELT_SET_BITRATE(x) CELT_SET_BITRATE_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_RESET_STATE_REQUEST 8
|
||||
/** Reset the encoder/decoder memories to zero*/
|
||||
#define CELT_RESET_STATE CELT_RESET_STATE_REQUEST
|
||||
|
||||
#define CELT_SET_VBR_CONSTRAINT_REQUEST 10
|
||||
#define CELT_SET_VBR_CONSTRAINT(x) CELT_SET_VBR_CONSTRAINT_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_SET_VBR_REQUEST 12
|
||||
#define CELT_SET_VBR(x) CELT_SET_VBR_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_SET_INPUT_CLIPPING_REQUEST 14
|
||||
#define CELT_SET_INPUT_CLIPPING(x) CELT_SET_INPUT_CLIPPING_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_GET_AND_CLEAR_ERROR_REQUEST 15
|
||||
#define CELT_GET_AND_CLEAR_ERROR(x) CELT_GET_AND_CLEAR_ERROR_REQUEST, _celt_check_int_ptr(x)
|
||||
|
||||
#define CELT_GET_LOOKAHEAD_REQUEST 17
|
||||
#define CELT_GET_LOOKAHEAD(x) CELT_GET_LOOKAHEAD_REQUEST, _celt_check_int_ptr(x)
|
||||
|
||||
#define CELT_SET_CHANNELS_REQUEST 18
|
||||
#define CELT_SET_CHANNELS(x) CELT_SET_CHANNELS_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_SET_LOSS_PERC_REQUEST 20
|
||||
#define CELT_SET_LOSS_PERC(x) CELT_SET_LOSS_PERC_REQUEST, _celt_check_int(x)
|
||||
|
||||
/* Internal */
|
||||
#define CELT_SET_START_BAND_REQUEST 10000
|
||||
#define CELT_SET_START_BAND(x) CELT_SET_START_BAND_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_SET_END_BAND_REQUEST 10001
|
||||
#define CELT_SET_END_BAND(x) CELT_SET_END_BAND_REQUEST, _celt_check_int(x)
|
||||
|
||||
|
||||
|
||||
/** Contains the state of an encoder. One encoder state is needed
|
||||
for each stream. It is initialised once at the beginning of the
|
||||
stream. Do *not* re-initialise the state for every frame.
|
||||
@brief Encoder state
|
||||
*/
|
||||
typedef struct CELTEncoder CELTEncoder;
|
||||
|
||||
/** State of the decoder. One decoder state is needed for each stream.
|
||||
It is initialised once at the beginning of the stream. Do *not*
|
||||
re-initialise the state for every frame */
|
||||
typedef struct CELTDecoder CELTDecoder;
|
||||
|
||||
/** The mode contains all the information necessary to create an
|
||||
encoder. Both the encoder and decoder need to be initialised
|
||||
with exactly the same mode, otherwise the quality will be very
|
||||
bad */
|
||||
typedef struct CELTMode CELTMode;
|
||||
|
||||
|
||||
/** \defgroup codec Encoding and decoding */
|
||||
/* @{ */
|
||||
|
||||
/* Mode calls */
|
||||
|
||||
/** 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 Fs Sampling rate (32000 to 96000 Hz)
|
||||
@param frame_size Number of samples (per channel) to encode in each
|
||||
packet (even values; 64 - 512)
|
||||
@param error Returned error code (if NULL, no error will be returned)
|
||||
@return A newly created mode
|
||||
*/
|
||||
EXPORT CELTMode *celt_mode_create(celt_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 mode Mode to be destroyed
|
||||
*/
|
||||
EXPORT void celt_mode_destroy(CELTMode *mode);
|
||||
|
||||
/* Encoder stuff */
|
||||
|
||||
EXPORT int celt_encoder_get_size(int channels);
|
||||
|
||||
EXPORT int celt_encoder_get_size_custom(const CELTMode *mode, int channels);
|
||||
|
||||
/** Creates a new encoder state. Each stream needs its own encoder
|
||||
state (can't be shared across simultaneous streams).
|
||||
@param channels Number of channels
|
||||
@param error Returns an error code
|
||||
@return Newly created encoder state.
|
||||
*/
|
||||
EXPORT CELTEncoder *celt_encoder_create(int sampling_rate, int channels, int *error);
|
||||
|
||||
/** Creates a new encoder state. Each stream needs its own encoder
|
||||
state (can't be shared across simultaneous streams).
|
||||
@param mode Contains all the information about the characteristics of
|
||||
* the stream (must be the same characteristics as used for the
|
||||
* decoder)
|
||||
@param channels Number of channels
|
||||
@param error Returns an error code
|
||||
@return Newly created encoder state.
|
||||
*/
|
||||
EXPORT CELTEncoder *celt_encoder_create_custom(const CELTMode *mode, int channels, int *error);
|
||||
|
||||
EXPORT CELTEncoder *celt_encoder_init(CELTEncoder *st, int sampling_rate, int channels, int *error);
|
||||
|
||||
EXPORT CELTEncoder *celt_encoder_init_custom(CELTEncoder *st, const CELTMode *mode, int channels, int *error);
|
||||
|
||||
/** Destroys a an encoder state.
|
||||
@param st Encoder state to be destroyed
|
||||
*/
|
||||
EXPORT void celt_encoder_destroy(CELTEncoder *st);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
@param st Encoder state
|
||||
@param pcm 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 dynmaic range. There must be exactly
|
||||
* frame_size samples per channel.
|
||||
@param compressed The compressed data is written here. This may not alias pcm or
|
||||
* optional_synthesis.
|
||||
@param nbCompressedBytes Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
@return Number of bytes written to "compressed". Will be the same as
|
||||
* "nbCompressedBytes" unless the stream is VBR and will never be larger.
|
||||
* 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.
|
||||
*/
|
||||
EXPORT int celt_encode_float(CELTEncoder *st, const float *pcm, int frame_size, unsigned char *compressed, int maxCompressedBytes);
|
||||
|
||||
/** Encodes a frame of audio.
|
||||
@param st Encoder state
|
||||
@param pcm PCM audio in signed 16-bit format (native endian). There must be
|
||||
* exactly frame_size samples per channel.
|
||||
@param compressed The compressed data is written here. This may not alias pcm or
|
||||
* optional_synthesis.
|
||||
@param nbCompressedBytes Maximum number of bytes to use for compressing the frame
|
||||
* (can change from one frame to another)
|
||||
@return Number of bytes written to "compressed". Will be the same as
|
||||
* "nbCompressedBytes" unless the stream is VBR and will never be larger.
|
||||
* 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.
|
||||
*/
|
||||
EXPORT int celt_encode(CELTEncoder *st, const celt_int16 *pcm, int frame_size, unsigned char *compressed, int maxCompressedBytes);
|
||||
|
||||
/** Query and set encoder parameters
|
||||
@param st Encoder state
|
||||
@param request Parameter to change or query
|
||||
@param value Pointer to a 32-bit int value
|
||||
@return Error code
|
||||
*/
|
||||
EXPORT int celt_encoder_ctl(CELTEncoder * st, int request, ...);
|
||||
|
||||
/* Decoder stuff */
|
||||
|
||||
EXPORT int celt_decoder_get_size(int channels);
|
||||
|
||||
EXPORT int celt_decoder_get_size_custom(const CELTMode *mode, int channels);
|
||||
|
||||
/** Creates a new decoder state. Each stream needs its own decoder state (can't
|
||||
be shared across simultaneous streams).
|
||||
@param mode Contains all the information about the characteristics of the
|
||||
stream (must be the same characteristics as used for the encoder)
|
||||
@param channels Number of channels
|
||||
@param error Returns an error code
|
||||
@return Newly created decoder state.
|
||||
*/
|
||||
EXPORT CELTDecoder *celt_decoder_create(int sampling_rate, int channels, int *error);
|
||||
|
||||
/** Creates a new decoder state. Each stream needs its own decoder state (can't
|
||||
be shared across simultaneous streams).
|
||||
@param mode Contains all the information about the characteristics of the
|
||||
stream (must be the same characteristics as used for the encoder)
|
||||
@param channels Number of channels
|
||||
@param error Returns an error code
|
||||
@return Newly created decoder state.
|
||||
*/
|
||||
EXPORT CELTDecoder *celt_decoder_create_custom(const CELTMode *mode, int channels, int *error);
|
||||
|
||||
EXPORT CELTDecoder *celt_decoder_init(CELTDecoder *st, int sampling_rate, int channels, int *error);
|
||||
|
||||
EXPORT CELTDecoder *celt_decoder_init_custom(CELTDecoder *st, const CELTMode *mode, int channels, int *error);
|
||||
|
||||
/** Destroys a a decoder state.
|
||||
@param st Decoder state to be destroyed
|
||||
*/
|
||||
EXPORT void celt_decoder_destroy(CELTDecoder *st);
|
||||
|
||||
/** Decodes a frame of audio.
|
||||
@param st Decoder state
|
||||
@param data Compressed data produced by an encoder
|
||||
@param len Number of bytes to read from "data". This MUST be exactly the number
|
||||
of bytes returned by the encoder. Using a larger value WILL NOT WORK.
|
||||
@param pcm One frame (frame_size samples per channel) of decoded PCM will be
|
||||
returned here in float format.
|
||||
@return Error code.
|
||||
*/
|
||||
EXPORT int celt_decode_float(CELTDecoder *st, const unsigned char *data, int len, float *pcm, int frame_size);
|
||||
|
||||
/** Decodes a frame of audio.
|
||||
@param st Decoder state
|
||||
@param data Compressed data produced by an encoder
|
||||
@param len Number of bytes to read from "data". This MUST be exactly the number
|
||||
of bytes returned by the encoder. Using a larger value WILL NOT WORK.
|
||||
@param pcm One frame (frame_size samples per channel) of decoded PCM will be
|
||||
returned here in 16-bit PCM format (native endian).
|
||||
@return Error code.
|
||||
*/
|
||||
EXPORT int celt_decode(CELTDecoder *st, const unsigned char *data, int len, celt_int16 *pcm, int frame_size);
|
||||
|
||||
/** Query and set decoder parameters
|
||||
@param st Decoder state
|
||||
@param request Parameter to change or query
|
||||
@param value Pointer to a 32-bit int value
|
||||
@return Error code
|
||||
*/
|
||||
EXPORT int celt_decoder_ctl(CELTDecoder * st, int request, ...);
|
||||
|
||||
|
||||
/** Returns the English string that corresponds to an error code
|
||||
* @param error Error code (negative for an error, 0 for success
|
||||
* @return Constant string (must NOT be freed)
|
||||
*/
|
||||
EXPORT const char *celt_strerror(int error);
|
||||
|
||||
/* @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*CELT_H */
|
||||
@@ -1,66 +0,0 @@
|
||||
/* Copyright (c) 2007 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 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 CELT_HEADER_H
|
||||
#define CELT_HEADER_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "celt.h"
|
||||
#include "celt_types.h"
|
||||
|
||||
/** Header data to be used for Ogg files (or possibly other encapsulation)
|
||||
@brief Header data
|
||||
*/
|
||||
typedef struct {
|
||||
char codec_id[8]; /**< MUST be "CELT " (four spaces) */
|
||||
char codec_version[20]; /**< Version used (as string) */
|
||||
celt_int32 version_id; /**< Version id (negative for until stream is frozen) */
|
||||
celt_int32 header_size; /**< Size of this header */
|
||||
celt_int32 sample_rate; /**< Sampling rate of the original audio */
|
||||
celt_int32 nb_channels; /**< Number of channels */
|
||||
celt_int32 frame_size; /**< Samples per frame (per channel) */
|
||||
celt_int32 overlap; /**< Overlapping samples (per channel) */
|
||||
celt_int32 bytes_per_packet; /**< Number of bytes per compressed packet (0 if unknown) */
|
||||
celt_int32 extra_headers; /**< Number of additional headers that follow this header */
|
||||
} CELTHeader;
|
||||
|
||||
/** Creates a basic header struct */
|
||||
EXPORT int celt_header_init(CELTHeader *header, const CELTMode *m, int frame_size, int channels);
|
||||
|
||||
EXPORT int celt_header_to_packet(const CELTHeader *header, unsigned char *packet, celt_uint32 size);
|
||||
|
||||
EXPORT int celt_header_from_packet(const unsigned char *packet, celt_uint32 size, CELTHeader *header);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CELT_HEADER_H */
|
||||
@@ -1,151 +0,0 @@
|
||||
/* (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 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.
|
||||
*/
|
||||
/* celt_types.h taken from libogg */
|
||||
|
||||
/**
|
||||
@file celt_types.h
|
||||
@brief CELT types
|
||||
*/
|
||||
#ifndef _CELT_TYPES_H
|
||||
#define _CELT_TYPES_H
|
||||
|
||||
/* Use the real stdint.h if it's there (taken from Paul Hsieh's pstdint.h) */
|
||||
#if (defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) || defined (HAVE_STDINT_H))
|
||||
#include <stdint.h>
|
||||
|
||||
typedef int16_t celt_int16;
|
||||
typedef uint16_t celt_uint16;
|
||||
typedef int32_t celt_int32;
|
||||
typedef uint32_t celt_uint32;
|
||||
#elif defined(_WIN32)
|
||||
|
||||
# if defined(__CYGWIN__)
|
||||
# include <_G_config.h>
|
||||
typedef _G_int32_t celt_int32;
|
||||
typedef _G_uint32_t celt_uint32;
|
||||
typedef _G_int16 celt_int16;
|
||||
typedef _G_uint16 celt_uint16;
|
||||
# elif defined(__MINGW32__)
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
# elif defined(__MWERKS__)
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
# else
|
||||
/* MSVC/Borland */
|
||||
typedef __int32 celt_int32;
|
||||
typedef unsigned __int32 celt_uint32;
|
||||
typedef __int16 celt_int16;
|
||||
typedef unsigned __int16 celt_uint16;
|
||||
# endif
|
||||
|
||||
#elif defined(__MACOS__)
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef SInt16 celt_int16;
|
||||
typedef UInt16 celt_uint16;
|
||||
typedef SInt32 celt_int32;
|
||||
typedef UInt32 celt_uint32;
|
||||
|
||||
#elif (defined(__APPLE__) && defined(__MACH__)) /* MacOS X Framework build */
|
||||
|
||||
# include <sys/types.h>
|
||||
typedef int16_t celt_int16;
|
||||
typedef u_int16_t celt_uint16;
|
||||
typedef int32_t celt_int32;
|
||||
typedef u_int32_t celt_uint32;
|
||||
|
||||
#elif defined(__BEOS__)
|
||||
|
||||
/* Be */
|
||||
# include <inttypes.h>
|
||||
typedef int16 celt_int16;
|
||||
typedef u_int16 celt_uint16;
|
||||
typedef int32_t celt_int32;
|
||||
typedef u_int32_t celt_uint32;
|
||||
|
||||
#elif defined (__EMX__)
|
||||
|
||||
/* OS/2 GCC */
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
|
||||
#elif defined (DJGPP)
|
||||
|
||||
/* DJGPP */
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
|
||||
#elif defined(R5900)
|
||||
|
||||
/* PS2 EE */
|
||||
typedef int celt_int32;
|
||||
typedef unsigned celt_uint32;
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
|
||||
#elif defined(__SYMBIAN32__)
|
||||
|
||||
/* Symbian GCC */
|
||||
typedef signed short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef signed int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C54X) || defined (CONFIG_TI_C55X)
|
||||
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef long celt_int32;
|
||||
typedef unsigned long celt_uint32;
|
||||
|
||||
#elif defined(CONFIG_TI_C6X)
|
||||
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
|
||||
#else
|
||||
|
||||
/* Give up, take a reasonable guess */
|
||||
typedef short celt_int16;
|
||||
typedef unsigned short celt_uint16;
|
||||
typedef int celt_int32;
|
||||
typedef unsigned int celt_uint32;
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* _CELT_TYPES_H */
|
||||
@@ -1,736 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "os_support.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "cwrs.h"
|
||||
#include "mathops.h"
|
||||
#include "arch.h"
|
||||
|
||||
/*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(celt_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).*/
|
||||
if(l>16)val=(val>>l-16)+((val&(1<<l-16)-1)+(1<<l-16)-1>>l-16);
|
||||
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;
|
||||
}
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
|
||||
#define MASK32 (0xFFFFFFFF)
|
||||
|
||||
/*INV_TABLE[i] holds the multiplicative inverse of (2*i+1) mod 2**32.*/
|
||||
static const celt_uint32 INV_TABLE[64]={
|
||||
0x00000001,0xAAAAAAAB,0xCCCCCCCD,0xB6DB6DB7,
|
||||
0x38E38E39,0xBA2E8BA3,0xC4EC4EC5,0xEEEEEEEF,
|
||||
0xF0F0F0F1,0x286BCA1B,0x3CF3CF3D,0xE9BD37A7,
|
||||
0xC28F5C29,0x684BDA13,0x4F72C235,0xBDEF7BDF,
|
||||
0x3E0F83E1,0x8AF8AF8B,0x914C1BAD,0x96F96F97,
|
||||
0xC18F9C19,0x2FA0BE83,0xA4FA4FA5,0x677D46CF,
|
||||
0x1A1F58D1,0xFAFAFAFB,0x8C13521D,0x586FB587,
|
||||
0xB823EE09,0xA08AD8F3,0xC10C9715,0xBEFBEFBF,
|
||||
0xC0FC0FC1,0x07A44C6B,0xA33F128D,0xE327A977,
|
||||
0xC7E3F1F9,0x962FC963,0x3F2B3885,0x613716AF,
|
||||
0x781948B1,0x2B2E43DB,0xFCFCFCFD,0x6FD0EB67,
|
||||
0xFA3F47E9,0xD2FD2FD3,0x3F4FD3F5,0xD4E25B9F,
|
||||
0x5F02A3A1,0xBF5A814B,0x7C32B16D,0xD3431B57,
|
||||
0xD8FD8FD9,0x8D28AC43,0xDA6C0965,0xDB195E8F,
|
||||
0x0FDBC091,0x61F2A4BB,0xDCFDCFDD,0x46FDD947,
|
||||
0x56BE69C9,0xEB2FDEB3,0x26E978D5,0xEFDFBF7F,
|
||||
/*
|
||||
0x0FE03F81,0xC9484E2B,0xE133F84D,0xE1A8C537,
|
||||
0x077975B9,0x70586723,0xCD29C245,0xFAA11E6F,
|
||||
0x0FE3C071,0x08B51D9B,0x8CE2CABD,0xBF937F27,
|
||||
0xA8FE53A9,0x592FE593,0x2C0685B5,0x2EB11B5F,
|
||||
0xFCD1E361,0x451AB30B,0x72CFE72D,0xDB35A717,
|
||||
0xFB74A399,0xE80BFA03,0x0D516325,0x1BCB564F,
|
||||
0xE02E4851,0xD962AE7B,0x10F8ED9D,0x95AEDD07,
|
||||
0xE9DC0589,0xA18A4473,0xEA53FA95,0xEE936F3F,
|
||||
0x90948F41,0xEAFEAFEB,0x3D137E0D,0xEF46C0F7,
|
||||
0x028C1979,0x791064E3,0xC04FEC05,0xE115062F,
|
||||
0x32385831,0x6E68575B,0xA10D387D,0x6FECF2E7,
|
||||
0x3FB47F69,0xED4BFB53,0x74FED775,0xDB43BB1F,
|
||||
0x87654321,0x9BA144CB,0x478BBCED,0xBFB912D7,
|
||||
0x1FDCD759,0x14B2A7C3,0xCB125CE5,0x437B2E0F,
|
||||
0x10FEF011,0xD2B3183B,0x386CAB5D,0xEF6AC0C7,
|
||||
0x0E64C149,0x9A020A33,0xE6B41C55,0xFEFEFEFF*/
|
||||
};
|
||||
|
||||
/*Computes (_a*_b-_c)/(2*_d+1) when the quotient is known to be exact.
|
||||
_a, _b, _c, and _d may be arbitrary so long as the arbitrary precision result
|
||||
fits in 32 bits, but currently the table for multiplicative inverses is only
|
||||
valid for _d<128.*/
|
||||
static inline celt_uint32 imusdiv32odd(celt_uint32 _a,celt_uint32 _b,
|
||||
celt_uint32 _c,int _d){
|
||||
return (_a*_b-_c)*INV_TABLE[_d]&MASK32;
|
||||
}
|
||||
|
||||
/*Computes (_a*_b-_c)/_d when the quotient is known to be exact.
|
||||
_d does not actually have to be even, but imusdiv32odd will be faster when
|
||||
it's odd, so you should use that instead.
|
||||
_a and _d are assumed to be small (e.g., _a*_d fits in 32 bits; currently the
|
||||
table for multiplicative inverses is only valid for _d<=256).
|
||||
_b and _c may be arbitrary so long as the arbitrary precision reuslt fits in
|
||||
32 bits.*/
|
||||
static inline celt_uint32 imusdiv32even(celt_uint32 _a,celt_uint32 _b,
|
||||
celt_uint32 _c,int _d){
|
||||
celt_uint32 inv;
|
||||
int mask;
|
||||
int shift;
|
||||
int one;
|
||||
celt_assert(_d>0);
|
||||
shift=EC_ILOG(_d^_d-1);
|
||||
celt_assert(_d<=256);
|
||||
inv=INV_TABLE[_d-1>>shift];
|
||||
shift--;
|
||||
one=1<<shift;
|
||||
mask=one-1;
|
||||
return (_a*(_b>>shift)-(_c>>shift)+
|
||||
(_a*(_b&mask)+one-(_c&mask)>>shift)-1)*inv&MASK32;
|
||||
}
|
||||
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*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
|
||||
http://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
|
||||
}*/
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
/*Compute U(1,_k).*/
|
||||
static inline unsigned ucwrs1(int _k){
|
||||
return _k?1:0;
|
||||
}
|
||||
|
||||
/*Compute V(1,_k).*/
|
||||
static inline unsigned ncwrs1(int _k){
|
||||
return _k?2:1;
|
||||
}
|
||||
|
||||
/*Compute U(2,_k).
|
||||
Note that this may be called with _k=32768 (maxK[2]+1).*/
|
||||
static inline unsigned ucwrs2(unsigned _k){
|
||||
return _k?_k+(_k-1):0;
|
||||
}
|
||||
|
||||
/*Compute V(2,_k).*/
|
||||
static inline celt_uint32 ncwrs2(int _k){
|
||||
return _k?4*(celt_uint32)_k:1;
|
||||
}
|
||||
|
||||
/*Compute U(3,_k).
|
||||
Note that this may be called with _k=32768 (maxK[3]+1).*/
|
||||
static inline celt_uint32 ucwrs3(unsigned _k){
|
||||
return _k?(2*(celt_uint32)_k-2)*_k+1:0;
|
||||
}
|
||||
|
||||
/*Compute V(3,_k).*/
|
||||
static inline celt_uint32 ncwrs3(int _k){
|
||||
return _k?2*(2*(unsigned)_k*(celt_uint32)_k+1):1;
|
||||
}
|
||||
|
||||
/*Compute U(4,_k).*/
|
||||
static inline celt_uint32 ucwrs4(int _k){
|
||||
return _k?imusdiv32odd(2*_k,(2*_k-3)*(celt_uint32)_k+4,3,1):0;
|
||||
}
|
||||
|
||||
/*Compute V(4,_k).*/
|
||||
static inline celt_uint32 ncwrs4(int _k){
|
||||
return _k?((_k*(celt_uint32)_k+2)*_k)/3<<3:1;
|
||||
}
|
||||
|
||||
/*Compute U(5,_k).*/
|
||||
static inline celt_uint32 ucwrs5(int _k){
|
||||
return _k?(((((_k-2)*(unsigned)_k+5)*(celt_uint32)_k-4)*_k)/3<<1)+1:0;
|
||||
}
|
||||
|
||||
/*Compute V(5,_k).*/
|
||||
static inline celt_uint32 ncwrs5(int _k){
|
||||
return _k?(((_k*(unsigned)_k+5)*(celt_uint32)_k*_k)/3<<2)+2:1;
|
||||
}
|
||||
|
||||
#endif /* 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 inline void unext(celt_uint32 *_ui,unsigned _len,celt_uint32 _ui0){
|
||||
celt_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 inline void uprev(celt_uint32 *_ui,unsigned _n,celt_uint32 _ui0){
|
||||
celt_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 celt_uint32 ncwrs_urow(unsigned _n,unsigned _k,celt_uint32 *_u){
|
||||
celt_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;
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
if(_n<=6 || _k>255)
|
||||
#endif
|
||||
{
|
||||
/*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);
|
||||
}
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
else{
|
||||
celt_uint32 um1;
|
||||
celt_uint32 n2m1;
|
||||
_u[2]=n2m1=um1=(_n<<1)-1;
|
||||
for(k=3;k<len;k++){
|
||||
/*U(N,K) = ((2*N-1)*U(N,K-1)-U(N,K-2))/(K-1) + U(N,K-2)*/
|
||||
_u[k]=um2=imusdiv32even(n2m1,um1,um2,k-1)+um2;
|
||||
if(++k>=len)break;
|
||||
_u[k]=um1=imusdiv32odd(n2m1,um2,um1,k-1>>1)+um1;
|
||||
}
|
||||
}
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
return _u[_k]+_u[_k+1];
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 32767) chosen from a
|
||||
set of size 1 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static inline void cwrsi1(int _k,celt_uint32 _i,int *_y){
|
||||
int s;
|
||||
s=-(int)_i;
|
||||
_y[0]=_k+s^s;
|
||||
}
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 32767) chosen from a
|
||||
set of size 2 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static inline void cwrsi2(int _k,celt_uint32 _i,int *_y){
|
||||
celt_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=ucwrs2(_k+1U);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
_k=_i+1>>1;
|
||||
p=ucwrs2(_k);
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=yj+s^s;
|
||||
cwrsi1(_k,_i,_y+1);
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 32767) chosen from a
|
||||
set of size 3 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static void cwrsi3(int _k,celt_uint32 _i,int *_y){
|
||||
celt_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=ucwrs3(_k+1U);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
/*Finds the maximum _k such that ucwrs3(_k)<=_i (tested for all
|
||||
_i<2147418113=U(3,32768)).*/
|
||||
_k=_i>0?isqrt32(2*_i-1)+1>>1:0;
|
||||
p=ucwrs3(_k);
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=yj+s^s;
|
||||
cwrsi2(_k,_i,_y+1);
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 1172) chosen from a set
|
||||
of size 4 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static void cwrsi4(int _k,celt_uint32 _i,int *_y){
|
||||
celt_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
int kl;
|
||||
int kr;
|
||||
p=ucwrs4(_k+1);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
/*We could solve a cubic for k here, but the form of the direct solution does
|
||||
not lend itself well to exact integer arithmetic.
|
||||
Instead we do a binary search on U(4,K).*/
|
||||
kl=0;
|
||||
kr=_k;
|
||||
for(;;){
|
||||
_k=kl+kr>>1;
|
||||
p=ucwrs4(_k);
|
||||
if(p<_i){
|
||||
if(_k>=kr)break;
|
||||
kl=_k+1;
|
||||
}
|
||||
else if(p>_i)kr=_k-1;
|
||||
else break;
|
||||
}
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=yj+s^s;
|
||||
cwrsi3(_k,_i,_y+1);
|
||||
}
|
||||
|
||||
/*Returns the _i'th combination of _k elements (at most 238) chosen from a set
|
||||
of size 5 with associated sign bits.
|
||||
_y: Returns the vector of pulses.*/
|
||||
static void cwrsi5(int _k,celt_uint32 _i,int *_y){
|
||||
celt_uint32 p;
|
||||
int s;
|
||||
int yj;
|
||||
p=ucwrs5(_k+1);
|
||||
s=-(_i>=p);
|
||||
_i-=p&s;
|
||||
yj=_k;
|
||||
/* A binary search on U(5,K) avoids the need for 64-bit arithmetic */
|
||||
{
|
||||
int kl=0;
|
||||
int kr=_k;
|
||||
for(;;){
|
||||
_k=kl+kr>>1;
|
||||
p=ucwrs5(_k);
|
||||
if(p<_i){
|
||||
if(_k>=kr)break;
|
||||
kl=_k+1;
|
||||
}
|
||||
else if(p>_i)kr=_k-1;
|
||||
else break;
|
||||
}
|
||||
}
|
||||
_i-=p;
|
||||
yj-=_k;
|
||||
_y[0]=yj+s^s;
|
||||
cwrsi4(_k,_i,_y+1);
|
||||
}
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*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 void cwrsi(int _n,int _k,celt_uint32 _i,int *_y,celt_uint32 *_u){
|
||||
int j;
|
||||
celt_assert(_n>0);
|
||||
j=0;
|
||||
do{
|
||||
celt_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;
|
||||
_y[j]=yj+s^s;
|
||||
uprev(_u,_k+2,0);
|
||||
}
|
||||
while(++j<_n);
|
||||
}
|
||||
|
||||
|
||||
/*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 inline celt_uint32 icwrs1(const int *_y,int *_k){
|
||||
*_k=abs(_y[0]);
|
||||
return _y[0]<0;
|
||||
}
|
||||
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 2 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline celt_uint32 icwrs2(const int *_y,int *_k){
|
||||
celt_uint32 i;
|
||||
int k;
|
||||
i=icwrs1(_y+1,&k);
|
||||
i+=ucwrs2(k);
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs2(k+1U);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 3 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline celt_uint32 icwrs3(const int *_y,int *_k){
|
||||
celt_uint32 i;
|
||||
int k;
|
||||
i=icwrs2(_y+1,&k);
|
||||
i+=ucwrs3(k);
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs3(k+1U);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 4 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline celt_uint32 icwrs4(const int *_y,int *_k){
|
||||
celt_uint32 i;
|
||||
int k;
|
||||
i=icwrs3(_y+1,&k);
|
||||
i+=ucwrs4(k);
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs4(k+1);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
|
||||
/*Returns the index of the given combination of K elements chosen from a set
|
||||
of size 5 with associated sign bits.
|
||||
_y: The vector of pulses, whose sum of absolute values is K.
|
||||
_k: Returns K.*/
|
||||
static inline celt_uint32 icwrs5(const int *_y,int *_k){
|
||||
celt_uint32 i;
|
||||
int k;
|
||||
i=icwrs4(_y+1,&k);
|
||||
i+=ucwrs5(k);
|
||||
k+=abs(_y[0]);
|
||||
if(_y[0]<0)i+=ucwrs5(k+1);
|
||||
*_k=k;
|
||||
return i;
|
||||
}
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*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).*/
|
||||
celt_uint32 icwrs(int _n,int _k,celt_uint32 *_nc,const int *_y,
|
||||
celt_uint32 *_u){
|
||||
celt_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(celt_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(celt_uint32,u);
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_maxk+2U,celt_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){
|
||||
celt_uint32 i;
|
||||
if (_k==0)
|
||||
return;
|
||||
switch(_n){
|
||||
case 1:{
|
||||
i=icwrs1(_y,&_k);
|
||||
celt_assert(ncwrs1(_k)==2);
|
||||
ec_enc_bits(_enc,i,1);
|
||||
}break;
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
case 2:{
|
||||
i=icwrs2(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs2(_k));
|
||||
}break;
|
||||
case 3:{
|
||||
i=icwrs3(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs3(_k));
|
||||
}break;
|
||||
case 4:{
|
||||
i=icwrs4(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs4(_k));
|
||||
}break;
|
||||
case 5:{
|
||||
i=icwrs5(_y,&_k);
|
||||
ec_enc_uint(_enc,i,ncwrs5(_k));
|
||||
}break;
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
VARDECL(celt_uint32,u);
|
||||
celt_uint32 nc;
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_k+2U,celt_uint32);
|
||||
i=icwrs(_n,_k,&nc,_y,u);
|
||||
ec_enc_uint(_enc,i,nc);
|
||||
RESTORE_STACK;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
void decode_pulses(int *_y,int _n,int _k,ec_dec *_dec)
|
||||
{
|
||||
if (_k==0) {
|
||||
int i;
|
||||
for (i=0;i<_n;i++)
|
||||
_y[i] = 0;
|
||||
return;
|
||||
}
|
||||
switch(_n){
|
||||
case 1:{
|
||||
celt_assert(ncwrs1(_k)==2);
|
||||
cwrsi1(_k,ec_dec_bits(_dec,1),_y);
|
||||
}break;
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
case 2:cwrsi2(_k,ec_dec_uint(_dec,ncwrs2(_k)),_y);break;
|
||||
case 3:cwrsi3(_k,ec_dec_uint(_dec,ncwrs3(_k)),_y);break;
|
||||
case 4:cwrsi4(_k,ec_dec_uint(_dec,ncwrs4(_k)),_y);break;
|
||||
case 5:cwrsi5(_k,ec_dec_uint(_dec,ncwrs5(_k)),_y);break;
|
||||
#endif
|
||||
default:
|
||||
{
|
||||
VARDECL(celt_uint32,u);
|
||||
SAVE_STACK;
|
||||
ALLOC(u,_k+2U,celt_uint32);
|
||||
cwrsi(_n,_k,ec_dec_uint(_dec,ncwrs_urow(_n,_k,u)),_y,u);
|
||||
RESTORE_STACK;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +0,0 @@
|
||||
/* 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 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 CWRS_H
|
||||
#define CWRS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
int log2_frac(celt_uint32 val, int frac);
|
||||
|
||||
void get_required_bits(celt_int16 *bits, int N, int K, int frac);
|
||||
|
||||
void encode_pulses(const int *_y, int N, int K, ec_enc *enc);
|
||||
|
||||
void decode_pulses(int *_y, int N, int K, ec_dec *dec);
|
||||
|
||||
#endif /* CWRS_H */
|
||||
@@ -1,325 +0,0 @@
|
||||
/* Copyright (c) 2008 CSIRO
|
||||
Copyright (c) 2008-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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "modes.h"
|
||||
#include "celt.h"
|
||||
#include "rate.h"
|
||||
|
||||
#define INT16 "%d"
|
||||
#define INT32 "%d"
|
||||
#define FLOAT "%f"
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#define WORD16 INT16
|
||||
#define WORD32 INT32
|
||||
#else
|
||||
#define WORD16 FLOAT
|
||||
#define WORD32 FLOAT
|
||||
#endif
|
||||
|
||||
|
||||
void dump_modes(FILE *file, CELTMode **modes, int nb_modes)
|
||||
{
|
||||
int i, j, k;
|
||||
fprintf(file, "/* The contents of this file is automatically generated and contains static\n");
|
||||
fprintf(file, " definitions for some pre-defined modes */\n");
|
||||
fprintf(file, "#include \"modes.h\"\n");
|
||||
fprintf(file, "#include \"rate.h\"\n");
|
||||
|
||||
fprintf(file, "\n");
|
||||
|
||||
for (i=0;i<nb_modes;i++)
|
||||
{
|
||||
CELTMode *mode = modes[i];
|
||||
int mdctSize;
|
||||
int standard, framerate;
|
||||
|
||||
mdctSize = mode->shortMdctSize*mode->nbShortMdcts;
|
||||
standard = (mode->Fs == 400*(celt_int32)mode->shortMdctSize);
|
||||
framerate = mode->Fs/mode->shortMdctSize;
|
||||
|
||||
if (!standard)
|
||||
{
|
||||
fprintf(file, "#ifndef DEF_EBANDS%d_%d\n", mode->Fs, mdctSize);
|
||||
fprintf(file, "#define DEF_EBANDS%d_%d\n", mode->Fs, mdctSize);
|
||||
fprintf (file, "static const celt_int16 eBands%d_%d[%d] = {\n", mode->Fs, mdctSize, mode->nbEBands+2);
|
||||
for (j=0;j<mode->nbEBands+2;j++)
|
||||
fprintf (file, "%d, ", mode->eBands[j]);
|
||||
fprintf (file, "};\n");
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
fprintf(file, "#ifndef DEF_WINDOW%d\n", mode->overlap);
|
||||
fprintf(file, "#define DEF_WINDOW%d\n", mode->overlap);
|
||||
fprintf (file, "static const celt_word16 window%d[%d] = {\n", mode->overlap, mode->overlap);
|
||||
for (j=0;j<mode->overlap;j++)
|
||||
fprintf (file, WORD16 ", ", mode->window[j]);
|
||||
fprintf (file, "};\n");
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
if (!standard)
|
||||
{
|
||||
fprintf(file, "#ifndef DEF_ALLOC_VECTORS%d_%d\n", mode->Fs, mdctSize);
|
||||
fprintf(file, "#define DEF_ALLOC_VECTORS%d_%d\n", mode->Fs, mdctSize);
|
||||
fprintf (file, "static const unsigned char allocVectors%d_%d[%d] = {\n", mode->Fs, mdctSize, mode->nbEBands*mode->nbAllocVectors);
|
||||
for (j=0;j<mode->nbAllocVectors;j++)
|
||||
{
|
||||
for (k=0;k<mode->nbEBands;k++)
|
||||
fprintf (file, "%2d, ", mode->allocVectors[j*mode->nbEBands+k]);
|
||||
fprintf (file, "\n");
|
||||
}
|
||||
fprintf (file, "};\n");
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
fprintf(file, "#ifndef DEF_LOGN%d\n", framerate);
|
||||
fprintf(file, "#define DEF_LOGN%d\n", framerate);
|
||||
fprintf (file, "static const celt_int16 logN%d[%d] = {\n", framerate, mode->nbEBands);
|
||||
for (j=0;j<mode->nbEBands;j++)
|
||||
fprintf (file, "%d, ", mode->logN[j]);
|
||||
fprintf (file, "};\n");
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
/* Pulse cache */
|
||||
fprintf(file, "#ifndef DEF_PULSE_CACHE%d\n", mode->Fs/mdctSize);
|
||||
fprintf(file, "#define DEF_PULSE_CACHE%d\n", mode->Fs/mdctSize);
|
||||
fprintf (file, "static const celt_int16 cache_index%d[%d] = {\n", mode->Fs/mdctSize, (mode->maxLM+2)*mode->nbEBands);
|
||||
for (j=0;j<mode->nbEBands*(mode->maxLM+2);j++)
|
||||
fprintf (file, "%d, ", mode->cache.index[j]);
|
||||
fprintf (file, "};\n");
|
||||
fprintf (file, "static const unsigned char cache_bits%d[%d] = {\n", mode->Fs/mdctSize, mode->cache.size);
|
||||
for (j=0;j<mode->cache.size;j++)
|
||||
fprintf (file, "%d, ", mode->cache.bits[j]);
|
||||
fprintf (file, "};\n");
|
||||
fprintf (file, "static const unsigned char cache_caps%d[%d] = {\n", mode->Fs/mdctSize, (mode->maxLM+1)*2*mode->nbEBands);
|
||||
for (j=0;j<(mode->maxLM+1)*2*mode->nbEBands;j++)
|
||||
fprintf (file, "%d, ", mode->cache.caps[j]);
|
||||
fprintf (file, "};\n");
|
||||
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
/* FFT twiddles */
|
||||
fprintf(file, "#ifndef FFT_TWIDDLES%d_%d\n", mode->Fs, mdctSize);
|
||||
fprintf(file, "#define FFT_TWIDDLES%d_%d\n", mode->Fs, mdctSize);
|
||||
fprintf (file, "static const kiss_twiddle_cpx fft_twiddles%d_%d[%d] = {\n",
|
||||
mode->Fs, mdctSize, mode->mdct.kfft[0]->nfft);
|
||||
for (j=0;j<mode->mdct.kfft[0]->nfft;j++)
|
||||
fprintf (file, "{" WORD16 ", " WORD16 "}, ", mode->mdct.kfft[0]->twiddles[j].r, mode->mdct.kfft[0]->twiddles[j].i);
|
||||
fprintf (file, "};\n");
|
||||
|
||||
/* FFT Bitrev tables */
|
||||
for (k=0;k<=mode->mdct.maxshift;k++)
|
||||
{
|
||||
fprintf(file, "#ifndef FFT_BITREV%d\n", mode->mdct.kfft[k]->nfft);
|
||||
fprintf(file, "#define FFT_BITREV%d\n", mode->mdct.kfft[k]->nfft);
|
||||
fprintf (file, "static const celt_int16 fft_bitrev%d[%d] = {\n",
|
||||
mode->mdct.kfft[k]->nfft, mode->mdct.kfft[k]->nfft);
|
||||
for (j=0;j<mode->mdct.kfft[k]->nfft;j++)
|
||||
fprintf (file, "%d, ", mode->mdct.kfft[k]->bitrev[j]);
|
||||
fprintf (file, "};\n");
|
||||
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
/* FFT States */
|
||||
for (k=0;k<=mode->mdct.maxshift;k++)
|
||||
{
|
||||
fprintf(file, "#ifndef FFT_STATE%d_%d_%d\n", mode->Fs, mdctSize, k);
|
||||
fprintf(file, "#define FFT_STATE%d_%d_%d\n", mode->Fs, mdctSize, k);
|
||||
fprintf (file, "static const kiss_fft_state fft_state%d_%d_%d = {\n",
|
||||
mode->Fs, mdctSize, k);
|
||||
fprintf (file, "%d,\t/* nfft */\n", mode->mdct.kfft[k]->nfft);
|
||||
#ifndef FIXED_POINT
|
||||
fprintf (file, "%f,\t/* scale */\n", mode->mdct.kfft[k]->scale);
|
||||
#endif
|
||||
fprintf (file, "%d,\t/* shift */\n", mode->mdct.kfft[k]->shift);
|
||||
fprintf (file, "{");
|
||||
for (j=0;j<2*MAXFACTORS;j++)
|
||||
fprintf (file, "%d, ", mode->mdct.kfft[k]->factors[j]);
|
||||
fprintf (file, "},\t/* factors */\n");
|
||||
fprintf (file, "fft_bitrev%d,\t/* bitrev */\n", mode->mdct.kfft[k]->nfft);
|
||||
fprintf (file, "fft_twiddles%d_%d,\t/* bitrev */\n", mode->Fs, mdctSize);
|
||||
fprintf (file, "};\n");
|
||||
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
}
|
||||
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
/* MDCT twiddles */
|
||||
fprintf(file, "#ifndef MDCT_TWIDDLES%d\n", mdctSize);
|
||||
fprintf(file, "#define MDCT_TWIDDLES%d\n", mdctSize);
|
||||
fprintf (file, "static const celt_word16 mdct_twiddles%d[%d] = {\n",
|
||||
mdctSize, mode->mdct.n/4+1);
|
||||
for (j=0;j<=mode->mdct.n/4;j++)
|
||||
fprintf (file, WORD16 ", ", mode->mdct.trig[j]);
|
||||
fprintf (file, "};\n");
|
||||
|
||||
fprintf(file, "#endif\n");
|
||||
fprintf(file, "\n");
|
||||
|
||||
|
||||
/* Print the actual mode data */
|
||||
fprintf(file, "static const CELTMode mode%d_%d_%d = {\n", mode->Fs, mdctSize, mode->overlap);
|
||||
fprintf(file, INT32 ",\t/* Fs */\n", mode->Fs);
|
||||
fprintf(file, "%d,\t/* overlap */\n", mode->overlap);
|
||||
fprintf(file, "%d,\t/* nbEBands */\n", mode->nbEBands);
|
||||
fprintf(file, "%d,\t/* effEBands */\n", mode->effEBands);
|
||||
fprintf(file, "{");
|
||||
for (j=0;j<4;j++)
|
||||
fprintf(file, WORD16 ", ", mode->preemph[j]);
|
||||
fprintf(file, "},\t/* preemph */\n");
|
||||
if (standard)
|
||||
fprintf(file, "eband5ms,\t/* eBands */\n");
|
||||
else
|
||||
fprintf(file, "eBands%d_%d,\t/* eBands */\n", mode->Fs, mdctSize);
|
||||
fprintf(file, "%d,\t/* nbAllocVectors */\n", mode->nbAllocVectors);
|
||||
if (standard)
|
||||
fprintf(file, "band_allocation,\t/* allocVectors */\n");
|
||||
else
|
||||
fprintf(file, "allocVectors%d_%d,\t/* allocVectors */\n", mode->Fs, mdctSize);
|
||||
|
||||
fprintf(file, "{%d, %d, {", mode->mdct.n, mode->mdct.maxshift);
|
||||
for (k=0;k<=mode->mdct.maxshift;k++)
|
||||
fprintf(file, "&fft_state%d_%d_%d, ", mode->Fs, mdctSize, k);
|
||||
fprintf (file, "}, mdct_twiddles%d},\t/* mdct */\n", mdctSize);
|
||||
|
||||
fprintf(file, "window%d,\t/* window */\n", mode->overlap);
|
||||
fprintf(file, "%d,\t/* maxLM */\n", mode->maxLM);
|
||||
fprintf(file, "%d,\t/* nbShortMdcts */\n", mode->nbShortMdcts);
|
||||
fprintf(file, "%d,\t/* shortMdctSize */\n", mode->shortMdctSize);
|
||||
fprintf(file, "logN%d,\t/* logN */\n", framerate);
|
||||
fprintf(file, "{%d, cache_index%d, cache_bits%d, cache_caps%d},\t/* cache */\n",
|
||||
mode->cache.size, mode->Fs/mdctSize, mode->Fs/mdctSize, mode->Fs/mdctSize);
|
||||
fprintf(file, "};\n");
|
||||
}
|
||||
fprintf(file, "\n");
|
||||
fprintf(file, "/* List of all the available modes */\n");
|
||||
fprintf(file, "#define TOTAL_MODES %d\n", nb_modes);
|
||||
fprintf(file, "static const CELTMode * const static_mode_list[TOTAL_MODES] = {\n");
|
||||
for (i=0;i<nb_modes;i++)
|
||||
{
|
||||
CELTMode *mode = modes[i];
|
||||
int mdctSize;
|
||||
mdctSize = mode->shortMdctSize*mode->nbShortMdcts;
|
||||
fprintf(file, "&mode%d_%d_%d,\n", mode->Fs, mdctSize, mode->overlap);
|
||||
}
|
||||
fprintf(file, "};\n");
|
||||
}
|
||||
|
||||
void dump_header(FILE *file, CELTMode **modes, int nb_modes)
|
||||
{
|
||||
int i;
|
||||
int channels = 0;
|
||||
int frame_size = 0;
|
||||
int overlap = 0;
|
||||
fprintf (file, "/* This header file is generated automatically*/\n");
|
||||
for (i=0;i<nb_modes;i++)
|
||||
{
|
||||
CELTMode *mode = modes[i];
|
||||
if (frame_size==0)
|
||||
frame_size = mode->shortMdctSize*mode->nbShortMdcts;
|
||||
else if (frame_size != mode->shortMdctSize*mode->nbShortMdcts)
|
||||
frame_size = -1;
|
||||
if (overlap==0)
|
||||
overlap = mode->overlap;
|
||||
else if (overlap != mode->overlap)
|
||||
overlap = -1;
|
||||
}
|
||||
if (channels>0)
|
||||
{
|
||||
fprintf (file, "#define CHANNELS(mode) %d\n", channels);
|
||||
if (channels==1)
|
||||
fprintf (file, "#define DISABLE_STEREO\n");
|
||||
}
|
||||
if (frame_size>0)
|
||||
{
|
||||
fprintf (file, "#define FRAMESIZE(mode) %d\n", frame_size);
|
||||
}
|
||||
if (overlap>0)
|
||||
{
|
||||
fprintf (file, "#define OVERLAP(mode) %d\n", overlap);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#define BASENAME "static_modes_fixed"
|
||||
#else
|
||||
#define BASENAME "static_modes_float"
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int i, nb;
|
||||
FILE *file;
|
||||
CELTMode **m;
|
||||
if (argc%2 != 1)
|
||||
{
|
||||
fprintf (stderr, "must have a multiple of 2 arguments\n");
|
||||
return 1;
|
||||
}
|
||||
nb = (argc-1)/2;
|
||||
m = malloc(nb*sizeof(CELTMode*));
|
||||
for (i=0;i<nb;i++)
|
||||
{
|
||||
int Fs, frame;
|
||||
Fs = atoi(argv[2*i+1]);
|
||||
frame = atoi(argv[2*i+2]);
|
||||
m[i] = celt_mode_create(Fs, frame, NULL);
|
||||
if (m[i]==NULL)
|
||||
{
|
||||
fprintf(stderr,"Error creating mode with Fs=%s, frame_size=%s\n",
|
||||
argv[2*i+1],argv[2*i+2]);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
file = fopen(BASENAME ".c", "w");
|
||||
dump_modes(file, m, nb);
|
||||
fclose(file);
|
||||
/*file = fopen(BASENAME ".h", "w");
|
||||
dump_header(file, m, nb);
|
||||
fclose(file);*/
|
||||
for (i=0;i<nb;i++)
|
||||
celt_mode_destroy(m[i]);
|
||||
free(m);
|
||||
return 0;
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
/*Some common macros for potential platform-specific optimization.*/
|
||||
#include "celt_types.h"
|
||||
#include <math.h>
|
||||
#include <limits.h>
|
||||
#if !defined(_ecintrin_H)
|
||||
# define _ecintrin_H (1)
|
||||
|
||||
/*Some specific platforms may have optimized intrinsic or 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.*/
|
||||
|
||||
/*Note that we do not provide a macro for abs(), because it is provided as a
|
||||
library function, which we assume is translated into an intrinsic to avoid
|
||||
the function call overhead and then implemented in the smartest way for the
|
||||
target platform.
|
||||
With modern gcc (4.x), this is true: it uses cmov instructions if the
|
||||
architecture supports it and branchless bit-twiddling if it does not (the
|
||||
speed difference between the two approaches is not measurable).
|
||||
Interestingly, the bit-twiddling method was patented in 2000 (US 6,073,150)
|
||||
by Sun Microsystems, despite prior art dating back to at least 1996:
|
||||
http://web.archive.org/web/19961201174141/www.x86.org/ftp/articles/pentopt/PENTOPT.TXT
|
||||
On gcc 3.x, however, our assumption is not true, as abs() is translated to a
|
||||
conditional jump, which is horrible on deeply piplined architectures (e.g.,
|
||||
all consumer architectures for the past decade or more) when the sign cannot
|
||||
be reliably predicted.*/
|
||||
|
||||
/*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_MAXI(_a,_b) ((_a)-((_a)-(_b)&-((_b)>(_a))))
|
||||
#define EC_MINI(_a,_b) ((_a)+((_b)-(_a)&-((_b)<(_a))))
|
||||
/*This has a chance of compiling branchless, and is just as fast as the
|
||||
bit-twiddling method, which is slightly less portable, since it relies on a
|
||||
sign-extended rightshift, which is not guaranteed by ANSI (but present on
|
||||
every relevant platform).*/
|
||||
#define EC_SIGNI(_a) (((_a)>0)-((_a)<0))
|
||||
/*Slightly more portable than relying on a sign-extended right-shift (which is
|
||||
not guaranteed by ANSI), and just as fast, since gcc (3.x and 4.x both)
|
||||
compile it into the right-shift anyway.*/
|
||||
#define EC_SIGNMASK(_a) (-((_a)<0))
|
||||
/*Clamps an integer into the given range.
|
||||
If _a>_c, then the lower bound _a is respected over the upper bound _c (this
|
||||
behavior is required to meet our documented API behavior).
|
||||
_a: The lower bound.
|
||||
_b: The value to clamp.
|
||||
_c: The upper boud.*/
|
||||
#define EC_CLAMPI(_a,_b,_c) (EC_MAXI(_a,EC_MINI(_b,_c)))
|
||||
|
||||
|
||||
/*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)
|
||||
# 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 defined(__GNUC_PREREQ)
|
||||
# if __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
|
||||
#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(celt_uint32 _v);
|
||||
|
||||
# define EC_ILOG(_x) (ec_ilog(_x))
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,90 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "entcode.h"
|
||||
|
||||
|
||||
|
||||
#if !defined(EC_CLZ)
|
||||
int ec_ilog(celt_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
|
||||
|
||||
|
||||
celt_uint32 ec_tell_frac(ec_ctx *_this){
|
||||
celt_uint32 nbits;
|
||||
celt_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;
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#include "celt_types.h"
|
||||
|
||||
#if !defined(_entcode_H)
|
||||
# define _entcode_H (1)
|
||||
# include <limits.h>
|
||||
# include <stddef.h>
|
||||
# include "ecintrin.h"
|
||||
|
||||
|
||||
|
||||
/*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 celt_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.*/
|
||||
celt_uint32 storage;
|
||||
/*The offset at which the last byte containing raw bits was read/written.*/
|
||||
celt_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.*/
|
||||
celt_uint32 offs;
|
||||
/*The number of values in the current range.*/
|
||||
celt_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.*/
|
||||
celt_uint32 val;
|
||||
/*In the decoder: the saved normalization factor from ec_decode().
|
||||
In the encoder: the number of oustanding carry propagating symbols.*/
|
||||
celt_uint32 ext;
|
||||
/*A buffered input/output symbol, awaiting carry propagation.*/
|
||||
int rem;
|
||||
/*Nonzero if an error occurred.*/
|
||||
int error;
|
||||
};
|
||||
|
||||
|
||||
/*Shared functions.*/
|
||||
static inline void ec_reset(ec_ctx *_this){
|
||||
_this->offs=_this->end_offs=0;
|
||||
}
|
||||
|
||||
static inline celt_uint32 ec_range_bytes(ec_ctx *_this){
|
||||
return _this->offs;
|
||||
}
|
||||
|
||||
static inline unsigned char *ec_get_buffer(ec_ctx *_this){
|
||||
return _this->buf;
|
||||
}
|
||||
|
||||
static 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 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).*/
|
||||
celt_uint32 ec_tell_frac(ec_ctx *_this);
|
||||
|
||||
#endif
|
||||
@@ -1,254 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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.
|
||||
|
||||
IBM (the author's employer) never sought to patent the idea, and to my
|
||||
knowledge the algorithm is unencumbered by any patents, though its
|
||||
performance is very competitive with proprietary arithmetic coding.
|
||||
The two are based on very similar ideas, however.
|
||||
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/ee398/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,celt_uint32 _storage){
|
||||
_this->buf=_buf;
|
||||
_this->storage=_storage;
|
||||
_this->end_offs=0;
|
||||
_this->end_window=0;
|
||||
_this->nend_bits=0;
|
||||
_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);
|
||||
/*This is the offset from which ec_tell() will subtract partial bits.
|
||||
This must be after the initial ec_dec_normalize(), or you will have to
|
||||
compensate for the bits that are read there.*/
|
||||
_this->nbits_total=EC_CODE_BITS+1;
|
||||
}
|
||||
|
||||
|
||||
unsigned ec_decode(ec_dec *_this,unsigned _ft){
|
||||
unsigned s;
|
||||
_this->ext=_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 (1<<_bits)-EC_MINI(s+1,1<<_bits);
|
||||
}
|
||||
|
||||
void ec_dec_update(ec_dec *_this,unsigned _fl,unsigned _fh,unsigned _ft){
|
||||
celt_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){
|
||||
celt_uint32 r;
|
||||
celt_uint32 d;
|
||||
celt_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){
|
||||
celt_uint32 r;
|
||||
celt_uint32 d;
|
||||
celt_uint32 s;
|
||||
celt_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;
|
||||
}
|
||||
|
||||
celt_uint32 ec_dec_uint(ec_dec *_this,celt_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){
|
||||
celt_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=(celt_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;
|
||||
}
|
||||
}
|
||||
|
||||
celt_uint32 ec_dec_bits(ec_dec *_this,unsigned _bits){
|
||||
ec_window window;
|
||||
int available;
|
||||
celt_uint32 ret;
|
||||
window=_this->end_window;
|
||||
available=_this->nend_bits;
|
||||
if(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=(celt_uint32)window&((celt_uint32)1<<_bits)-1;
|
||||
window>>=_bits;
|
||||
available-=_bits;
|
||||
_this->end_window=window;
|
||||
_this->nend_bits=available;
|
||||
_this->nbits_total+=_bits;
|
||||
return ret;
|
||||
}
|
||||
@@ -1,102 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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,celt_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 one, and no more than 2**32-1.
|
||||
Return: The decoded bits.*/
|
||||
celt_uint32 ec_dec_uint(ec_dec *_this,celt_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.*/
|
||||
celt_uint32 ec_dec_bits(ec_dec *_this,unsigned _ftb);
|
||||
|
||||
#endif
|
||||
@@ -1,298 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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 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,celt_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){
|
||||
celt_uint32 r;
|
||||
r=_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){
|
||||
celt_uint32 r;
|
||||
r=_this->rng>>_bits;
|
||||
if(_fl>0){
|
||||
_this->val+=_this->rng-IMUL32(r,((1<<_bits)-_fl));
|
||||
_this->rng=IMUL32(r,(_fh-_fl));
|
||||
}
|
||||
else _this->rng-=IMUL32(r,((1<<_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){
|
||||
celt_uint32 r;
|
||||
celt_uint32 s;
|
||||
celt_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){
|
||||
celt_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,celt_uint32 _fl,celt_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&((celt_uint32)1<<ftb)-1,ftb);
|
||||
}
|
||||
else ec_encode(_this,_fl,_fl+1,_ft+1);
|
||||
}
|
||||
|
||||
void ec_enc_bits(ec_enc *_this,celt_uint32 _fl,unsigned _bits){
|
||||
ec_window window;
|
||||
int used;
|
||||
window=_this->end_window;
|
||||
used=_this->nend_bits;
|
||||
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>>shift){
|
||||
/*The renormalization loop has never been run.*/
|
||||
_this->val=_this->val&~((celt_uint32)mask<<EC_CODE_SHIFT)|
|
||||
(celt_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,celt_uint32 _size){
|
||||
celt_assert(_this->offs+_this->end_offs<=_size);
|
||||
CELT_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;
|
||||
celt_uint32 msk;
|
||||
celt_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){
|
||||
CELT_MEMSET(_this->buf+_this->offs,0,
|
||||
_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;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,112 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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,celt_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 one, and no more than 2**32-1.*/
|
||||
void ec_enc_uint(ec_enc *_this,celt_uint32 _fl,celt_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 0 and 25, inclusive.*/
|
||||
void ec_enc_bits(ec_enc *_this,celt_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,celt_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
|
||||
@@ -1,89 +0,0 @@
|
||||
/* Copyright (C) 2003 Jean-Marc Valin */
|
||||
/**
|
||||
@file fixed_c5x.h
|
||||
@brief Fixed-point operations for the TI C5x DSP family
|
||||
*/
|
||||
/*
|
||||
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 FIXED_C5X_H
|
||||
#define FIXED_C5X_H
|
||||
|
||||
#include "dsplib.h"
|
||||
|
||||
#undef IMUL32
|
||||
static inline long IMUL32(long i, long j)
|
||||
{
|
||||
long ac0, ac1;
|
||||
ac0 = _lmpy(i>>16,j);
|
||||
ac1 = ac0 + _lmpy(i,j>>16);
|
||||
return _lmpyu(i,j) + (ac1<<16);
|
||||
}
|
||||
|
||||
#undef MAX16
|
||||
#define MAX16(a,b) _max(a,b)
|
||||
|
||||
#undef MIN16
|
||||
#define MIN16(a,b) _min(a,b)
|
||||
|
||||
#undef MAX32
|
||||
#define MAX32(a,b) _lmax(a,b)
|
||||
|
||||
#undef MIN32
|
||||
#define MIN32(a,b) _lmin(a,b)
|
||||
|
||||
#undef VSHR32
|
||||
#define VSHR32(a, shift) _lshl(a,-(shift))
|
||||
|
||||
#undef MULT16_16_Q15
|
||||
#define MULT16_16_Q15(a,b) (_smpy(a,b))
|
||||
|
||||
#undef MULT16_16SU
|
||||
#define MULT16_16SU(a,b) _lmpysu(a,b)
|
||||
|
||||
#undef MULT_16_16
|
||||
#define MULT_16_16(a,b) _lmpy(a,b)
|
||||
|
||||
/* FIXME: This is technically incorrect and is bound to cause problems. Is there any cleaner solution? */
|
||||
#undef MULT16_32_Q15
|
||||
#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),(b)),15))
|
||||
|
||||
|
||||
#define celt_ilog2(x) (30 - _lnorm(x))
|
||||
#define OVERRIDE_CELT_ILOG2
|
||||
|
||||
#define celt_maxabs16(x, len) MAX16(maxval((DATA *)x, len),-minval((DATA *)x, len))
|
||||
#define OVERRIDE_CELT_MAXABS16
|
||||
|
||||
#define OVERRIDE_FIND_MAX16
|
||||
static inline int find_max16(celt_word16 *x, int len)
|
||||
{
|
||||
DATA max_corr16 = -VERY_LARGE16;
|
||||
DATA pitch16 = 0;
|
||||
maxvec((DATA *)x, len, &max_corr16, &pitch16);
|
||||
return pitch16;
|
||||
}
|
||||
|
||||
#endif /* FIXED_C5X_H */
|
||||
@@ -1,80 +0,0 @@
|
||||
/* Copyright (C) 2008 CSIRO */
|
||||
/**
|
||||
@file fixed_c6x.h
|
||||
@brief Fixed-point operations for the TI C6x DSP family
|
||||
*/
|
||||
/*
|
||||
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 FIXED_C6X_H
|
||||
#define FIXED_C6X_H
|
||||
|
||||
#undef MULT16_16SU
|
||||
#define MULT16_16SU(a,b) _mpysu(a,b)
|
||||
|
||||
#undef MULT_16_16
|
||||
#define MULT_16_16(a,b) _mpy(a,b)
|
||||
|
||||
#define celt_ilog2(x) (30 - _norm(x))
|
||||
#define OVERRIDE_CELT_ILOG2
|
||||
|
||||
#undef MULT16_32_Q15
|
||||
#define MULT16_32_Q15(a,b) (_mpylill(a, b) >> 15)
|
||||
|
||||
#if 0
|
||||
#include "dsplib.h"
|
||||
|
||||
#undef MAX16
|
||||
#define MAX16(a,b) _max(a,b)
|
||||
|
||||
#undef MIN16
|
||||
#define MIN16(a,b) _min(a,b)
|
||||
|
||||
#undef MAX32
|
||||
#define MAX32(a,b) _lmax(a,b)
|
||||
|
||||
#undef MIN32
|
||||
#define MIN32(a,b) _lmin(a,b)
|
||||
|
||||
#undef VSHR32
|
||||
#define VSHR32(a, shift) _lshl(a,-(shift))
|
||||
|
||||
#undef MULT16_16_Q15
|
||||
#define MULT16_16_Q15(a,b) (_smpy(a,b))
|
||||
|
||||
#define celt_maxabs16(x, len) MAX16(maxval((DATA *)x, len),-minval((DATA *)x, len))
|
||||
#define OVERRIDE_CELT_MAXABS16
|
||||
|
||||
#define OVERRIDE_FIND_MAX16
|
||||
static inline int find_max16(celt_word16 *x, int len)
|
||||
{
|
||||
DATA max_corr16 = -VERY_LARGE16;
|
||||
DATA pitch16 = 0;
|
||||
maxvec((DATA *)x, len, &max_corr16, &pitch16);
|
||||
return pitch16;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FIXED_C6X_H */
|
||||
@@ -1,551 +0,0 @@
|
||||
/* Copyright (C) 2003-2008 Jean-Marc Valin
|
||||
Copyright (C) 2007-2009 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 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 FIXED_DEBUG_H
|
||||
#define FIXED_DEBUG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef CELT_C
|
||||
long long celt_mips=0;
|
||||
#else
|
||||
extern long long celt_mips;
|
||||
#endif
|
||||
|
||||
#define MIPS_INC celt_mips++,
|
||||
|
||||
#define MULT16_16SU(a,b) ((celt_word32)(celt_word16)(a)*(celt_word32)(celt_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 QCONST16(x,bits) ((celt_word16)(.5+(x)*(((celt_word32)1)<<(bits))))
|
||||
#define QCONST32(x,bits) ((celt_word32)(.5+(x)*(((celt_word32)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)
|
||||
|
||||
static inline short NEG16(int x)
|
||||
{
|
||||
int res;
|
||||
if (!VERIFY_SHORT(x))
|
||||
{
|
||||
fprintf (stderr, "NEG16: input is not short: %d\n", (int)x);
|
||||
}
|
||||
res = -x;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "NEG16: output is not short: %d\n", (int)res);
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
static inline int NEG32(long long x)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_INT(x))
|
||||
{
|
||||
fprintf (stderr, "NEG16: input is not int: %d\n", (int)x);
|
||||
}
|
||||
res = -x;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "NEG16: output is not int: %d\n", (int)res);
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define EXTRACT16(x) _EXTRACT16(x, __FILE__, __LINE__)
|
||||
static 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);
|
||||
}
|
||||
res = x;
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define EXTEND32(x) _EXTEND32(x, __FILE__, __LINE__)
|
||||
static 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);
|
||||
}
|
||||
res = x;
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SHR16(a, shift) _SHR16(a, shift, __FILE__, __LINE__)
|
||||
static 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);
|
||||
}
|
||||
res = a>>shift;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "SHR16: output is not short: %d in %s: line %d\n", res, file, line);
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
#define SHL16(a, shift) _SHL16(a, shift, __FILE__, __LINE__)
|
||||
static 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);
|
||||
}
|
||||
res = a<<shift;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "SHL16: output is not short: %d in %s: line %d\n", res, file, line);
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int SHR32(long long a, int shift)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
|
||||
{
|
||||
fprintf (stderr, "SHR32: inputs are not int: %d %d\n", (int)a, shift);
|
||||
}
|
||||
res = a>>shift;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "SHR32: output is not int: %d\n", (int)res);
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
static inline int SHL32(long long a, int shift)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_INT(a) || !VERIFY_SHORT(shift))
|
||||
{
|
||||
fprintf (stderr, "SHL32: inputs are not int: %d %d\n", (int)a, shift);
|
||||
}
|
||||
res = a<<shift;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "SHL32: output is not int: %d\n", (int)res);
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define PSHR16(a,shift) (celt_mips--,SHR16(ADD16((a),((1<<((shift))>>1))),shift))
|
||||
#define PSHR32(a,shift) (celt_mips--,SHR32(ADD32((a),(((celt_word32)(1)<<((shift))>>1))),shift))
|
||||
#define VSHR32(a, shift) (((shift)>0) ? SHR32(a, shift) : SHL32(a, -(shift)))
|
||||
|
||||
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||
|
||||
#define ROUND16(x,a) (celt_mips--,EXTRACT16(PSHR32((x),(a))))
|
||||
#define HALF32(x) (SHR32(x,1))
|
||||
|
||||
//#define SHR(a,shift) ((a) >> (shift))
|
||||
//#define SHL(a,shift) ((a) << (shift))
|
||||
|
||||
#define ADD16(a, b) _ADD16(a, b, __FILE__, __LINE__)
|
||||
static 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SUB16(a, b) _SUB16(a, b, __FILE__, __LINE__)
|
||||
static 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);
|
||||
}
|
||||
res = a-b;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "SUB16: output is not short: %d in %s: line %d\n", res, file, line);
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define ADD32(a, b) _ADD32(a, b, __FILE__, __LINE__)
|
||||
static inline int _ADD32(long long a, long long b, char *file, int line)
|
||||
{
|
||||
long long 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);
|
||||
}
|
||||
res = a+b;
|
||||
if (!VERIFY_INT(res))
|
||||
{
|
||||
fprintf (stderr, "ADD32: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define SUB32(a, b) _SUB32(a, b, __FILE__, __LINE__)
|
||||
static inline int _SUB32(long long a, long long b, char *file, int line)
|
||||
{
|
||||
long long 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);
|
||||
}
|
||||
res = a-b;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "SUB32: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef UADD32
|
||||
#define UADD32(a, b) _UADD32(a, b, __FILE__, __LINE__)
|
||||
static inline unsigned int _UADD32(unsigned long long a, unsigned long long b, char *file, int line)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
|
||||
{
|
||||
fprintf (stderr, "UADD32: inputs are not int: %u %u in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);
|
||||
}
|
||||
res = a+b;
|
||||
if (!VERIFY_UINT(res))
|
||||
{
|
||||
fprintf (stderr, "UADD32: output is not int: %u in %s: line %d\n", (unsigned)res, file, line);
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#undef USUB32
|
||||
#define USUB32(a, b) _USUB32(a, b, __FILE__, __LINE__)
|
||||
static inline unsigned int _USUB32(unsigned long long a, unsigned long long b, char *file, int line)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_UINT(a) || !VERIFY_UINT(b))
|
||||
{
|
||||
/*fprintf (stderr, "USUB32: inputs are not int: %llu %llu in %s: line %d\n", (unsigned)a, (unsigned)b, file, line);*/
|
||||
}
|
||||
res = a-b;
|
||||
if (!VERIFY_UINT(res))
|
||||
{
|
||||
/*fprintf (stderr, "USUB32: output is not int: %llu - %llu = %llu in %s: line %d\n", a, b, res, file, line);*/
|
||||
}
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* result fits in 16 bits */
|
||||
static 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);
|
||||
}
|
||||
res = a*b;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "MULT16_16_16: output is not short: %d\n", res);
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MULT16_16(a, b) _MULT16_16(a, b, __FILE__, __LINE__)
|
||||
static inline int _MULT16_16(int a, int b, char *file, int line)
|
||||
{
|
||||
long long 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);
|
||||
}
|
||||
res = ((long long)a)*b;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "MULT16_16: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
celt_mips++;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MAC16_16(c,a,b) (celt_mips-=2,ADD32((c),MULT16_16((a),(b))))
|
||||
#define MAC16_16_Q11(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),11))))
|
||||
#define MAC16_16_Q13(c,a,b) (ADD16((c),EXTRACT16(SHR32(MULT16_16((a),(b)),13))))
|
||||
#define MAC16_16_P13(c,a,b) (ADD16((c),SHR32(ADD32(4096,MULT16_16((a),(b))),13)))
|
||||
|
||||
|
||||
#define MULT16_32_QX(a, b, Q) _MULT16_32_QX(a, b, Q, __FILE__, __LINE__)
|
||||
static inline int _MULT16_32_QX(int a, long long b, int Q, char *file, int line)
|
||||
{
|
||||
long long 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);
|
||||
}
|
||||
if (ABS32(b)>=((celt_word32)(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);
|
||||
res = (((long long)a)*(long long)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);
|
||||
if (Q==15)
|
||||
celt_mips+=3;
|
||||
else
|
||||
celt_mips+=4;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline int MULT16_32_PX(int a, long long b, int Q)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_INT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_32_P%d: inputs are not short+int: %d %d\n", Q, (int)a, (int)b);
|
||||
}
|
||||
if (ABS32(b)>=((celt_word32)(1)<<(15+Q)))
|
||||
fprintf (stderr, "MULT16_32_Q%d: second operand too large: %d %d\n", Q, (int)a, (int)b);
|
||||
res = ((((long long)a)*(long long)b) + (((celt_word32)(1)<<Q)>>1))>> Q;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "MULT16_32_P%d: output is not int: %d*%d=%d\n", Q, (int)a, (int)b,(int)res);
|
||||
if (Q==15)
|
||||
celt_mips+=4;
|
||||
else
|
||||
celt_mips+=5;
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
#define MULT16_32_Q11(a,b) MULT16_32_QX(a,b,11)
|
||||
#define MAC16_32_Q11(c,a,b) ADD32((c),MULT16_32_Q11((a),(b)))
|
||||
#define MULT16_32_Q12(a,b) MULT16_32_QX(a,b,12)
|
||||
#define MULT16_32_Q13(a,b) MULT16_32_QX(a,b,13)
|
||||
#define MULT16_32_Q14(a,b) MULT16_32_QX(a,b,14)
|
||||
#define MULT16_32_Q15(a,b) MULT16_32_QX(a,b,15)
|
||||
#define MULT16_32_P15(a,b) MULT16_32_PX(a,b,15)
|
||||
#define MAC16_32_Q15(c,a,b) (celt_mips-=2,ADD32((c),MULT16_32_Q15((a),(b))))
|
||||
|
||||
static inline int SATURATE(int a, int b)
|
||||
{
|
||||
if (a>b)
|
||||
a=b;
|
||||
if (a<-b)
|
||||
a = -b;
|
||||
celt_mips+=3;
|
||||
return a;
|
||||
}
|
||||
|
||||
static inline int MULT16_16_Q11_32(int a, int b)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q11: inputs are not short: %d %d\n", a, b);
|
||||
}
|
||||
res = ((long long)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);
|
||||
celt_mips+=3;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_Q13(int a, int b)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q13: inputs are not short: %d %d\n", a, b);
|
||||
}
|
||||
res = ((long long)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);
|
||||
celt_mips+=3;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_Q14(int a, int b)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_Q14: inputs are not short: %d %d\n", a, b);
|
||||
}
|
||||
res = ((long long)a)*b;
|
||||
res >>= 14;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "MULT16_16_Q14: output is not short: %d\n", (int)res);
|
||||
celt_mips+=3;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define MULT16_16_Q15(a, b) _MULT16_16_Q15(a, b, __FILE__, __LINE__)
|
||||
static inline short _MULT16_16_Q15(int a, int b, char *file, int line)
|
||||
{
|
||||
long long 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);
|
||||
}
|
||||
res = ((long long)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);
|
||||
}
|
||||
celt_mips+=1;
|
||||
return res;
|
||||
}
|
||||
|
||||
static inline short MULT16_16_P13(int a, int b)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P13: inputs are not short: %d %d\n", a, b);
|
||||
}
|
||||
res = ((long long)a)*b;
|
||||
res += 4096;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "MULT16_16_P13: overflow: %d*%d=%d\n", a, b, (int)res);
|
||||
res >>= 13;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "MULT16_16_P13: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
celt_mips+=4;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_P14(int a, int b)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P14: inputs are not short: %d %d\n", a, b);
|
||||
}
|
||||
res = ((long long)a)*b;
|
||||
res += 8192;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "MULT16_16_P14: overflow: %d*%d=%d\n", a, b, (int)res);
|
||||
res >>= 14;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "MULT16_16_P14: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
celt_mips+=4;
|
||||
return res;
|
||||
}
|
||||
static inline short MULT16_16_P15(int a, int b)
|
||||
{
|
||||
long long res;
|
||||
if (!VERIFY_SHORT(a) || !VERIFY_SHORT(b))
|
||||
{
|
||||
fprintf (stderr, "MULT16_16_P15: inputs are not short: %d %d\n", a, b);
|
||||
}
|
||||
res = ((long long)a)*b;
|
||||
res += 16384;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "MULT16_16_P15: overflow: %d*%d=%d\n", a, b, (int)res);
|
||||
res >>= 15;
|
||||
if (!VERIFY_SHORT(res))
|
||||
fprintf (stderr, "MULT16_16_P15: output is not short: %d*%d=%d\n", a, b, (int)res);
|
||||
celt_mips+=2;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define DIV32_16(a, b) _DIV32_16(a, b, __FILE__, __LINE__)
|
||||
|
||||
static inline int _DIV32_16(long long a, long long b, char *file, int line)
|
||||
{
|
||||
long long res;
|
||||
if (b==0)
|
||||
{
|
||||
fprintf(stderr, "DIV32_16: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
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);
|
||||
}
|
||||
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;
|
||||
}
|
||||
celt_mips+=35;
|
||||
return res;
|
||||
}
|
||||
|
||||
#define DIV32(a, b) _DIV32(a, b, __FILE__, __LINE__)
|
||||
static inline int _DIV32(long long a, long long b, char *file, int line)
|
||||
{
|
||||
long long res;
|
||||
if (b==0)
|
||||
{
|
||||
fprintf(stderr, "DIV32: divide by zero: %d/%d in %s: line %d\n", (int)a, (int)b, file, line);
|
||||
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);
|
||||
}
|
||||
res = a/b;
|
||||
if (!VERIFY_INT(res))
|
||||
fprintf (stderr, "DIV32: output is not int: %d in %s: line %d\n", (int)res, file, line);
|
||||
celt_mips+=70;
|
||||
return res;
|
||||
}
|
||||
#define PDIV32(a,b) DIV32(ADD32((a),(b)>>1),b)
|
||||
#define PDIV32_16(a,b) DIV32_16(ADD32((a),(b)>>1),b)
|
||||
|
||||
#undef PRINT_MIPS
|
||||
#define PRINT_MIPS(file) do {fprintf (file, "total complexity = %llu MIPS\n", celt_mips);} while (0);
|
||||
|
||||
#endif
|
||||
@@ -1,157 +0,0 @@
|
||||
/* 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 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 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) ((celt_word32)(celt_word16)(a)*(celt_word32)(celt_uint16)(b))
|
||||
|
||||
/** 16x32 multiplication, followed by a 16-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q16(a,b) ADD32(MULT16_16((a),SHR((b),16)), SHR(MULT16_16SU((a),((b)&0x0000ffff)),16))
|
||||
|
||||
/** 16x32 multiplication, followed by a 15-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q15(a,b) ADD32(SHL(MULT16_16((a),SHR((b),16)),1), SHR(MULT16_16SU((a),((b)&0x0000ffff)),15))
|
||||
|
||||
/** 32x32 multiplication, followed by a 31-bit shift right. Results fits in 32 bits */
|
||||
#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))
|
||||
|
||||
/** 32x32 multiplication, followed by a 32-bit shift right. Results fits in 32 bits */
|
||||
#define MULT32_32_Q32(a,b) ADD32(ADD32(MULT16_16(SHR((a),16),SHR((b),16)), SHR(MULT16_16SU(SHR((a),16),((b)&0x0000ffff)),16)), SHR(MULT16_16SU(SHR((b),16),((a)&0x0000ffff)),16))
|
||||
|
||||
/** Compile-time conversion of float constant to 16-bit value */
|
||||
#define QCONST16(x,bits) ((celt_word16)(.5+(x)*(((celt_word32)1)<<(bits))))
|
||||
/** Compile-time conversion of float constant to 32-bit value */
|
||||
#define QCONST32(x,bits) ((celt_word32)(.5+(x)*(((celt_word32)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) ((celt_word16)(x))
|
||||
/** Change a 16-bit value into a 32-bit value */
|
||||
#define EXTEND32(x) ((celt_word32)(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) ((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) ((celt_word32)(a) << (shift))
|
||||
|
||||
/** 16-bit arithmetic shift right with rounding-to-nearest instead of rounding down */
|
||||
#define PSHR16(a,shift) (SHR16((a)+((1<<((shift))>>1)),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)))
|
||||
|
||||
/** Saturates 16-bit value to +/- a */
|
||||
#define SATURATE16(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||
/** Saturates 32-bit value to +/- a */
|
||||
#define SATURATE32(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (x)))
|
||||
|
||||
/** "RAW" macros, should not be used outside of this header file */
|
||||
#define SHR(a,shift) ((a) >> (shift))
|
||||
#define SHL(a,shift) ((celt_word32)(a) << (shift))
|
||||
#define PSHR(a,shift) (SHR((a)+((EXTEND32(1)<<((shift))>>1)),shift))
|
||||
#define SATURATE(x,a) (((x)>(a) ? (a) : (x)<-(a) ? -(a) : (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))))
|
||||
/** Divide by two */
|
||||
#define HALF32(x) (SHR32(x,1))
|
||||
|
||||
/** Add two 16-bit values */
|
||||
#define ADD16(a,b) ((celt_word16)((celt_word16)(a)+(celt_word16)(b)))
|
||||
/** Subtract two 16-bit values */
|
||||
#define SUB16(a,b) ((celt_word16)(a)-(celt_word16)(b))
|
||||
/** Add two 32-bit values */
|
||||
#define ADD32(a,b) ((celt_word32)(a)+(celt_word32)(b))
|
||||
/** Subtract two 32-bit values */
|
||||
#define SUB32(a,b) ((celt_word32)(a)-(celt_word32)(b))
|
||||
|
||||
|
||||
/** 16x16 multiplication where the result fits in 16 bits */
|
||||
#define MULT16_16_16(a,b) ((((celt_word16)(a))*((celt_word16)(b))))
|
||||
|
||||
/* (celt_word32)(celt_word16) 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) (((celt_word32)(celt_word16)(a))*((celt_word32)(celt_word16)(b)))
|
||||
|
||||
/** 16x16 multiply-add where the result fits in 32 bits */
|
||||
#define MAC16_16(c,a,b) (ADD32((c),MULT16_16((a),(b))))
|
||||
/** 16x32 multiplication, followed by a 12-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q12(a,b) ADD32(MULT16_16((a),SHR((b),12)), SHR(MULT16_16((a),((b)&0x00000fff)),12))
|
||||
/** 16x32 multiplication, followed by a 13-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q13(a,b) ADD32(MULT16_16((a),SHR((b),13)), SHR(MULT16_16((a),((b)&0x00001fff)),13))
|
||||
/** 16x32 multiplication, followed by a 14-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q14(a,b) ADD32(MULT16_16((a),SHR((b),14)), SHR(MULT16_16((a),((b)&0x00003fff)),14))
|
||||
|
||||
/** 16x32 multiplication, followed by an 11-bit shift right. Results fits in 32 bits */
|
||||
#define MULT16_32_Q11(a,b) ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11))
|
||||
/** 16x32 multiply-add, followed by an 11-bit shift right. Results fits in 32 bits */
|
||||
#define MAC16_32_Q11(c,a,b) ADD32(c,ADD32(MULT16_16((a),SHR((b),11)), SHR(MULT16_16((a),((b)&0x000007ff)),11)))
|
||||
|
||||
/** 16x32 multiplication, followed by a 15-bit shift right (round-to-nearest). Results fits in 32 bits */
|
||||
#define MULT16_32_P15(a,b) ADD32(MULT16_16((a),SHR((b),15)), PSHR(MULT16_16((a),((b)&0x00007fff)),15))
|
||||
/** 16x32 multiply-add, followed by a 15-bit shift right. Results 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)))
|
||||
|
||||
|
||||
#define MAC16_16_Q11(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),11)))
|
||||
#define MAC16_16_Q13(c,a,b) (ADD32((c),SHR(MULT16_16((a),(b)),13)))
|
||||
#define MAC16_16_P13(c,a,b) (ADD32((c),SHR(ADD32(4096,MULT16_16((a),(b))),13)))
|
||||
|
||||
#define MULT16_16_Q11_32(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) ((celt_word16)(((celt_word32)(a))/((celt_word16)(b))))
|
||||
/** Divide a 32-bit value by a 16-bit value and round to nearest. Result fits in 16 bits */
|
||||
#define PDIV32_16(a,b) ((celt_word16)(((celt_word32)(a)+((celt_word16)(b)>>1))/((celt_word16)(b))))
|
||||
/** Divide a 32-bit value by a 32-bit value. Result fits in 32 bits */
|
||||
#define DIV32(a,b) (((celt_word32)(a))/((celt_word32)(b)))
|
||||
/** Divide a 32-bit value by a 32-bit value and round to nearest. Result fits in 32 bits */
|
||||
#define PDIV32(a,b) (((celt_word32)(a)+((celt_word16)(b)>>1))/((celt_word32)(b)))
|
||||
|
||||
#endif
|
||||
@@ -1,132 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
/* Version 1.1 */
|
||||
|
||||
#ifndef FLOAT_CAST_H
|
||||
#define FLOAT_CAST_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.
|
||||
*/
|
||||
|
||||
#if (HAVE_LRINTF)
|
||||
/*#if 0*/
|
||||
|
||||
/* 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 (WIN64) || defined (_WIN64))
|
||||
#include <xmmintrin.h>
|
||||
|
||||
__inline long int float2int(float value)
|
||||
{
|
||||
return _mm_cvtss_si32(_mm_load_ss(&value));
|
||||
}
|
||||
#elif (defined (WIN32) || defined (_WIN32))
|
||||
|
||||
#include <math.h>
|
||||
|
||||
/* Win32 doesn't seem to have these functions.
|
||||
** Therefore implement inline versions of these functions here.
|
||||
*/
|
||||
|
||||
__inline long int
|
||||
float2int (float flt)
|
||||
{ int intgr;
|
||||
|
||||
_asm
|
||||
{ fld flt
|
||||
fistp intgr
|
||||
} ;
|
||||
|
||||
return intgr ;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __GNUC__ /* supported by gcc, 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 /* __GNUC__ */
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#define float2int(flt) ((int)(floor(.5+flt)))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* FLOAT_CAST_H */
|
||||
@@ -1,124 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt_header.h"
|
||||
#include "os_support.h"
|
||||
#include "modes.h"
|
||||
|
||||
static celt_uint32
|
||||
_le_32 (celt_uint32 i)
|
||||
{
|
||||
celt_uint32 ret=i;
|
||||
#if !defined(__LITTLE_ENDIAN__) && ( defined(WORDS_BIGENDIAN) || defined(__BIG_ENDIAN__) )
|
||||
ret = (i>>24);
|
||||
ret += (i>>8) & 0x0000ff00;
|
||||
ret += (i<<8) & 0x00ff0000;
|
||||
ret += (i<<24);
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
|
||||
int celt_header_init(CELTHeader *header, const CELTMode *m, int frame_size, int channels)
|
||||
{
|
||||
if (header==NULL)
|
||||
return CELT_BAD_ARG;
|
||||
|
||||
CELT_COPY(header->codec_id, "CELT ", 8);
|
||||
CELT_COPY(header->codec_version, "experimental ", 20);
|
||||
|
||||
/* FIXME: Set that to zero when we freeze */
|
||||
header->version_id = 0x80001000;
|
||||
header->header_size = 56;
|
||||
header->sample_rate = m->Fs;
|
||||
header->nb_channels = channels;
|
||||
/*FIXME: This won't work for variable frame size */
|
||||
header->frame_size = frame_size;
|
||||
header->overlap = m->overlap;
|
||||
header->bytes_per_packet = -1;
|
||||
header->extra_headers = 0;
|
||||
return CELT_OK;
|
||||
}
|
||||
|
||||
int celt_header_to_packet(const CELTHeader *header, unsigned char *packet, celt_uint32 size)
|
||||
{
|
||||
celt_int32 * h;
|
||||
|
||||
if ((size < 56) || (header==NULL) || (packet==NULL))
|
||||
return CELT_BAD_ARG; /* FAIL */
|
||||
|
||||
CELT_MEMSET(packet, 0, sizeof(*header));
|
||||
/* FIXME: Do it in an alignment-safe manner */
|
||||
|
||||
/* Copy ident and version */
|
||||
CELT_COPY(packet, (unsigned char*)header, 28);
|
||||
|
||||
/* Copy the int32 fields */
|
||||
h = (celt_int32*)(packet+28);
|
||||
*h++ = _le_32 (header->version_id);
|
||||
*h++ = _le_32 (header->header_size);
|
||||
*h++ = _le_32 (header->sample_rate);
|
||||
*h++ = _le_32 (header->nb_channels);
|
||||
*h++ = _le_32 (header->frame_size);
|
||||
*h++ = _le_32 (header->overlap);
|
||||
*h++ = _le_32 (header->bytes_per_packet);
|
||||
*h = _le_32 (header->extra_headers);
|
||||
|
||||
return sizeof(*header);
|
||||
}
|
||||
|
||||
int celt_header_from_packet(const unsigned char *packet, celt_uint32 size, CELTHeader *header)
|
||||
{
|
||||
celt_int32 * h;
|
||||
|
||||
if ((size < 56) || (header==NULL) || (packet==NULL))
|
||||
return CELT_BAD_ARG; /* FAIL */
|
||||
|
||||
CELT_MEMSET((unsigned char*)header, 0, sizeof(*header));
|
||||
/* FIXME: Do it in an alignment-safe manner */
|
||||
|
||||
/* Copy ident and version */
|
||||
CELT_COPY((unsigned char*)header, packet, 28);
|
||||
|
||||
/* Copy the int32 fields */
|
||||
h = (celt_int32*)(packet+28);
|
||||
header->version_id = _le_32(*h++);
|
||||
header->header_size = _le_32(*h++);
|
||||
header->sample_rate = _le_32(*h++);
|
||||
header->nb_channels = _le_32(*h++);
|
||||
header->frame_size = _le_32(*h++);
|
||||
header->overlap = _le_32(*h++);
|
||||
header->bytes_per_packet = _le_32(*h++);
|
||||
header->extra_headers = _le_32(*h);
|
||||
|
||||
return sizeof(*header);
|
||||
}
|
||||
|
||||
@@ -1,693 +0,0 @@
|
||||
/*
|
||||
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 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,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
const kiss_twiddle_cpx * tw1;
|
||||
int i,j;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
Fout2 = Fout + m;
|
||||
tw1 = st->twiddles;
|
||||
for(j=0;j<m;j++)
|
||||
{
|
||||
kiss_fft_cpx t;
|
||||
Fout->r = SHR(Fout->r, 1);Fout->i = SHR(Fout->i, 1);
|
||||
Fout2->r = SHR(Fout2->r, 1);Fout2->i = SHR(Fout2->i, 1);
|
||||
C_MUL (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly2(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
kiss_fft_cpx * Fout2;
|
||||
const kiss_twiddle_cpx * tw1;
|
||||
kiss_fft_cpx t;
|
||||
int i,j;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
Fout2 = Fout + m;
|
||||
tw1 = st->twiddles;
|
||||
for(j=0;j<m;j++)
|
||||
{
|
||||
C_MULC (t, *Fout2 , *tw1);
|
||||
tw1 += fstride;
|
||||
C_SUB( *Fout2 , *Fout , t );
|
||||
C_ADDTO( *Fout , t );
|
||||
++Fout2;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void kf_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
const kiss_twiddle_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
int i, j;
|
||||
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
for (j=0;j<m;j++)
|
||||
{
|
||||
C_MUL4(scratch[0],Fout[m] , *tw1 );
|
||||
C_MUL4(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MUL4(scratch[2],Fout[m3] , *tw3 );
|
||||
|
||||
Fout->r = PSHR(Fout->r, 2);
|
||||
Fout->i = PSHR(Fout->i, 2);
|
||||
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] );
|
||||
Fout[m2].r = PSHR(Fout[m2].r, 2);
|
||||
Fout[m2].i = PSHR(Fout[m2].i, 2);
|
||||
C_SUB( Fout[m2], *Fout, scratch[3] );
|
||||
tw1 += fstride;
|
||||
tw2 += fstride*2;
|
||||
tw3 += fstride*3;
|
||||
C_ADDTO( *Fout , scratch[3] );
|
||||
|
||||
Fout[m].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m].i = scratch[5].i - scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r - scratch[4].i;
|
||||
Fout[m3].i = scratch[5].i + scratch[4].r;
|
||||
++Fout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly4(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
int m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
const kiss_twiddle_cpx *tw1,*tw2,*tw3;
|
||||
kiss_fft_cpx scratch[6];
|
||||
const size_t m2=2*m;
|
||||
const size_t m3=3*m;
|
||||
int i, j;
|
||||
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw3 = tw2 = tw1 = st->twiddles;
|
||||
for (j=0;j<m;j++)
|
||||
{
|
||||
C_MULC(scratch[0],Fout[m] , *tw1 );
|
||||
C_MULC(scratch[1],Fout[m2] , *tw2 );
|
||||
C_MULC(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 = scratch[5].r - scratch[4].i;
|
||||
Fout[m].i = scratch[5].i + scratch[4].r;
|
||||
Fout[m3].r = scratch[5].r + scratch[4].i;
|
||||
Fout[m3].i = 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;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw1=tw2=st->twiddles;
|
||||
k=m;
|
||||
do {
|
||||
C_FIXDIV(*Fout,3); C_FIXDIV(Fout[m],3); C_FIXDIV(Fout[m2],3);
|
||||
|
||||
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 = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
} while(--k);
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_bfly3(
|
||||
kiss_fft_cpx * Fout,
|
||||
const size_t fstride,
|
||||
const kiss_fft_state *st,
|
||||
size_t m,
|
||||
int N,
|
||||
int mm
|
||||
)
|
||||
{
|
||||
size_t i, 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;
|
||||
epi3 = st->twiddles[fstride*m];
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
Fout = Fout_beg + i*mm;
|
||||
tw1=tw2=st->twiddles;
|
||||
k=m;
|
||||
do{
|
||||
|
||||
C_MULC(scratch[1],Fout[m] , *tw1);
|
||||
C_MULC(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 = Fout->r - HALF_OF(scratch[3].r);
|
||||
Fout[m].i = Fout->i - HALF_OF(scratch[3].i);
|
||||
|
||||
C_MULBYSCALAR( scratch[0] , -epi3.i );
|
||||
|
||||
C_ADDTO(*Fout,scratch[3]);
|
||||
|
||||
Fout[m2].r = Fout[m].r + scratch[0].i;
|
||||
Fout[m2].i = Fout[m].i - scratch[0].r;
|
||||
|
||||
Fout[m].r -= scratch[0].i;
|
||||
Fout[m].i += scratch[0].r;
|
||||
|
||||
++Fout;
|
||||
}while(--k);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 * twiddles = st->twiddles;
|
||||
const kiss_twiddle_cpx *tw;
|
||||
kiss_twiddle_cpx ya,yb;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
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 ( u=0; u<m; ++u ) {
|
||||
C_FIXDIV( *Fout0,5); C_FIXDIV( *Fout1,5); C_FIXDIV( *Fout2,5); C_FIXDIV( *Fout3,5); C_FIXDIV( *Fout4,5);
|
||||
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 += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = S_MUL(scratch[10].i,ya.i) + S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = -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 = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = - S_MUL(scratch[10].i,yb.i) + S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void ki_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 * twiddles = st->twiddles;
|
||||
const kiss_twiddle_cpx *tw;
|
||||
kiss_twiddle_cpx ya,yb;
|
||||
kiss_fft_cpx * Fout_beg = Fout;
|
||||
|
||||
ya = twiddles[fstride*m];
|
||||
yb = twiddles[fstride*2*m];
|
||||
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 ( u=0; u<m; ++u ) {
|
||||
scratch[0] = *Fout0;
|
||||
|
||||
C_MULC(scratch[1] ,*Fout1, tw[u*fstride]);
|
||||
C_MULC(scratch[2] ,*Fout2, tw[2*u*fstride]);
|
||||
C_MULC(scratch[3] ,*Fout3, tw[3*u*fstride]);
|
||||
C_MULC(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 += scratch[7].r + scratch[8].r;
|
||||
Fout0->i += scratch[7].i + scratch[8].i;
|
||||
|
||||
scratch[5].r = scratch[0].r + S_MUL(scratch[7].r,ya.r) + S_MUL(scratch[8].r,yb.r);
|
||||
scratch[5].i = scratch[0].i + S_MUL(scratch[7].i,ya.r) + S_MUL(scratch[8].i,yb.r);
|
||||
|
||||
scratch[6].r = -S_MUL(scratch[10].i,ya.i) - S_MUL(scratch[9].i,yb.i);
|
||||
scratch[6].i = 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 = scratch[0].r + S_MUL(scratch[7].r,yb.r) + S_MUL(scratch[8].r,ya.r);
|
||||
scratch[11].i = scratch[0].i + S_MUL(scratch[7].i,yb.r) + S_MUL(scratch[8].i,ya.r);
|
||||
scratch[12].r = S_MUL(scratch[10].i,yb.i) - S_MUL(scratch[9].i,ya.i);
|
||||
scratch[12].i = -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
|
||||
|
||||
static void kf_work(
|
||||
kiss_fft_cpx * Fout,
|
||||
const kiss_fft_cpx * f,
|
||||
size_t fstride,
|
||||
int in_stride,
|
||||
const celt_int16 * factors,
|
||||
const kiss_fft_state *st,
|
||||
int N,
|
||||
int m2
|
||||
)
|
||||
{
|
||||
const int p=*factors++; /* the radix */
|
||||
const int m=*factors++; /* stage's fft length/p */
|
||||
/*printf ("fft %d %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N, m2);*/
|
||||
if (m!=1)
|
||||
kf_work( Fout , f, fstride*p, in_stride, factors,st, N*p, m);
|
||||
|
||||
/* Compensate for longer twiddles table (when sharing) */
|
||||
if (st->shift>0)
|
||||
fstride <<= st->shift;
|
||||
switch (p) {
|
||||
case 2: kf_bfly2(Fout,fstride,st,m, N, m2); break;
|
||||
case 4: kf_bfly4(Fout,fstride,st,m, N, m2); break;
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
case 3: kf_bfly3(Fout,fstride,st,m, N, m2); break;
|
||||
case 5: kf_bfly5(Fout,fstride,st,m, N, m2); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void ki_work(
|
||||
kiss_fft_cpx * Fout,
|
||||
const kiss_fft_cpx * f,
|
||||
size_t fstride,
|
||||
int in_stride,
|
||||
const celt_int16 * factors,
|
||||
const kiss_fft_state *st,
|
||||
int N,
|
||||
int m2
|
||||
)
|
||||
{
|
||||
const int p=*factors++; /* the radix */
|
||||
const int m=*factors++; /* stage's fft length/p */
|
||||
/*printf ("fft %d %d %d %d %d %d %d\n", p*m, m, p, s2, fstride*in_stride, N, m2);*/
|
||||
if (m!=1)
|
||||
ki_work( Fout , f, fstride*p, in_stride, factors,st, N*p, m);
|
||||
|
||||
/* Compensate for longer twiddles table (when sharing) */
|
||||
if (st->shift>0)
|
||||
fstride <<= st->shift;
|
||||
switch (p) {
|
||||
case 2: ki_bfly2(Fout,fstride,st,m, N, m2); break;
|
||||
case 4: ki_bfly4(Fout,fstride,st,m, N, m2); break;
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
case 3: ki_bfly3(Fout,fstride,st,m, N, m2); break;
|
||||
case 5: ki_bfly5(Fout,fstride,st,m, N, m2); break;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
static
|
||||
void compute_bitrev_table(
|
||||
int Fout,
|
||||
celt_int16 *f,
|
||||
const size_t fstride,
|
||||
int in_stride,
|
||||
celt_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,celt_int16 * facbuf)
|
||||
{
|
||||
int p=4;
|
||||
|
||||
/*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 || (celt_int32)p*(celt_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++ = p;
|
||||
*facbuf++ = n;
|
||||
} while (n > 1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void compute_twiddles(kiss_twiddle_cpx *twiddles, int nfft)
|
||||
{
|
||||
int i;
|
||||
#ifdef FIXED_POINT
|
||||
for (i=0;i<nfft;++i) {
|
||||
celt_word32 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
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
*
|
||||
* User-callable function to allocate all necessary storage space for the fft.
|
||||
*
|
||||
* The return value is a contiguous block of memory, allocated with malloc. As such,
|
||||
* It can be freed with free(), rather than a kiss_fft-specific function.
|
||||
* */
|
||||
kiss_fft_state *kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base)
|
||||
{
|
||||
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) {
|
||||
celt_int16 *bitrev;
|
||||
kiss_twiddle_cpx *twiddles;
|
||||
|
||||
st->nfft=nfft;
|
||||
#ifndef FIXED_POINT
|
||||
st->scale = 1./nfft;
|
||||
#endif
|
||||
if (base != NULL)
|
||||
{
|
||||
st->twiddles = base->twiddles;
|
||||
st->shift = 0;
|
||||
while (nfft<<st->shift != base->nfft && st->shift < 32)
|
||||
st->shift++;
|
||||
/* FIXME: Report error and do proper cleanup */
|
||||
if (st->shift>=32)
|
||||
return NULL;
|
||||
} 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))
|
||||
{
|
||||
kiss_fft_free(st);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* bitrev */
|
||||
st->bitrev = bitrev = (celt_int16*)KISS_FFT_MALLOC(sizeof(celt_int16)*nfft);
|
||||
compute_bitrev_table(0, bitrev, 1,1, st->factors,st);
|
||||
}
|
||||
return st;
|
||||
}
|
||||
|
||||
kiss_fft_state *kiss_fft_alloc(int nfft,void * mem,size_t * lenmem )
|
||||
{
|
||||
return kiss_fft_alloc_twiddles(nfft, mem, lenmem, NULL);
|
||||
}
|
||||
|
||||
void kiss_fft_free(const kiss_fft_state *cfg)
|
||||
{
|
||||
if (cfg)
|
||||
{
|
||||
celt_free((celt_int16*)cfg->bitrev);
|
||||
if (cfg->shift < 0)
|
||||
celt_free((kiss_twiddle_cpx*)cfg->twiddles);
|
||||
celt_free((kiss_fft_state*)cfg);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
static void kiss_fft_stride(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||
{
|
||||
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];
|
||||
#ifndef FIXED_POINT
|
||||
fout[st->bitrev[i]].r *= st->scale;
|
||||
fout[st->bitrev[i]].i *= st->scale;
|
||||
#endif
|
||||
}
|
||||
kf_work( fout, fin, 1,in_stride, st->factors,st, 1, 1);
|
||||
}
|
||||
|
||||
void kiss_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
kiss_fft_stride(cfg,fin,fout,1);
|
||||
}
|
||||
|
||||
static void kiss_ifft_stride(const kiss_fft_state *st,const kiss_fft_cpx *fin,kiss_fft_cpx *fout,int in_stride)
|
||||
{
|
||||
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];
|
||||
ki_work( fout, fin, 1,in_stride, st->factors,st, 1, 1);
|
||||
}
|
||||
|
||||
void kiss_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout)
|
||||
{
|
||||
kiss_ifft_stride(cfg,fin,fout,1);
|
||||
}
|
||||
|
||||
@@ -1,165 +0,0 @@
|
||||
/*
|
||||
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"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
ATTENTION!
|
||||
If you would like a :
|
||||
-- a utility that will handle the caching of fft objects
|
||||
-- real-only (no imaginary time component ) FFT
|
||||
-- a multi-dimensional FFT
|
||||
-- a command-line utility to perform ffts
|
||||
-- a command-line utility to perform fast-convolution filtering
|
||||
|
||||
Then see kfc.h kiss_fftr.h kiss_fftnd.h fftutil.c kiss_fastfir.c
|
||||
in the tools/ directory.
|
||||
*/
|
||||
|
||||
#ifdef USE_SIMD
|
||||
# include <xmmintrin.h>
|
||||
# define kiss_fft_scalar __m128
|
||||
#define KISS_FFT_MALLOC(nbytes) memalign(16,nbytes)
|
||||
#else
|
||||
#define KISS_FFT_MALLOC celt_alloc
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#include "arch.h"
|
||||
#define DOUBLE_PRECISION
|
||||
|
||||
#ifdef DOUBLE_PRECISION
|
||||
# define kiss_fft_scalar celt_int32
|
||||
# define kiss_twiddle_scalar celt_int16
|
||||
# define KF_SUFFIX _celt_double
|
||||
#else
|
||||
# define kiss_fft_scalar celt_int16
|
||||
# define kiss_twiddle_scalar celt_int16
|
||||
# define KF_SUFFIX _celt_single
|
||||
#endif
|
||||
#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
|
||||
|
||||
#if 0
|
||||
/* This adds a suffix to all the kiss_fft functions so we
|
||||
can easily link with more than one copy of the fft */
|
||||
#define CAT_SUFFIX(a,b) a ## b
|
||||
#define SUF(a,b) CAT_SUFFIX(a, b)
|
||||
|
||||
#define kiss_fft_alloc_twiddles SUF(kiss_fft_alloc_twiddles,KF_SUFFIX)
|
||||
#define kiss_fft_alloc SUF(kiss_fft_alloc,KF_SUFFIX)
|
||||
#define kiss_fft SUF(kiss_fft,KF_SUFFIX)
|
||||
#define kiss_ifft SUF(kiss_ifft,KF_SUFFIX)
|
||||
#define kiss_fft_stride SUF(kiss_fft_stride,KF_SUFFIX)
|
||||
#define kiss_ifft_stride SUF(kiss_ifft_stride,KF_SUFFIX)
|
||||
#define kiss_fft_free SUF(kiss_fft_free,KF_SUFFIX)
|
||||
|
||||
#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 kiss_fft_state{
|
||||
int nfft;
|
||||
#ifndef FIXED_POINT
|
||||
kiss_fft_scalar scale;
|
||||
#endif
|
||||
int shift;
|
||||
celt_int16 factors[2*MAXFACTORS];
|
||||
const celt_int16 *bitrev;
|
||||
const kiss_twiddle_cpx *twiddles;
|
||||
} kiss_fft_state;
|
||||
|
||||
//typedef struct kiss_fft_state* kiss_fft_cfg;
|
||||
|
||||
/**
|
||||
* kiss_fft_alloc
|
||||
*
|
||||
* Initialize a FFT (or IFFT) algorithm's cfg/state buffer.
|
||||
*
|
||||
* typical usage: kiss_fft_cfg mycfg=kiss_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 kiss_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 *kiss_fft_alloc_twiddles(int nfft,void * mem,size_t * lenmem, const kiss_fft_state *base);
|
||||
|
||||
kiss_fft_state *kiss_fft_alloc(int nfft,void * mem,size_t * lenmem);
|
||||
|
||||
/**
|
||||
* kiss_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 kiss_fft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
void kiss_ifft(const kiss_fft_state *cfg,const kiss_fft_cpx *fin,kiss_fft_cpx *fout);
|
||||
|
||||
void kiss_fft_free(const kiss_fft_state *cfg);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,134 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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)
|
||||
|
||||
static int ec_laplace_get_freq1(int fs0, int decay)
|
||||
{
|
||||
celt_int32 ft;
|
||||
ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN) - fs0;
|
||||
return ft*(16384-decay)>>15;
|
||||
}
|
||||
|
||||
void ec_laplace_encode(ec_enc *enc, int *value, int 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*(celt_int32)decay)>>15;
|
||||
}
|
||||
/* Everything beyond that has probability LAPLACE_MINP. */
|
||||
if (fs <= 0)
|
||||
{
|
||||
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, int fs, int decay)
|
||||
{
|
||||
int val=0;
|
||||
unsigned fl;
|
||||
int 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)*(celt_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;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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, int 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, int fs, int decay);
|
||||
@@ -1,126 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{245603E3-F580-41A5-9632-B25FE3372CBF}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>libcelt</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup />
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;_DEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>HAVE_CONFIG_H;WIN32;NDEBUG;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>..\msvc;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\msvc\config.h" />
|
||||
<ClInclude Include="arch.h" />
|
||||
<ClInclude Include="bands.h" />
|
||||
<ClInclude Include="celt.h" />
|
||||
<ClInclude Include="celt_header.h" />
|
||||
<ClInclude Include="celt_types.h" />
|
||||
<ClInclude Include="cwrs.h" />
|
||||
<ClInclude Include="ecintrin.h" />
|
||||
<ClInclude Include="entcode.h" />
|
||||
<ClInclude Include="entdec.h" />
|
||||
<ClInclude Include="entenc.h" />
|
||||
<ClInclude Include="fixed_debug.h" />
|
||||
<ClInclude Include="fixed_generic.h" />
|
||||
<ClInclude Include="float_cast.h" />
|
||||
<ClInclude Include="kiss_fft.h" />
|
||||
<ClInclude Include="laplace.h" />
|
||||
<ClInclude Include="mathops.h" />
|
||||
<ClInclude Include="mdct.h" />
|
||||
<ClInclude Include="modes.h" />
|
||||
<ClInclude Include="os_support.h" />
|
||||
<ClInclude Include="pitch.h" />
|
||||
<ClInclude Include="plc.h" />
|
||||
<ClInclude Include="quant_bands.h" />
|
||||
<ClInclude Include="rate.h" />
|
||||
<ClInclude Include="stack_alloc.h" />
|
||||
<ClInclude Include="vq.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bands.c" />
|
||||
<ClCompile Include="celt.c" />
|
||||
<ClCompile Include="cwrs.c" />
|
||||
<ClCompile Include="entcode.c" />
|
||||
<ClCompile Include="entdec.c" />
|
||||
<ClCompile Include="entenc.c" />
|
||||
<ClCompile Include="header.c" />
|
||||
<ClCompile Include="kiss_fft.c" />
|
||||
<ClCompile Include="laplace.c" />
|
||||
<ClCompile Include="mathops.c" />
|
||||
<ClCompile Include="mdct.c" />
|
||||
<ClCompile Include="modes.c" />
|
||||
<ClCompile Include="pitch.c" />
|
||||
<ClCompile Include="plc.c" />
|
||||
<ClCompile Include="quant_bands.c" />
|
||||
<ClCompile Include="rate.c" />
|
||||
<ClCompile Include="vq.c" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
||||
@@ -1,153 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="ReadMe.txt" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="arch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="bands.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="celt.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="celt_header.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="celt_types.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="cwrs.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ecintrin.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="entcode.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="entdec.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="entenc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="fixed_debug.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="fixed_generic.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="float_cast.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kiss_fft.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="laplace.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mathops.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="mdct.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="modes.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="os_support.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="pitch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="plc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="quant_bands.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="rate.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="stack_alloc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="vq.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\msvc\config.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="bands.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="celt.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="cwrs.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="entcode.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="entdec.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="entenc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="header.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="kiss_fft.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="laplace.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mdct.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="modes.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="pitch.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="plc.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="quant_bands.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="rate.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="vq.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="mathops.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
@@ -1,30 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
#outfile=`mktemp`
|
||||
#if [ $? != 0 ]; then
|
||||
# echo "count not create temp output file"
|
||||
# exit 0
|
||||
#fi
|
||||
outfile=/dev/null
|
||||
|
||||
if [ -f mono_test_file.sw ]; then
|
||||
echo -n "mono test... "
|
||||
./testcelt 44100 1 256 32 mono_test_file.sw $outfile
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "no mono test file"
|
||||
fi
|
||||
|
||||
if [ -f stereo_test_file.sw ]; then
|
||||
echo -n "stereo test... "
|
||||
./testcelt 44100 2 256 92 stereo_test_file.sw $outfile
|
||||
if [ $? != 0 ]; then
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "no stereo test file"
|
||||
fi
|
||||
|
||||
exit 0
|
||||
@@ -1,201 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mathops.h"
|
||||
|
||||
/*Compute floor(sqrt(_val)) with exact arithmetic.
|
||||
This has been tested on all possible 32-bit inputs.*/
|
||||
unsigned isqrt32(celt_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{
|
||||
celt_uint32 t;
|
||||
t=((celt_uint32)g<<1)+b<<bshift;
|
||||
if(t<=_val){
|
||||
g+=b;
|
||||
_val-=t;
|
||||
}
|
||||
b>>=1;
|
||||
bshift--;
|
||||
}
|
||||
while(bshift>=0);
|
||||
return g;
|
||||
}
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
|
||||
celt_word32 frac_div32(celt_word32 a, celt_word32 b)
|
||||
{
|
||||
celt_word16 rcp;
|
||||
celt_word32 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 = SHL32(MULT16_32_Q15(rcp, a),2);
|
||||
rem = a-MULT32_32_Q31(result, b);
|
||||
result += SHL32(MULT16_32_Q15(rcp, rem),2);
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Reciprocal sqrt approximation in the range [0.25,1) (Q16 in, Q14 out) */
|
||||
celt_word16 celt_rsqrt_norm(celt_word32 x)
|
||||
{
|
||||
celt_word16 n;
|
||||
celt_word16 r;
|
||||
celt_word16 r2;
|
||||
celt_word16 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) */
|
||||
celt_word32 celt_sqrt(celt_word32 x)
|
||||
{
|
||||
int k;
|
||||
celt_word16 n;
|
||||
celt_word32 rt;
|
||||
static const celt_word16 C[5] = {23175, 11561, -3011, 1699, -664};
|
||||
if (x==0)
|
||||
return 0;
|
||||
k = (celt_ilog2(x)>>1)-7;
|
||||
x = VSHR32(x, (k<<1));
|
||||
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 inline celt_word16 _celt_cos_pi_2(celt_word16 x)
|
||||
{
|
||||
celt_word16 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
|
||||
|
||||
celt_word16 celt_cos_norm(celt_word32 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 NEG32(_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) */
|
||||
celt_word32 celt_rcp(celt_word32 x)
|
||||
{
|
||||
int i;
|
||||
celt_word16 n;
|
||||
celt_word16 r;
|
||||
celt_assert2(x>0, "celt_rcp() only defined for positive values");
|
||||
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
|
||||
@@ -1,234 +0,0 @@
|
||||
/* 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 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 MATHOPS_H
|
||||
#define MATHOPS_H
|
||||
|
||||
#include "arch.h"
|
||||
#include "entcode.h"
|
||||
#include "os_support.h"
|
||||
|
||||
/* Multiplies two 16-bit fractional values. Bit-exactness of this macro is important */
|
||||
#define FRAC_MUL16(a,b) ((16384+((celt_int32)(celt_int16)(a)*(celt_int16)(b)))>>15)
|
||||
|
||||
unsigned isqrt32(celt_uint32 _val);
|
||||
|
||||
#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_acos acos
|
||||
#define celt_exp exp
|
||||
#define celt_cos_norm(x) ((float)cos((.5f*M_PI)*(x)))
|
||||
#define celt_atan atan
|
||||
#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 inline float celt_log2(float x)
|
||||
{
|
||||
int integer;
|
||||
float frac;
|
||||
union {
|
||||
float f;
|
||||
celt_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 inline float celt_exp2(float x)
|
||||
{
|
||||
int integer;
|
||||
float frac;
|
||||
union {
|
||||
float f;
|
||||
celt_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 inline celt_int16 celt_ilog2(celt_int32 x)
|
||||
{
|
||||
celt_assert2(x>0, "celt_ilog2() only defined for strictly positive numbers");
|
||||
return EC_ILOG(x)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef OVERRIDE_CELT_MAXABS16
|
||||
static inline celt_word16 celt_maxabs16(celt_word16 *x, int len)
|
||||
{
|
||||
int i;
|
||||
celt_word16 maxval = 0;
|
||||
for (i=0;i<len;i++)
|
||||
maxval = MAX16(maxval, ABS16(x[i]));
|
||||
return maxval;
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Integer log in base2. Defined for zero, but not for negative numbers */
|
||||
static inline celt_int16 celt_zlog2(celt_word32 x)
|
||||
{
|
||||
return x <= 0 ? 0 : celt_ilog2(x);
|
||||
}
|
||||
|
||||
celt_word16 celt_rsqrt_norm(celt_word32 x);
|
||||
|
||||
celt_word32 celt_sqrt(celt_word32 x);
|
||||
|
||||
celt_word16 celt_cos_norm(celt_word32 x);
|
||||
|
||||
|
||||
static inline celt_word16 celt_log2(celt_word32 x)
|
||||
{
|
||||
int i;
|
||||
celt_word16 n, frac;
|
||||
/* -0.41509302963303146, 0.9609890551383969, -0.31836011537636605,
|
||||
0.15530808010959576, -0.08556153059057618 */
|
||||
static const celt_word16 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
|
||||
/** Base-2 exponential approximation (2^x). (Q10 input, Q16 output) */
|
||||
static inline celt_word32 celt_exp2(celt_word16 x)
|
||||
{
|
||||
int integer;
|
||||
celt_word16 frac;
|
||||
integer = SHR16(x,10);
|
||||
if (integer>14)
|
||||
return 0x7f000000;
|
||||
else if (integer < -15)
|
||||
return 0;
|
||||
frac = SHL16(x-SHL16(integer,10),4);
|
||||
frac = ADD16(D0, MULT16_16_Q15(frac, ADD16(D1, MULT16_16_Q15(frac, ADD16(D2 , MULT16_16_Q15(D3,frac))))));
|
||||
return VSHR32(EXTEND32(frac), -integer-2);
|
||||
}
|
||||
|
||||
celt_word32 celt_rcp(celt_word32 x);
|
||||
|
||||
#define celt_div(a,b) MULT32_32_Q31((celt_word32)(a),celt_rcp(b))
|
||||
|
||||
celt_word32 frac_div32(celt_word32 a, celt_word32 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 inline celt_word16 celt_atan01(celt_word16 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 inline celt_word16 celt_atan2p(celt_word16 y, celt_word16 x)
|
||||
{
|
||||
if (y < x)
|
||||
{
|
||||
celt_word32 arg;
|
||||
arg = celt_div(SHL32(EXTEND32(y),15),x);
|
||||
if (arg >= 32767)
|
||||
arg = 32767;
|
||||
return SHR16(celt_atan01(EXTRACT16(arg)),1);
|
||||
} else {
|
||||
celt_word32 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 */
|
||||
@@ -1,333 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
/* 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"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.141592653
|
||||
#endif
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
|
||||
void clt_mdct_init(mdct_lookup *l,int N, int maxshift)
|
||||
{
|
||||
int i;
|
||||
int N4, N2;
|
||||
kiss_twiddle_scalar *trig;
|
||||
l->n = N;
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
l->maxshift = maxshift;
|
||||
for (i=0;i<=maxshift;i++)
|
||||
{
|
||||
if (i==0)
|
||||
l->kfft[i] = kiss_fft_alloc(N>>2>>i, 0, 0);
|
||||
else
|
||||
l->kfft[i] = kiss_fft_alloc_twiddles(N>>2>>i, 0, 0, l->kfft[0]);
|
||||
#ifndef ENABLE_TI_DSPLIB55
|
||||
if (l->kfft[i]==NULL)
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
l->trig = trig = (kiss_twiddle_scalar*)celt_alloc((N4+1)*sizeof(kiss_twiddle_scalar));
|
||||
if (l->trig==NULL)
|
||||
return;
|
||||
/* We have enough points that sine isn't necessary */
|
||||
#if defined(FIXED_POINT)
|
||||
for (i=0;i<=N4;i++)
|
||||
trig[i] = TRIG_UPSCALE*celt_cos_norm(DIV32(ADD32(SHL32(EXTEND32(i),17),N2),N));
|
||||
#else
|
||||
for (i=0;i<=N4;i++)
|
||||
trig[i] = (kiss_twiddle_scalar)cos(2*M_PI*i/N);
|
||||
#endif
|
||||
}
|
||||
|
||||
void clt_mdct_clear(mdct_lookup *l)
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<=l->maxshift;i++)
|
||||
kiss_fft_free(l->kfft[i]);
|
||||
celt_free((kiss_twiddle_scalar*)l->trig);
|
||||
}
|
||||
|
||||
#endif /* CUSTOM_MODES */
|
||||
|
||||
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * restrict out, const celt_word16 *window, int overlap, int shift)
|
||||
{
|
||||
int i;
|
||||
int N, N2, N4;
|
||||
kiss_twiddle_scalar sine;
|
||||
VARDECL(kiss_fft_scalar, f);
|
||||
SAVE_STACK;
|
||||
N = l->n;
|
||||
N >>= shift;
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
ALLOC(f, N2, kiss_fft_scalar);
|
||||
/* sin(x) ~= x here */
|
||||
#ifdef FIXED_POINT
|
||||
sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N;
|
||||
#else
|
||||
sine = (kiss_twiddle_scalar)2*M_PI*(.125f)/N;
|
||||
#endif
|
||||
|
||||
/* 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 * restrict xp1 = in+(overlap>>1);
|
||||
const kiss_fft_scalar * restrict xp2 = in+N2-1+(overlap>>1);
|
||||
kiss_fft_scalar * restrict yp = out;
|
||||
const celt_word16 * restrict wp1 = window+(overlap>>1);
|
||||
const celt_word16 * restrict wp2 = window+(overlap>>1)-1;
|
||||
for(i=0;i<(overlap>>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>>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 * restrict yp = out;
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar re, im, yr, yi;
|
||||
re = yp[0];
|
||||
im = yp[1];
|
||||
yr = -S_MUL(re,t[i<<shift]) - S_MUL(im,t[(N4-i)<<shift]);
|
||||
yi = -S_MUL(im,t[i<<shift]) + S_MUL(re,t[(N4-i)<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*yp++ = yr + S_MUL(yi,sine);
|
||||
*yp++ = yi - S_MUL(yr,sine);
|
||||
}
|
||||
}
|
||||
|
||||
/* N/4 complex FFT, down-scales by 4/N */
|
||||
kiss_fft(l->kfft[shift], (kiss_fft_cpx *)out, (kiss_fft_cpx *)f);
|
||||
|
||||
/* Post-rotate */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * restrict fp = f;
|
||||
kiss_fft_scalar * restrict yp1 = out;
|
||||
kiss_fft_scalar * restrict yp2 = out+N2-1;
|
||||
const kiss_twiddle_scalar *t = &l->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[1],t[(N4-i)<<shift]) + S_MUL(fp[0],t[i<<shift]);
|
||||
yi = S_MUL(fp[0],t[(N4-i)<<shift]) - S_MUL(fp[1],t[i<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*yp1 = yr - S_MUL(yi,sine);
|
||||
*yp2 = yi + S_MUL(yr,sine);;
|
||||
fp += 2;
|
||||
yp1 += 2;
|
||||
yp2 -= 2;
|
||||
}
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
||||
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar * restrict out, const celt_word16 * restrict window, int overlap, int shift)
|
||||
{
|
||||
int i;
|
||||
int N, N2, N4;
|
||||
kiss_twiddle_scalar sine;
|
||||
VARDECL(kiss_fft_scalar, f);
|
||||
VARDECL(kiss_fft_scalar, f2);
|
||||
SAVE_STACK;
|
||||
N = l->n;
|
||||
N >>= shift;
|
||||
N2 = N>>1;
|
||||
N4 = N>>2;
|
||||
ALLOC(f, N2, kiss_fft_scalar);
|
||||
ALLOC(f2, N2, kiss_fft_scalar);
|
||||
/* sin(x) ~= x here */
|
||||
#ifdef FIXED_POINT
|
||||
sine = TRIG_UPSCALE*(QCONST16(0.7853981f, 15)+N2)/N;
|
||||
#else
|
||||
sine = (kiss_twiddle_scalar)2*M_PI*(.125f)/N;
|
||||
#endif
|
||||
|
||||
/* Pre-rotate */
|
||||
{
|
||||
/* Temp pointers to make it really clear to the compiler what we're doing */
|
||||
const kiss_fft_scalar * restrict xp1 = in;
|
||||
const kiss_fft_scalar * restrict xp2 = in+N2-1;
|
||||
kiss_fft_scalar * restrict yp = f2;
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar yr, yi;
|
||||
yr = -S_MUL(*xp2, t[i<<shift]) + S_MUL(*xp1,t[(N4-i)<<shift]);
|
||||
yi = -S_MUL(*xp2, t[(N4-i)<<shift]) - S_MUL(*xp1,t[i<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*yp++ = yr - S_MUL(yi,sine);
|
||||
*yp++ = yi + S_MUL(yr,sine);
|
||||
xp1+=2;
|
||||
xp2-=2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Inverse N/4 complex FFT. This one should *not* downscale even in fixed-point */
|
||||
kiss_ifft(l->kfft[shift], (kiss_fft_cpx *)f2, (kiss_fft_cpx *)f);
|
||||
|
||||
/* Post-rotate */
|
||||
{
|
||||
kiss_fft_scalar * restrict fp = f;
|
||||
const kiss_twiddle_scalar *t = &l->trig[0];
|
||||
|
||||
for(i=0;i<N4;i++)
|
||||
{
|
||||
kiss_fft_scalar re, im, yr, yi;
|
||||
re = fp[0];
|
||||
im = fp[1];
|
||||
/* We'd scale up by 2 here, but instead it's done when mixing the windows */
|
||||
yr = S_MUL(re,t[i<<shift]) - S_MUL(im,t[(N4-i)<<shift]);
|
||||
yi = S_MUL(im,t[i<<shift]) + S_MUL(re,t[(N4-i)<<shift]);
|
||||
/* works because the cos is nearly one */
|
||||
*fp++ = yr - S_MUL(yi,sine);
|
||||
*fp++ = yi + S_MUL(yr,sine);
|
||||
}
|
||||
}
|
||||
/* De-shuffle the components for the middle of the window only */
|
||||
{
|
||||
const kiss_fft_scalar * restrict fp1 = f;
|
||||
const kiss_fft_scalar * restrict fp2 = f+N2-1;
|
||||
kiss_fft_scalar * restrict yp = f2;
|
||||
for(i = 0; i < N4; i++)
|
||||
{
|
||||
*yp++ =-*fp1;
|
||||
*yp++ = *fp2;
|
||||
fp1 += 2;
|
||||
fp2 -= 2;
|
||||
}
|
||||
}
|
||||
out -= (N2-overlap)>>1;
|
||||
/* Mirror on both sides for TDAC */
|
||||
{
|
||||
kiss_fft_scalar * restrict fp1 = f2+N4-1;
|
||||
kiss_fft_scalar * restrict xp1 = out+N2-1;
|
||||
kiss_fft_scalar * restrict yp1 = out+N4-overlap/2;
|
||||
const celt_word16 * restrict wp1 = window;
|
||||
const celt_word16 * restrict wp2 = window+overlap-1;
|
||||
for(i = 0; i< N4-overlap/2; i++)
|
||||
{
|
||||
*xp1 = *fp1;
|
||||
xp1--;
|
||||
fp1--;
|
||||
}
|
||||
for(; i < N4; i++)
|
||||
{
|
||||
kiss_fft_scalar x1;
|
||||
x1 = *fp1--;
|
||||
*yp1++ +=-MULT16_32_Q15(*wp1, x1);
|
||||
*xp1-- += MULT16_32_Q15(*wp2, x1);
|
||||
wp1++;
|
||||
wp2--;
|
||||
}
|
||||
}
|
||||
{
|
||||
kiss_fft_scalar * restrict fp2 = f2+N4;
|
||||
kiss_fft_scalar * restrict xp2 = out+N2;
|
||||
kiss_fft_scalar * restrict yp2 = out+N-1-(N4-overlap/2);
|
||||
const celt_word16 * restrict wp1 = window;
|
||||
const celt_word16 * restrict wp2 = window+overlap-1;
|
||||
for(i = 0; i< N4-overlap/2; i++)
|
||||
{
|
||||
*xp2 = *fp2;
|
||||
xp2++;
|
||||
fp2++;
|
||||
}
|
||||
for(; i < N4; i++)
|
||||
{
|
||||
kiss_fft_scalar x2;
|
||||
x2 = *fp2++;
|
||||
*yp2-- = MULT16_32_Q15(*wp1, x2);
|
||||
*xp2++ = MULT16_32_Q15(*wp2, x2);
|
||||
wp1++;
|
||||
wp2--;
|
||||
}
|
||||
}
|
||||
RESTORE_STACK;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,65 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
/* 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 "kiss_fft.h"
|
||||
#include "arch.h"
|
||||
|
||||
typedef struct {
|
||||
int n;
|
||||
int maxshift;
|
||||
const kiss_fft_state *kfft[4];
|
||||
const kiss_twiddle_scalar * restrict trig;
|
||||
} mdct_lookup;
|
||||
|
||||
void clt_mdct_init(mdct_lookup *l,int N, int maxshift);
|
||||
void clt_mdct_clear(mdct_lookup *l);
|
||||
|
||||
/** Compute a forward MDCT and scale by 4/N */
|
||||
void clt_mdct_forward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const celt_word16 *window, int overlap, int shift);
|
||||
|
||||
/** Compute a backward MDCT (no scaling) and performs weighted overlap-add
|
||||
(scales implicitly by 1/2) */
|
||||
void clt_mdct_backward(const mdct_lookup *l, kiss_fft_scalar *in, kiss_fft_scalar *out, const celt_word16 * restrict window, int overlap, int shift);
|
||||
|
||||
#endif
|
||||
@@ -1,56 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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 (((celt_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)
|
||||
/*Code for which propagating carries are possible.*/
|
||||
# define EC_CODE_CARRY (((celt_uint32)EC_SYM_MAX)<<EC_CODE_SHIFT)
|
||||
/*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)
|
||||
/*A mask for the bits available in the coding buffer.
|
||||
This allows different platforms to use a variable with more bits, if it is
|
||||
convenient.
|
||||
We will only use EC_CODE_BITS of it.*/
|
||||
# define EC_CODE_MASK ((((celt_uint32)1U)<<EC_CODE_BITS-1)-1<<1|1)
|
||||
|
||||
#endif
|
||||
@@ -1,433 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
static const celt_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.c"
|
||||
#else
|
||||
#include "static_modes_float.c"
|
||||
#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 celt_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 celt_int16 *compute_ebands(celt_int32 Fs, int frame_size, int res, int *nbEBands)
|
||||
{
|
||||
celt_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*(celt_int32)frame_size)
|
||||
{
|
||||
*nbEBands = sizeof(eband5ms)/sizeof(eband5ms[0])-1;
|
||||
eBands = celt_alloc(sizeof(celt_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 = celt_alloc(sizeof(celt_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 = celt_alloc(sizeof(unsigned char)*(BITALLOC_SIZE*mode->nbEBands));
|
||||
if (allocVectors==NULL)
|
||||
return;
|
||||
|
||||
/* Check for standard mode */
|
||||
if (mode->Fs == 400*(celt_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*(celt_int32)eband5ms[k] > mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize)
|
||||
break;
|
||||
}
|
||||
if (k>maxBands-1)
|
||||
allocVectors[i*mode->nbEBands+j] = band_allocation[i*maxBands + maxBands-1];
|
||||
else {
|
||||
celt_int32 a0, a1;
|
||||
a1 = mode->eBands[j]*(celt_int32)mode->Fs/mode->shortMdctSize - 400*(celt_int32)eband5ms[k-1];
|
||||
a0 = 400*(celt_int32)eband5ms[k] - mode->eBands[j]*(celt_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 *celt_mode_create(celt_int32 Fs, int frame_size, int *error)
|
||||
{
|
||||
int i;
|
||||
#ifdef CUSTOM_MODES
|
||||
CELTMode *mode=NULL;
|
||||
int res;
|
||||
celt_word16 *window;
|
||||
celt_int16 *logN;
|
||||
int LM;
|
||||
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 = CELT_OK;
|
||||
return (CELTMode*)static_mode_list[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* CUSTOM_MODES_ONLY */
|
||||
|
||||
#ifndef CUSTOM_MODES
|
||||
if (error)
|
||||
*error = CELT_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 = CELT_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
if (frame_size < 40 || frame_size > 1024 || frame_size%2!=0)
|
||||
{
|
||||
if (error)
|
||||
*error = CELT_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
/* Frames of less than 1ms are not supported. */
|
||||
if ((celt_int32)frame_size*1000 < Fs)
|
||||
{
|
||||
if (error)
|
||||
*error = CELT_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if ((celt_int32)frame_size*75 >= Fs && (frame_size%16)==0)
|
||||
{
|
||||
LM = 3;
|
||||
} else if ((celt_int32)frame_size*150 >= Fs && (frame_size%8)==0)
|
||||
{
|
||||
LM = 2;
|
||||
} else if ((celt_int32)frame_size*300 >= Fs && (frame_size%4)==0)
|
||||
{
|
||||
LM = 1;
|
||||
} else
|
||||
{
|
||||
LM = 0;
|
||||
}
|
||||
|
||||
/* Shorts longer than 3.3ms are not supported. */
|
||||
if ((celt_int32)(frame_size>>LM)*300 > Fs)
|
||||
{
|
||||
if (error)
|
||||
*error = CELT_BAD_ARG;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mode = celt_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;
|
||||
|
||||
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 = (celt_word16*)celt_alloc(mode->overlap*sizeof(celt_word16));
|
||||
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 = (celt_int16*)celt_alloc(mode->nbEBands*sizeof(celt_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);
|
||||
|
||||
clt_mdct_init(&mode->mdct, 2*mode->shortMdctSize*mode->nbShortMdcts, mode->maxLM);
|
||||
if ((mode->mdct.trig==NULL)
|
||||
#ifndef ENABLE_TI_DSPLIB55
|
||||
|| (mode->mdct.kfft==NULL)
|
||||
#endif
|
||||
)
|
||||
goto failure;
|
||||
|
||||
if (error)
|
||||
*error = CELT_OK;
|
||||
|
||||
return mode;
|
||||
failure:
|
||||
if (error)
|
||||
*error = CELT_ALLOC_FAIL;
|
||||
if (mode!=NULL)
|
||||
celt_mode_destroy(mode);
|
||||
return NULL;
|
||||
#endif /* !CUSTOM_MODES */
|
||||
}
|
||||
|
||||
void celt_mode_destroy(CELTMode *mode)
|
||||
{
|
||||
#ifdef CUSTOM_MODES
|
||||
int i;
|
||||
if (mode == NULL)
|
||||
return;
|
||||
#ifndef CUSTOM_MODES_ONLY
|
||||
for (i=0;i<TOTAL_MODES;i++)
|
||||
{
|
||||
if (mode == static_mode_list[i])
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
#endif /* CUSTOM_MODES_ONLY */
|
||||
celt_free((celt_int16*)mode->eBands);
|
||||
celt_free((celt_int16*)mode->allocVectors);
|
||||
|
||||
celt_free((celt_word16*)mode->window);
|
||||
celt_free((celt_int16*)mode->logN);
|
||||
|
||||
celt_free((celt_int16*)mode->cache.index);
|
||||
celt_free((unsigned char*)mode->cache.bits);
|
||||
celt_free((unsigned char*)mode->cache.caps);
|
||||
clt_mdct_clear(&mode->mdct);
|
||||
|
||||
celt_free((CELTMode *)mode);
|
||||
#endif
|
||||
}
|
||||
@@ -1,117 +0,0 @@
|
||||
/* 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 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 MODES_H
|
||||
#define MODES_H
|
||||
|
||||
#include "celt_types.h"
|
||||
#include "celt.h"
|
||||
#include "arch.h"
|
||||
#include "mdct.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
|
||||
#define CELT_BITSTREAM_VERSION 0x80000010
|
||||
|
||||
#define MAX_PERIOD 1024
|
||||
|
||||
#ifndef CHANNELS
|
||||
# ifdef DISABLE_STEREO
|
||||
# define CHANNELS(_C) (1)
|
||||
# else
|
||||
# define CHANNELS(_C) (_C)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#ifndef OVERLAP
|
||||
#define OVERLAP(mode) ((mode)->overlap)
|
||||
#endif
|
||||
|
||||
#ifndef FRAMESIZE
|
||||
#define FRAMESIZE(mode) ((mode)->mdctSize)
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
int size;
|
||||
const celt_int16 *index;
|
||||
const unsigned char *bits;
|
||||
const unsigned char *caps;
|
||||
} PulseCache;
|
||||
|
||||
/** Mode definition (opaque)
|
||||
@brief Mode definition
|
||||
*/
|
||||
struct CELTMode {
|
||||
celt_int32 Fs;
|
||||
int overlap;
|
||||
|
||||
int nbEBands;
|
||||
int effEBands;
|
||||
celt_word16 preemph[4];
|
||||
const celt_int16 *eBands; /**< Definition for each "pseudo-critical band" */
|
||||
|
||||
int nbAllocVectors; /**< Number of lines in the matrix below */
|
||||
const unsigned char *allocVectors; /**< Number of bits in each band for several rates */
|
||||
|
||||
/* Stuff that could go in the {en,de}coder, but we save space this way */
|
||||
mdct_lookup mdct;
|
||||
|
||||
const celt_word16 *window;
|
||||
|
||||
int maxLM;
|
||||
int nbShortMdcts;
|
||||
int shortMdctSize;
|
||||
|
||||
const celt_int16 *logN;
|
||||
|
||||
PulseCache cache;
|
||||
};
|
||||
|
||||
#ifndef OPUS_BUILD
|
||||
#define CELT_STATIC static
|
||||
#else
|
||||
#define CELT_STATIC
|
||||
#endif
|
||||
|
||||
#ifdef OPUS_BUILD
|
||||
#define CELT_SET_SIGNALLING_REQUEST 10003
|
||||
#define CELT_SET_SIGNALLING(x) CELT_SET_SIGNALLING_REQUEST, _celt_check_int(x)
|
||||
|
||||
#define CELT_GET_MODE_REQUEST 10004
|
||||
/** Get the CELTMode used by an encoder or decoder */
|
||||
#define CELT_GET_MODE(x) CELT_GET_MODE_REQUEST, _celt_check_mode_ptr_ptr(x)
|
||||
|
||||
/* Prototypes for _ec versions of the encoder/decoder calls (not public) */
|
||||
int celt_encode_with_ec(CELTEncoder * restrict st, const celt_int16 * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
|
||||
int celt_encode_with_ec_float(CELTEncoder * restrict st, const float * pcm, int frame_size, unsigned char *compressed, int nbCompressedBytes, ec_enc *enc);
|
||||
int celt_decode_with_ec(CELTDecoder * restrict st, const unsigned char *data, int len, celt_int16 * restrict pcm, int frame_size, ec_dec *dec);
|
||||
int celt_decode_with_ec_float(CELTDecoder * restrict st, const unsigned char *data, int len, float * restrict pcm, int frame_size, ec_dec *dec);
|
||||
#endif /* OPUS_BUILD */
|
||||
|
||||
#endif
|
||||
@@ -1,101 +0,0 @@
|
||||
/* 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 <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
/** CELT wrapper for calloc(). To do your own dynamic allocation, all you need to do is replace this function, celt_realloc and celt_free
|
||||
NOTE: celt_alloc needs to CLEAR THE MEMORY */
|
||||
#ifndef OVERRIDE_CELT_ALLOC
|
||||
static inline void *celt_alloc (int size)
|
||||
{
|
||||
/* WARNING: this is not equivalent to malloc(). If you want to use malloc()
|
||||
or your own allocator, YOU NEED TO CLEAR THE MEMORY ALLOCATED. Otherwise
|
||||
you will experience strange bugs */
|
||||
return calloc(size,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Same as celt_alloc(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */
|
||||
#ifndef OVERRIDE_CELT_ALLOC_SCRATCH
|
||||
static inline void *celt_alloc_scratch (int size)
|
||||
{
|
||||
/* Scratch space doesn't need to be cleared */
|
||||
return calloc(size,1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** CELT wrapper for free(). To do your own dynamic allocation, all you need to do is replace this function, celt_realloc and celt_alloc */
|
||||
#ifndef OVERRIDE_CELT_FREE
|
||||
static inline void celt_free (void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Same as celt_free(), except that the area is only needed inside a CELT call (might cause problem with wideband though) */
|
||||
#ifndef OVERRIDE_CELT_FREE_SCRATCH
|
||||
static inline void celt_free_scratch (void *ptr)
|
||||
{
|
||||
free(ptr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/** Copy n bytes of memory from src to dst. The 0* term provides compile-time type checking */
|
||||
#ifndef OVERRIDE_CELT_COPY
|
||||
#define CELT_COPY(dst, src, n) (memcpy((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
|
||||
#endif
|
||||
|
||||
/** Copy n bytes of memory from src to dst, allowing overlapping regions. The 0* term
|
||||
provides compile-time type checking */
|
||||
#ifndef OVERRIDE_CELT_MOVE
|
||||
#define CELT_MOVE(dst, src, n) (memmove((dst), (src), (n)*sizeof(*(dst)) + 0*((dst)-(src)) ))
|
||||
#endif
|
||||
|
||||
/** Set n bytes of memory to value of c, starting at address s */
|
||||
#ifndef OVERRIDE_CELT_MEMSET
|
||||
#define CELT_MEMSET(dst, c, n) (memset((dst), (c), (n)*sizeof(*(dst))))
|
||||
#endif
|
||||
|
||||
/*#ifdef __GNUC__
|
||||
#pragma GCC poison printf sprintf
|
||||
#pragma GCC poison malloc free realloc calloc
|
||||
#endif*/
|
||||
|
||||
#endif /* OS_SUPPORT_H */
|
||||
|
||||
@@ -1,373 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
/* Always enable postfilter for Opus */
|
||||
#if defined(OPUS_BUILD) && !defined(ENABLE_POSTFILTER)
|
||||
#define ENABLE_POSTFILTER
|
||||
#endif
|
||||
|
||||
#include "pitch.h"
|
||||
#include "os_support.h"
|
||||
#include "modes.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "mathops.h"
|
||||
|
||||
static void find_best_pitch(celt_word32 *xcorr, celt_word32 maxcorr, celt_word16 *y,
|
||||
int yshift, int len, int max_pitch, int best_pitch[2])
|
||||
{
|
||||
int i, j;
|
||||
celt_word32 Syy=1;
|
||||
celt_word16 best_num[2];
|
||||
celt_word32 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 = MAC16_16(Syy, y[j],y[j]);
|
||||
for (i=0;i<max_pitch;i++)
|
||||
{
|
||||
if (xcorr[i]>0)
|
||||
{
|
||||
celt_word16 num;
|
||||
celt_word32 xcorr16;
|
||||
xcorr16 = EXTRACT16(VSHR32(xcorr[i], xshift));
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
#include "plc.h"
|
||||
void pitch_downsample(celt_sig * restrict x[], celt_word16 * restrict x_lp,
|
||||
int len, int _C)
|
||||
{
|
||||
int i;
|
||||
celt_word32 ac[5];
|
||||
celt_word16 tmp=Q15ONE;
|
||||
celt_word16 lpc[4], mem[4]={0,0,0,0};
|
||||
const int C = CHANNELS(_C);
|
||||
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]), SIG_SHIFT+3);
|
||||
x_lp[0] = SHR32(HALF32(HALF32(x[0][1])+x[0][0]), SIG_SHIFT+3);
|
||||
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]), SIG_SHIFT+3);
|
||||
x_lp[0] += SHR32(HALF32(HALF32(x[1][1])+x[1][0]), SIG_SHIFT+3);
|
||||
}
|
||||
|
||||
_celt_autocorr(x_lp, ac, NULL, 0,
|
||||
4, len>>1);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
fir(x_lp, lpc, x_lp, len>>1, 4, mem);
|
||||
|
||||
mem[0]=0;
|
||||
lpc[0]=QCONST16(.8f,12);
|
||||
fir(x_lp, lpc, x_lp, len>>1, 1, mem);
|
||||
|
||||
}
|
||||
|
||||
void pitch_search(const celt_word16 * restrict x_lp, celt_word16 * restrict y,
|
||||
int len, int max_pitch, int *pitch)
|
||||
{
|
||||
int i, j;
|
||||
int lag;
|
||||
int best_pitch[2]={0};
|
||||
VARDECL(celt_word16, x_lp4);
|
||||
VARDECL(celt_word16, y_lp4);
|
||||
VARDECL(celt_word32, xcorr);
|
||||
celt_word32 maxcorr=1;
|
||||
int offset;
|
||||
int shift=0;
|
||||
|
||||
SAVE_STACK;
|
||||
|
||||
lag = len+max_pitch;
|
||||
|
||||
ALLOC(x_lp4, len>>2, celt_word16);
|
||||
ALLOC(y_lp4, lag>>2, celt_word16);
|
||||
ALLOC(xcorr, max_pitch>>1, celt_word32);
|
||||
|
||||
/* 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
|
||||
shift = celt_ilog2(MAX16(1, MAX16(celt_maxabs16(x_lp4, len>>2), celt_maxabs16(y_lp4, lag>>2))))-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 */
|
||||
|
||||
for (i=0;i<max_pitch>>2;i++)
|
||||
{
|
||||
celt_word32 sum = 0;
|
||||
for (j=0;j<len>>2;j++)
|
||||
sum = MAC16_16(sum, x_lp4[j],y_lp4[i+j]);
|
||||
xcorr[i] = MAX32(-1, sum);
|
||||
maxcorr = MAX32(maxcorr, sum);
|
||||
}
|
||||
find_best_pitch(xcorr, maxcorr, y_lp4, 0, len>>2, max_pitch>>2, best_pitch);
|
||||
|
||||
/* Finer search with 2x decimation */
|
||||
maxcorr=1;
|
||||
for (i=0;i<max_pitch>>1;i++)
|
||||
{
|
||||
celt_word32 sum=0;
|
||||
xcorr[i] = 0;
|
||||
if (abs(i-2*best_pitch[0])>2 && abs(i-2*best_pitch[1])>2)
|
||||
continue;
|
||||
for (j=0;j<len>>1;j++)
|
||||
sum += SHR32(MULT16_16(x_lp[j],y[i+j]), shift);
|
||||
xcorr[i] = MAX32(-1, sum);
|
||||
maxcorr = MAX32(maxcorr, sum);
|
||||
}
|
||||
find_best_pitch(xcorr, maxcorr, y, shift, len>>1, max_pitch>>1, best_pitch);
|
||||
|
||||
/* Refine by pseudo-interpolation */
|
||||
if (best_pitch[0]>0 && best_pitch[0]<(max_pitch>>1)-1)
|
||||
{
|
||||
celt_word32 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 ENABLE_POSTFILTER
|
||||
static const int second_check[16] = {0, 0, 3, 2, 3, 2, 5, 2, 3, 2, 3, 2, 5, 2, 3, 2};
|
||||
celt_word16 remove_doubling(celt_word16 *x, int maxperiod, int minperiod,
|
||||
int N, int *_T0, int prev_period, celt_word16 prev_gain)
|
||||
{
|
||||
int k, i, T, T0;
|
||||
celt_word16 g, g0;
|
||||
celt_word16 pg;
|
||||
celt_word32 xy,xx,yy;
|
||||
celt_word32 xcorr[3];
|
||||
celt_word32 best_xy, best_yy;
|
||||
int offset;
|
||||
int minperiod0;
|
||||
|
||||
minperiod0 = minperiod;
|
||||
maxperiod /= 2;
|
||||
minperiod /= 2;
|
||||
*_T0 /= 2;
|
||||
prev_period /= 2;
|
||||
N /= 2;
|
||||
x += maxperiod;
|
||||
if (*_T0>=maxperiod)
|
||||
*_T0=maxperiod-1;
|
||||
|
||||
T = T0 = *_T0;
|
||||
xx=xy=yy=0;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
xy = MAC16_16(xy, x[i], x[i-T0]);
|
||||
xx = MAC16_16(xx, x[i], x[i]);
|
||||
yy = MAC16_16(yy, x[i-T0],x[i-T0]);
|
||||
}
|
||||
best_xy = xy;
|
||||
best_yy = yy;
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
celt_word32 x2y2;
|
||||
int sh, t;
|
||||
x2y2 = 1+HALF32(MULT32_32_Q31(xx,yy));
|
||||
sh = celt_ilog2(x2y2)>>1;
|
||||
t = VSHR32(x2y2, 2*(sh-7));
|
||||
g = g0 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
|
||||
}
|
||||
#else
|
||||
g = g0 = xy/sqrt(1+xx*yy);
|
||||
#endif
|
||||
/* Look for any pitch at T/k */
|
||||
for (k=2;k<=15;k++)
|
||||
{
|
||||
int T1, T1b;
|
||||
celt_word16 g1;
|
||||
celt_word16 cont=0;
|
||||
T1 = (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 = (2*second_check[k]*T0+k)/(2*k);
|
||||
}
|
||||
xy=yy=0;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
xy = MAC16_16(xy, x[i], x[i-T1]);
|
||||
yy = MAC16_16(yy, x[i-T1], x[i-T1]);
|
||||
|
||||
xy = MAC16_16(xy, x[i], x[i-T1b]);
|
||||
yy = MAC16_16(yy, x[i-T1b], x[i-T1b]);
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
celt_word32 x2y2;
|
||||
int sh, t;
|
||||
x2y2 = 1+MULT32_32_Q31(xx,yy);
|
||||
sh = celt_ilog2(x2y2)>>1;
|
||||
t = VSHR32(x2y2, 2*(sh-7));
|
||||
g1 = VSHR32(MULT16_32_Q15(celt_rsqrt_norm(t), xy),sh+1);
|
||||
}
|
||||
#else
|
||||
g1 = xy/sqrt(1+2.f*xx*1.f*yy);
|
||||
#endif
|
||||
if (abs(T1-prev_period)<=1)
|
||||
cont = prev_gain;
|
||||
else if (abs(T1-prev_period)<=2 && 5*k*k < T0)
|
||||
cont = HALF32(prev_gain);
|
||||
else
|
||||
cont = 0;
|
||||
if (g1 > QCONST16(.3f,15) + MULT16_16_Q15(QCONST16(.4f,15),g0)-cont)
|
||||
{
|
||||
best_xy = xy;
|
||||
best_yy = yy;
|
||||
T = T1;
|
||||
g = g1;
|
||||
}
|
||||
}
|
||||
if (best_yy <= best_xy)
|
||||
pg = Q15ONE;
|
||||
else
|
||||
pg = SHR32(frac_div32(best_xy,best_yy+1),16);
|
||||
|
||||
for (k=0;k<3;k++)
|
||||
{
|
||||
int T1 = T+k-1;
|
||||
xy = 0;
|
||||
for (i=0;i<N;i++)
|
||||
xy = MAC16_16(xy, x[i], x[i-T1]);
|
||||
xcorr[k] = xy;
|
||||
}
|
||||
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;
|
||||
return pg;
|
||||
}
|
||||
|
||||
#endif /* ENABLE_POSTFILTER */
|
||||
@@ -1,49 +0,0 @@
|
||||
/* 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 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 _PITCH_H
|
||||
#define _PITCH_H
|
||||
|
||||
#include "modes.h"
|
||||
|
||||
void pitch_downsample(celt_sig * restrict x[], celt_word16 * restrict x_lp,
|
||||
int len, int _C);
|
||||
|
||||
void pitch_search(const celt_word16 * restrict x_lp, celt_word16 * restrict y,
|
||||
int len, int max_pitch, int *pitch);
|
||||
|
||||
celt_word16 remove_doubling(celt_word16 *x, int maxperiod, int minperiod,
|
||||
int N, int *T0, int prev_period, celt_word16 prev_gain);
|
||||
|
||||
#endif
|
||||
@@ -1,189 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "plc.h"
|
||||
#include "stack_alloc.h"
|
||||
#include "mathops.h"
|
||||
|
||||
|
||||
|
||||
|
||||
void _celt_lpc(
|
||||
celt_word16 *_lpc, /* out: [0...p-1] LPC coefficients */
|
||||
const celt_word32 *ac, /* in: [0...p] autocorrelation values */
|
||||
int p
|
||||
)
|
||||
{
|
||||
int i, j;
|
||||
celt_word32 r;
|
||||
celt_word32 error = ac[0];
|
||||
#ifdef FIXED_POINT
|
||||
celt_word32 lpc[LPC_ORDER];
|
||||
#else
|
||||
float *lpc = _lpc;
|
||||
#endif
|
||||
|
||||
for (i = 0; i < p; i++)
|
||||
lpc[i] = 0;
|
||||
if (ac[0] != 0)
|
||||
{
|
||||
for (i = 0; i < p; i++) {
|
||||
/* Sum up this iteration's reflection coefficient */
|
||||
celt_word32 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++)
|
||||
{
|
||||
celt_word32 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 fir(const celt_word16 *x,
|
||||
const celt_word16 *num,
|
||||
celt_word16 *y,
|
||||
int N,
|
||||
int ord,
|
||||
celt_word16 *mem)
|
||||
{
|
||||
int i,j;
|
||||
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
celt_word32 sum = SHL32(EXTEND32(x[i]), SIG_SHIFT);
|
||||
for (j=0;j<ord;j++)
|
||||
{
|
||||
sum += MULT16_16(num[j],mem[j]);
|
||||
}
|
||||
for (j=ord-1;j>=1;j--)
|
||||
{
|
||||
mem[j]=mem[j-1];
|
||||
}
|
||||
mem[0] = x[i];
|
||||
y[i] = ROUND16(sum, SIG_SHIFT);
|
||||
}
|
||||
}
|
||||
|
||||
void iir(const celt_word32 *x,
|
||||
const celt_word16 *den,
|
||||
celt_word32 *y,
|
||||
int N,
|
||||
int ord,
|
||||
celt_word16 *mem)
|
||||
{
|
||||
int i,j;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
celt_word32 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] = ROUND16(sum,SIG_SHIFT);
|
||||
y[i] = sum;
|
||||
}
|
||||
}
|
||||
|
||||
void _celt_autocorr(
|
||||
const celt_word16 *x, /* in: [0...n-1] samples x */
|
||||
celt_word32 *ac, /* out: [0...lag-1] ac values */
|
||||
const celt_word16 *window,
|
||||
int overlap,
|
||||
int lag,
|
||||
int n
|
||||
)
|
||||
{
|
||||
celt_word32 d;
|
||||
int i;
|
||||
VARDECL(celt_word16, xx);
|
||||
SAVE_STACK;
|
||||
ALLOC(xx, n, celt_word16);
|
||||
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]);
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
{
|
||||
celt_word32 ac0=0;
|
||||
int shift;
|
||||
for(i=0;i<n;i++)
|
||||
ac0 += SHR32(MULT16_16(xx[i],xx[i]),8);
|
||||
ac0 += 1+n;
|
||||
|
||||
shift = celt_ilog2(ac0)-30+9;
|
||||
shift = (shift+1)/2;
|
||||
for(i=0;i<n;i++)
|
||||
xx[i] = VSHR32(xx[i], shift);
|
||||
}
|
||||
#endif
|
||||
while (lag>=0)
|
||||
{
|
||||
for (i = lag, d = 0; i < n; i++)
|
||||
d += xx[i] * xx[i-lag];
|
||||
ac[lag] = d;
|
||||
/*printf ("%f ", ac[lag]);*/
|
||||
lag--;
|
||||
}
|
||||
/*printf ("\n");*/
|
||||
ac[0] += 10;
|
||||
|
||||
RESTORE_STACK;
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
/* 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 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 PLC_H
|
||||
#define PLC_H
|
||||
|
||||
#include "arch.h"
|
||||
|
||||
#define LPC_ORDER 24
|
||||
|
||||
void _celt_lpc(celt_word16 *_lpc, const celt_word32 *ac, int p);
|
||||
|
||||
void fir(const celt_word16 *x,
|
||||
const celt_word16 *num,
|
||||
celt_word16 *y,
|
||||
int N,
|
||||
int ord,
|
||||
celt_word16 *mem);
|
||||
|
||||
void iir(const celt_word32 *x,
|
||||
const celt_word16 *den,
|
||||
celt_word32 *y,
|
||||
int N,
|
||||
int ord,
|
||||
celt_word16 *mem);
|
||||
|
||||
|
||||
void _celt_autocorr(const celt_word16 *x, celt_word32 *ac, const celt_word16 *window, int overlap, int lag, int n);
|
||||
|
||||
|
||||
#endif /* PLC_H */
|
||||
@@ -1,574 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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 Q6 */
|
||||
static 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 Q6 and converted back to float */
|
||||
static const celt_word16 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 celt_word16 pred_coef[4] = {29440, 26112, 21248, 16384};
|
||||
static const celt_word16 beta_coef[4] = {30147, 22282, 12124, 6554};
|
||||
static const celt_word16 beta_intra = 4915;
|
||||
#else
|
||||
static const celt_word16 pred_coef[4] = {29440/32768., 26112/32768., 21248/32768., 16384/32768.};
|
||||
static const celt_word16 beta_coef[4] = {30147/32768., 22282/32768., 12124/32768., 6554/32768.};
|
||||
static const celt_word16 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 celt_word32 loss_distortion(const celt_word16 *eBands, celt_word16 *oldEBands, int start, int end, int len, int C)
|
||||
{
|
||||
int c, i;
|
||||
celt_word32 dist = 0;
|
||||
c=0; do {
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
celt_word16 d = SHR16(SUB16(eBands[i+c*len], oldEBands[i+c*len]),2);
|
||||
dist = MAC16_16(dist, d,d);
|
||||
}
|
||||
} while (++c<C);
|
||||
return MIN32(200,SHR32(dist,2*DB_SHIFT-4));
|
||||
}
|
||||
|
||||
static int quant_coarse_energy_impl(const CELTMode *m, int start, int end,
|
||||
const celt_word16 *eBands, celt_word16 *oldEBands,
|
||||
celt_int32 budget, celt_int32 tell,
|
||||
const unsigned char *prob_model, celt_word16 *error, ec_enc *enc,
|
||||
int _C, int LM, int intra, celt_word16 max_decay)
|
||||
{
|
||||
const int C = CHANNELS(_C);
|
||||
int i, c;
|
||||
int badness = 0;
|
||||
celt_word32 prev[2] = {0,0};
|
||||
celt_word16 coef;
|
||||
celt_word16 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;
|
||||
celt_word32 q;
|
||||
celt_word16 x;
|
||||
celt_word32 f, tmp;
|
||||
celt_word16 oldE;
|
||||
celt_word16 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((celt_word32)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 (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 = 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 badness;
|
||||
}
|
||||
|
||||
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
|
||||
const celt_word16 *eBands, celt_word16 *oldEBands, celt_uint32 budget,
|
||||
celt_word16 *error, ec_enc *enc, int _C, int LM, int nbAvailableBytes,
|
||||
int force_intra, celt_word32 *delayedIntra, int two_pass, int loss_rate)
|
||||
{
|
||||
const int C = CHANNELS(_C);
|
||||
int intra;
|
||||
celt_word16 max_decay;
|
||||
VARDECL(celt_word16, oldEBands_intra);
|
||||
VARDECL(celt_word16, error_intra);
|
||||
ec_enc enc_start_state;
|
||||
celt_uint32 tell;
|
||||
int badness1=0;
|
||||
celt_int32 intra_bias;
|
||||
celt_word32 new_distortion;
|
||||
SAVE_STACK;
|
||||
|
||||
intra = force_intra || (!two_pass && *delayedIntra>2*C*(end-start) && nbAvailableBytes > (end-start)*C);
|
||||
intra_bias = ((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;
|
||||
|
||||
/* Encode the global flags using a simple probability model
|
||||
(first symbols in the stream) */
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
max_decay = MIN32(QCONST16(16.f,DB_SHIFT), SHL32(EXTEND32(nbAvailableBytes),DB_SHIFT-3));
|
||||
#else
|
||||
max_decay = MIN32(16.f, .125f*nbAvailableBytes);
|
||||
#endif
|
||||
|
||||
enc_start_state = *enc;
|
||||
|
||||
ALLOC(oldEBands_intra, C*m->nbEBands, celt_word16);
|
||||
ALLOC(error_intra, C*m->nbEBands, celt_word16);
|
||||
CELT_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);
|
||||
}
|
||||
|
||||
if (!intra)
|
||||
{
|
||||
ec_enc enc_intra_state;
|
||||
int tell_intra;
|
||||
celt_uint32 nstart_bytes;
|
||||
celt_uint32 nintra_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);
|
||||
ALLOC(intra_bits, nintra_bytes-nstart_bytes, unsigned char);
|
||||
/* Copy bits from intra bit-stream */
|
||||
CELT_COPY(intra_bits,
|
||||
ec_get_buffer(&enc_intra_state) + nstart_bytes,
|
||||
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);
|
||||
|
||||
if (two_pass && (badness1 < badness2 || (badness1 == badness2 && ec_tell_frac(enc)+intra_bias > tell_intra)))
|
||||
{
|
||||
*enc = enc_intra_state;
|
||||
/* Copy intra bits to bit-stream */
|
||||
CELT_COPY(ec_get_buffer(&enc_intra_state) + nstart_bytes,
|
||||
intra_bits, nintra_bytes - nstart_bytes);
|
||||
CELT_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
|
||||
CELT_COPY(error, error_intra, C*m->nbEBands);
|
||||
intra = 1;
|
||||
}
|
||||
} else {
|
||||
CELT_COPY(oldEBands, oldEBands_intra, C*m->nbEBands);
|
||||
CELT_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, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C)
|
||||
{
|
||||
int i, c;
|
||||
const int C = CHANNELS(_C);
|
||||
|
||||
/* Encode finer resolution */
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
celt_int16 frac = 1<<fine_quant[i];
|
||||
if (fine_quant[i] <= 0)
|
||||
continue;
|
||||
c=0;
|
||||
do {
|
||||
int q2;
|
||||
celt_word16 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, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, int *fine_priority, int bits_left, ec_enc *enc, int _C)
|
||||
{
|
||||
int i, prio, c;
|
||||
const int C = CHANNELS(_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;
|
||||
celt_word16 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;
|
||||
bits_left--;
|
||||
} while (++c < C);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void unquant_coarse_energy(const CELTMode *m, int start, int end, celt_word16 *oldEBands, int intra, ec_dec *dec, int _C, int LM)
|
||||
{
|
||||
const unsigned char *prob_model = e_prob_model[LM][intra];
|
||||
int i, c;
|
||||
celt_word32 prev[2] = {0, 0};
|
||||
celt_word16 coef;
|
||||
celt_word16 beta;
|
||||
const int C = CHANNELS(_C);
|
||||
celt_int32 budget;
|
||||
celt_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;
|
||||
celt_word32 q;
|
||||
celt_word32 tmp;
|
||||
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 = 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, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C)
|
||||
{
|
||||
int i, c;
|
||||
const int C = CHANNELS(_C);
|
||||
/* Decode finer resolution */
|
||||
for (i=start;i<end;i++)
|
||||
{
|
||||
if (fine_quant[i] <= 0)
|
||||
continue;
|
||||
c=0;
|
||||
do {
|
||||
int q2;
|
||||
celt_word16 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, celt_word16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int _C)
|
||||
{
|
||||
int i, prio, c;
|
||||
const int C = CHANNELS(_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;
|
||||
celt_word16 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 log2Amp(const CELTMode *m, int start, int end,
|
||||
celt_ener *eBands, celt_word16 *oldEBands, int _C)
|
||||
{
|
||||
int c, i;
|
||||
const int C = CHANNELS(_C);
|
||||
c=0;
|
||||
do {
|
||||
for (i=0;i<start;i++)
|
||||
eBands[i+c*m->nbEBands] = 0;
|
||||
for (;i<end;i++)
|
||||
{
|
||||
celt_word16 lg = ADD16(oldEBands[i+c*m->nbEBands],
|
||||
SHL16((celt_word16)eMeans[i],6));
|
||||
eBands[i+c*m->nbEBands] = PSHR32(celt_exp2(lg),4);
|
||||
}
|
||||
for (;i<m->nbEBands;i++)
|
||||
eBands[i+c*m->nbEBands] = 0;
|
||||
} while (++c < C);
|
||||
}
|
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end,
|
||||
celt_ener *bandE, celt_word16 *bandLogE, int _C)
|
||||
{
|
||||
int c, i;
|
||||
const int C = CHANNELS(_C);
|
||||
c=0;
|
||||
do {
|
||||
for (i=0;i<effEnd;i++)
|
||||
bandLogE[i+c*m->nbEBands] =
|
||||
celt_log2(SHL32(bandE[i+c*m->nbEBands],2))
|
||||
- SHL16((celt_word16)eMeans[i],6);
|
||||
for (i=effEnd;i<end;i++)
|
||||
bandLogE[c*m->nbEBands+i] = -QCONST16(14.f,DB_SHIFT);
|
||||
} while (++c < C);
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/* 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 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 QUANT_BANDS
|
||||
#define QUANT_BANDS
|
||||
|
||||
#include "arch.h"
|
||||
#include "modes.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "mathops.h"
|
||||
|
||||
void amp2Log2(const CELTMode *m, int effEnd, int end,
|
||||
celt_ener *bandE, celt_word16 *bandLogE, int _C);
|
||||
|
||||
void log2Amp(const CELTMode *m, int start, int end,
|
||||
celt_ener *eBands, celt_word16 *oldEBands, int _C);
|
||||
|
||||
unsigned char *quant_prob_alloc(const CELTMode *m);
|
||||
void quant_prob_free(const celt_int16 *freq);
|
||||
|
||||
void quant_coarse_energy(const CELTMode *m, int start, int end, int effEnd,
|
||||
const celt_word16 *eBands, celt_word16 *oldEBands, celt_uint32 budget,
|
||||
celt_word16 *error, ec_enc *enc, int _C, int LM,
|
||||
int nbAvailableBytes, int force_intra, celt_word32 *delayedIntra,
|
||||
int two_pass, int loss_rate);
|
||||
|
||||
void quant_fine_energy(const CELTMode *m, int start, int end, celt_word16 *oldEBands, celt_word16 *error, int *fine_quant, ec_enc *enc, int _C);
|
||||
|
||||
void quant_energy_finalise(const CELTMode *m, int start, int end, celt_word16 *oldEBands, celt_word16 *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, celt_word16 *oldEBands, int intra, ec_dec *dec, int _C, int LM);
|
||||
|
||||
void unquant_fine_energy(const CELTMode *m, int start, int end, celt_word16 *oldEBands, int *fine_quant, ec_dec *dec, int _C);
|
||||
|
||||
void unquant_energy_finalise(const CELTMode *m, int start, int end, celt_word16 *oldEBands, int *fine_quant, int *fine_priority, int bits_left, ec_dec *dec, int _C);
|
||||
|
||||
#endif /* QUANT_BANDS */
|
||||
@@ -1,638 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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 celt_int16 maxN[15] = {
|
||||
32767, 32767, 32767, 1476, 283, 109, 60, 40,
|
||||
29, 24, 20, 18, 16, 14, 13};
|
||||
static const celt_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 celt_int16 *eBands = m->eBands;
|
||||
PulseCache *cache = &m->cache;
|
||||
celt_int16 *cindex;
|
||||
unsigned char *bits;
|
||||
unsigned char *cap;
|
||||
|
||||
cindex = celt_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 = celt_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];
|
||||
celt_int16 tmp[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 = celt_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;
|
||||
celt_int32 num;
|
||||
celt_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. */
|
||||
if (N0 > 2 && !(N0&1))
|
||||
{
|
||||
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*(celt_int32)((2*N-1)*offset+max_bits);
|
||||
den=((celt_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)*(celt_int32)(max_bits+ndof*offset);
|
||||
den = ((celt_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 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, celt_int32 total, celt_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)
|
||||
{
|
||||
celt_int32 psum;
|
||||
int lo, hi;
|
||||
int i, j;
|
||||
int logM;
|
||||
const int C = CHANNELS(_C);
|
||||
int stereo;
|
||||
int codedBands=-1;
|
||||
int alloc_floor;
|
||||
celt_int32 left, percoeff;
|
||||
int done;
|
||||
int 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*(celt_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] + (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 = 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.*/
|
||||
/*Choose a threshold with some hysteresis to keep bands from
|
||||
fluctuating in and out.*/
|
||||
if (band_bits > ((j<prev?7:9)*band_width<<LM<<BITRES)>>4)
|
||||
{
|
||||
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 = 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;
|
||||
int excess;
|
||||
|
||||
celt_assert(bits[j] >= 0);
|
||||
N0 = m->eBands[j+1]-m->eBands[j];
|
||||
N=N0<<LM;
|
||||
bits[j] += balance;
|
||||
|
||||
if (N>1)
|
||||
{
|
||||
excess = IMAX(bits[j]-cap[j],0);
|
||||
bits[j] -= 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))) / (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 = IMAX(0,bits[j]-(C<<BITRES));
|
||||
bits[j] -= 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 compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stereo,
|
||||
celt_int32 total, celt_int32 *balance, int *pulses, int *ebits, int *fine_priority, int _C, int LM, ec_ctx *ec, int encode, int prev)
|
||||
{
|
||||
int lo, hi, len, j;
|
||||
const int C = CHANNELS(_C);
|
||||
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)
|
||||
<<(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);
|
||||
RESTORE_STACK;
|
||||
return codedBands;
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/* 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 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 RATE_H
|
||||
#define RATE_H
|
||||
|
||||
#define MAX_PSEUDO 40
|
||||
#define LOG_MAX_PSEUDO 6
|
||||
|
||||
#define MAX_PULSES 128
|
||||
|
||||
#define MAX_FINE_BITS 8
|
||||
|
||||
#define FINE_OFFSET 21
|
||||
#define QTHETA_OFFSET 4
|
||||
#define QTHETA_OFFSET_TWOPHASE 16
|
||||
|
||||
#define BITOVERFLOW 30000
|
||||
|
||||
#include "cwrs.h"
|
||||
#include "modes.h"
|
||||
|
||||
void compute_pulse_cache(CELTMode *m, int LM);
|
||||
|
||||
static inline int get_pulses(int i)
|
||||
{
|
||||
return i<8 ? i : (8 + (i&7)) << ((i>>3)-1);
|
||||
}
|
||||
|
||||
static 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 (cache[mid] >= bits)
|
||||
hi = mid;
|
||||
else
|
||||
lo = mid;
|
||||
}
|
||||
if (bits- (lo == 0 ? -1 : cache[lo]) <= cache[hi]-bits)
|
||||
return lo;
|
||||
else
|
||||
return hi;
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
/** Computes a cache of the pulses->bits mapping in each band */
|
||||
celt_int16 **compute_alloc_cache(CELTMode *m, int M);
|
||||
|
||||
/** 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 compute_allocation(const CELTMode *m, int start, int end, const int *offsets, const int *cap, int alloc_trim, int *intensity, int *dual_stero,
|
||||
celt_int32 total, celt_int32 *balance, int *pulses, int *ebits, int *fine_priority, int _C, int LM, ec_ctx *ec, int encode, int prev);
|
||||
|
||||
|
||||
#endif
|
||||
@@ -1,147 +0,0 @@
|
||||
/* 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 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 STACK_ALLOC_H
|
||||
#define STACK_ALLOC_H
|
||||
|
||||
#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
|
||||
|
||||
#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
|
||||
|
||||
#else
|
||||
|
||||
#ifdef CELT_C
|
||||
char *global_stack=0;
|
||||
#else
|
||||
extern char *global_stack;
|
||||
#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=celt_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))))
|
||||
#define RESTORE_STACK (global_stack = _saved_stack)
|
||||
#define ALLOC_STACK char *_saved_stack; (global_stack = (global_stack==0) ? celt_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;
|
||||
|
||||
#endif /*VAR_ARRAYS*/
|
||||
|
||||
|
||||
#endif /*STACK_ALLOC_H*/
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,206 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt.h"
|
||||
#include "arch.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAX_PACKET 1275
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int err;
|
||||
char *inFile, *outFile;
|
||||
FILE *fin, *fout;
|
||||
CELTMode *mode=NULL;
|
||||
CELTEncoder *enc;
|
||||
CELTDecoder *dec;
|
||||
int len;
|
||||
celt_int32 frame_size, channels;
|
||||
int bytes_per_packet;
|
||||
unsigned char data[MAX_PACKET];
|
||||
int rate;
|
||||
int complexity;
|
||||
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
|
||||
int i;
|
||||
double rmsd = 0;
|
||||
#endif
|
||||
int count = 0;
|
||||
celt_int32 skip;
|
||||
celt_int16 *in, *out;
|
||||
if (argc != 9 && argc != 8 && argc != 7)
|
||||
{
|
||||
fprintf (stderr, "Usage: testcelt <rate> <channels> <frame size> "
|
||||
" <bytes per packet> [<complexity> [packet loss rate]] "
|
||||
"<input> <output>\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
rate = atoi(argv[1]);
|
||||
channels = atoi(argv[2]);
|
||||
frame_size = atoi(argv[3]);
|
||||
mode = celt_mode_create(rate, frame_size, NULL);
|
||||
if (mode == NULL)
|
||||
{
|
||||
fprintf(stderr, "failed to create a mode\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
bytes_per_packet = atoi(argv[4]);
|
||||
if (bytes_per_packet < 0 || bytes_per_packet > MAX_PACKET)
|
||||
{
|
||||
fprintf (stderr, "bytes per packet must be between 0 and %d\n",
|
||||
MAX_PACKET);
|
||||
return 1;
|
||||
}
|
||||
|
||||
inFile = argv[argc-2];
|
||||
fin = fopen(inFile, "rb");
|
||||
if (!fin)
|
||||
{
|
||||
fprintf (stderr, "Could not open input file %s\n", argv[argc-2]);
|
||||
return 1;
|
||||
}
|
||||
outFile = argv[argc-1];
|
||||
fout = fopen(outFile, "wb+");
|
||||
if (!fout)
|
||||
{
|
||||
fprintf (stderr, "Could not open output file %s\n", argv[argc-1]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
enc = celt_encoder_create_custom(mode, channels, &err);
|
||||
if (err != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create the encoder: %s\n", celt_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
dec = celt_decoder_create_custom(mode, channels, &err);
|
||||
if (err != 0)
|
||||
{
|
||||
fprintf(stderr, "Failed to create the decoder: %s\n", celt_strerror(err));
|
||||
return 1;
|
||||
}
|
||||
celt_decoder_ctl(dec, CELT_GET_LOOKAHEAD(&skip));
|
||||
|
||||
if (argc>7)
|
||||
{
|
||||
complexity=atoi(argv[5]);
|
||||
celt_encoder_ctl(enc,CELT_SET_COMPLEXITY(complexity));
|
||||
}
|
||||
|
||||
in = (celt_int16*)malloc(frame_size*channels*sizeof(celt_int16));
|
||||
out = (celt_int16*)malloc(frame_size*channels*sizeof(celt_int16));
|
||||
|
||||
while (!feof(fin))
|
||||
{
|
||||
int ret;
|
||||
err = fread(in, sizeof(short), frame_size*channels, fin);
|
||||
if (feof(fin))
|
||||
break;
|
||||
len = celt_encode(enc, in, frame_size, data, bytes_per_packet);
|
||||
if (len <= 0)
|
||||
fprintf (stderr, "celt_encode() failed: %s\n", celt_strerror(len));
|
||||
|
||||
/* This is for simulating bit errors */
|
||||
#if 0
|
||||
int errors = 0;
|
||||
int eid = 0;
|
||||
/* This simulates random bit error */
|
||||
for (i=0;i<len*8;i++)
|
||||
{
|
||||
if (rand()%atoi(argv[8])==0)
|
||||
{
|
||||
if (i<64)
|
||||
{
|
||||
errors++;
|
||||
eid = i;
|
||||
}
|
||||
data[i/8] ^= 1<<(7-(i%8));
|
||||
}
|
||||
}
|
||||
if (errors == 1)
|
||||
data[eid/8] ^= 1<<(7-(eid%8));
|
||||
else if (errors%2 == 1)
|
||||
data[rand()%8] ^= 1<<rand()%8;
|
||||
#endif
|
||||
|
||||
#if 1 /* Set to zero to use the encoder's output instead */
|
||||
/* This is to simulate packet loss */
|
||||
if (argc==9 && rand()%1000<atoi(argv[argc-3]))
|
||||
/*if (errors && (errors%2==0))*/
|
||||
ret = celt_decode(dec, NULL, len, out, frame_size);
|
||||
else
|
||||
ret = celt_decode(dec, data, len, out, frame_size);
|
||||
if (ret < 0)
|
||||
fprintf(stderr, "celt_decode() failed: %s\n", celt_strerror(ret));
|
||||
#else
|
||||
for (i=0;i<ret*channels;i++)
|
||||
out[i] = in[i];
|
||||
#endif
|
||||
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
|
||||
for (i=0;i<ret*channels;i++)
|
||||
{
|
||||
rmsd += (in[i]-out[i])*1.0*(in[i]-out[i]);
|
||||
/*out[i] -= in[i];*/
|
||||
}
|
||||
#endif
|
||||
count++;
|
||||
fwrite(out+skip*channels, sizeof(short), (ret-skip)*channels, fout);
|
||||
skip = 0;
|
||||
}
|
||||
PRINT_MIPS(stderr);
|
||||
|
||||
celt_encoder_destroy(enc);
|
||||
celt_decoder_destroy(dec);
|
||||
fclose(fin);
|
||||
fclose(fout);
|
||||
celt_mode_destroy(mode);
|
||||
free(in);
|
||||
free(out);
|
||||
#if !(defined (FIXED_POINT) && !defined(CUSTOM_MODES)) && defined(RESYNTH)
|
||||
if (rmsd > 0)
|
||||
{
|
||||
rmsd = sqrt(rmsd/(1.0*frame_size*channels*count));
|
||||
fprintf (stderr, "Error: encoder doesn't match decoder\n");
|
||||
fprintf (stderr, "RMS mismatch is %f\n", rmsd);
|
||||
return 1;
|
||||
} else {
|
||||
fprintf (stderr, "Encoder matches decoder!!\n");
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -1,430 +0,0 @@
|
||||
/* 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 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.
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.141592653
|
||||
#endif
|
||||
|
||||
static void exp_rotation1(celt_norm *X, int len, int stride, celt_word16 c, celt_word16 s)
|
||||
{
|
||||
int i;
|
||||
celt_norm *Xptr;
|
||||
Xptr = X;
|
||||
for (i=0;i<len-stride;i++)
|
||||
{
|
||||
celt_norm x1, x2;
|
||||
x1 = Xptr[0];
|
||||
x2 = Xptr[stride];
|
||||
Xptr[stride] = EXTRACT16(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15));
|
||||
*Xptr++ = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,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(SHR32(MULT16_16(c,x2) + MULT16_16(s,x1), 15));
|
||||
*Xptr-- = EXTRACT16(SHR32(MULT16_16(c,x1) - MULT16_16(s,x2), 15));
|
||||
}
|
||||
}
|
||||
|
||||
static 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;
|
||||
celt_word16 c, s;
|
||||
celt_word16 gain, theta;
|
||||
int stride2=0;
|
||||
int factor;
|
||||
/*int i;
|
||||
if (len>=30)
|
||||
{
|
||||
for (i=0;i<len;i++)
|
||||
X[i] = 0;
|
||||
X[14] = 1;
|
||||
K=5;
|
||||
}*/
|
||||
if (2*K>=len || spread==SPREAD_NONE)
|
||||
return;
|
||||
factor = SPREAD_FACTOR[spread-1];
|
||||
|
||||
gain = celt_div((celt_word32)MULT16_16(Q15_ONE,len),(celt_word32)(len+factor*K));
|
||||
/* FIXME: Make that HALF16 instead of HALF32 */
|
||||
theta = HALF32(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 way of computing sqrt(len/stride) with rounding.
|
||||
It's basically incrementing long as (stride2+0.5)^2 < len/stride.
|
||||
I _think_ it is bit-exact */
|
||||
while ((stride2*stride2+stride2)*stride + (stride>>2) < len)
|
||||
stride2++;
|
||||
}
|
||||
/*TODO: We should be passing around log2(B), not B, for both this and for
|
||||
extract_collapse_mask().*/
|
||||
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);
|
||||
}
|
||||
}
|
||||
/*if (len>=30)
|
||||
{
|
||||
for (i=0;i<len;i++)
|
||||
printf ("%f ", X[i]);
|
||||
printf ("\n");
|
||||
exit(0);
|
||||
}*/
|
||||
}
|
||||
|
||||
/** 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 * restrict iy, celt_norm * restrict X,
|
||||
int N, celt_word32 Ryy, celt_word16 gain)
|
||||
{
|
||||
int i;
|
||||
#ifdef FIXED_POINT
|
||||
int k;
|
||||
#endif
|
||||
celt_word32 t;
|
||||
celt_word16 g;
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
k = celt_ilog2(Ryy)>>1;
|
||||
#endif
|
||||
t = VSHR32(Ryy, (k-7)<<1);
|
||||
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;
|
||||
/*TODO: We should be passing around log2(B), not B, for both this and for
|
||||
exp_rotation().*/
|
||||
N0 = N/B;
|
||||
collapse_mask = 0;
|
||||
i=0; do {
|
||||
int j;
|
||||
j=0; do {
|
||||
collapse_mask |= (iy[i*N0+j]!=0)<<i;
|
||||
} while (++j<N0);
|
||||
} while (++i<B);
|
||||
return collapse_mask;
|
||||
}
|
||||
|
||||
unsigned alg_quant(celt_norm *X, int N, int K, int spread, int B,
|
||||
int resynth, ec_enc *enc, celt_word16 gain)
|
||||
{
|
||||
VARDECL(celt_norm, y);
|
||||
VARDECL(int, iy);
|
||||
VARDECL(celt_word16, signx);
|
||||
int i, j;
|
||||
celt_word16 s;
|
||||
int pulsesLeft;
|
||||
celt_word32 sum;
|
||||
celt_word32 xy;
|
||||
celt_word16 yy;
|
||||
unsigned collapse_mask;
|
||||
SAVE_STACK;
|
||||
|
||||
celt_assert2(K!=0, "alg_quant() needs at least one pulse");
|
||||
|
||||
ALLOC(y, N, celt_norm);
|
||||
ALLOC(iy, N, int);
|
||||
ALLOC(signx, N, celt_word16);
|
||||
|
||||
exp_rotation(X, N, 1, B, K, spread);
|
||||
|
||||
/* Get rid of the sign */
|
||||
sum = 0;
|
||||
j=0; do {
|
||||
if (X[j]>0)
|
||||
signx[j]=1;
|
||||
else {
|
||||
signx[j]=-1;
|
||||
X[j]=-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))
|
||||
{
|
||||
celt_word16 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
|
||||
if (sum <= EPSILON)
|
||||
#endif
|
||||
{
|
||||
X[0] = QCONST16(1.f,14);
|
||||
j=1; do
|
||||
X[j]=0;
|
||||
while (++j<N);
|
||||
sum = QCONST16(1.f,14);
|
||||
}
|
||||
/* Do we have sufficient accuracy here? */
|
||||
rcp = EXTRACT16(MULT16_32_Q16(K-1, celt_rcp(sum)));
|
||||
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] = 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_assert2(pulsesLeft>=1, "Allocated too many pulses in the quick pass");
|
||||
|
||||
/* 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_assert2(pulsesLeft<=N+3, "Not enough pulses in the quick pass");
|
||||
#endif
|
||||
if (pulsesLeft > N+3)
|
||||
{
|
||||
celt_word16 tmp = pulsesLeft;
|
||||
yy = MAC16_16(yy, tmp, tmp);
|
||||
yy = MAC16_16(yy, tmp, y[0]);
|
||||
iy[0] += pulsesLeft;
|
||||
pulsesLeft=0;
|
||||
}
|
||||
|
||||
s = 1;
|
||||
for (i=0;i<pulsesLeft;i++)
|
||||
{
|
||||
int best_id;
|
||||
celt_word32 best_num = -VERY_LARGE16;
|
||||
celt_word16 best_den = 0;
|
||||
#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 = ADD32(yy, 1);
|
||||
j=0;
|
||||
do {
|
||||
celt_word16 Rxy, Ryy;
|
||||
/* 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: Make sure to use conditional moves here */
|
||||
if (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*s;
|
||||
iy[best_id]++;
|
||||
}
|
||||
|
||||
/* Put the original sign back */
|
||||
j=0;
|
||||
do {
|
||||
X[j] = MULT16_16(signx[j],X[j]);
|
||||
if (signx[j] < 0)
|
||||
iy[j] = -iy[j];
|
||||
} while (++j<N);
|
||||
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, celt_word16 gain)
|
||||
{
|
||||
int i;
|
||||
celt_word32 Ryy;
|
||||
unsigned collapse_mask;
|
||||
VARDECL(int, iy);
|
||||
SAVE_STACK;
|
||||
|
||||
celt_assert2(K!=0, "alg_unquant() needs at least one pulse");
|
||||
ALLOC(iy, N, int);
|
||||
decode_pulses(iy, N, K, dec);
|
||||
Ryy = 0;
|
||||
i=0;
|
||||
do {
|
||||
Ryy = MAC16_16(Ryy, iy[i], iy[i]);
|
||||
} while (++i < N);
|
||||
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;
|
||||
}
|
||||
|
||||
void renormalise_vector(celt_norm *X, int N, celt_word16 gain)
|
||||
{
|
||||
int i;
|
||||
#ifdef FIXED_POINT
|
||||
int k;
|
||||
#endif
|
||||
celt_word32 E = EPSILON;
|
||||
celt_word16 g;
|
||||
celt_word32 t;
|
||||
celt_norm *xptr = X;
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
E = MAC16_16(E, *xptr, *xptr);
|
||||
xptr++;
|
||||
}
|
||||
#ifdef FIXED_POINT
|
||||
k = celt_ilog2(E)>>1;
|
||||
#endif
|
||||
t = VSHR32(E, (k-7)<<1);
|
||||
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);*/
|
||||
}
|
||||
|
||||
int stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N)
|
||||
{
|
||||
int i;
|
||||
int itheta;
|
||||
celt_word16 mid, side;
|
||||
celt_word32 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 {
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
celt_norm m, s;
|
||||
m = X[i];
|
||||
s = Y[i];
|
||||
Emid = MAC16_16(Emid, m, m);
|
||||
Eside = MAC16_16(Eside, s, s);
|
||||
}
|
||||
}
|
||||
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*atan2(side,mid));
|
||||
#endif
|
||||
|
||||
return itheta;
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/* 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 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 VQ_H
|
||||
#define VQ_H
|
||||
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include "modes.h"
|
||||
|
||||
/** 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 W Perceptual weight to use when optimising (currently unused)
|
||||
* @param N Number of samples to encode
|
||||
* @param K Number of pulses to use
|
||||
* @param p Pitch vector (it is assumed that p+x is a unit vector)
|
||||
* @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,
|
||||
int resynth, ec_enc *enc, celt_word16 gain);
|
||||
|
||||
/** Algebraic pulse decoder
|
||||
* @param x Decoded normalised spectrum (returned)
|
||||
* @param N Number of samples to decode
|
||||
* @param K Number of pulses to use
|
||||
* @param p Pitch vector (automatically added to x)
|
||||
* @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, celt_word16 gain);
|
||||
|
||||
void renormalise_vector(celt_norm *X, int N, celt_word16 gain);
|
||||
|
||||
int stereo_itheta(celt_norm *X, celt_norm *Y, int stereo, int N);
|
||||
|
||||
#endif /* VQ_H */
|
||||
@@ -1,17 +0,0 @@
|
||||
INCLUDES = -I$(top_srcdir)/libcelt
|
||||
METASOURCES = AUTO
|
||||
|
||||
TESTS = type-test ectest cwrs32-test dft-test laplace-test mdct-test mathops-test tandem-test
|
||||
|
||||
noinst_PROGRAMS = type-test ectest cwrs32-test dft-test laplace-test mdct-test mathops-test tandem-test
|
||||
|
||||
type_test_SOURCES = type-test.c
|
||||
ectest_SOURCES = ectest.c
|
||||
cwrs32_test_SOURCES = cwrs32-test.c
|
||||
dft_test_SOURCES = dft-test.c
|
||||
laplace_test_SOURCES = laplace-test.c
|
||||
mdct_test_SOURCES = mdct-test.c
|
||||
#rotation_test_SOURCES = rotation-test.c
|
||||
mathops_test_SOURCES = mathops-test.c
|
||||
tandem_test_SOURCES = tandem-test.c
|
||||
tandem_test_LDADD = $(top_builddir)/libcelt/libcelt@LIBCELT_SUFFIX@.la
|
||||
@@ -1,176 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CELT_C
|
||||
#include "../libcelt/stack_alloc.h"
|
||||
#include "../libcelt/entenc.c"
|
||||
#include "../libcelt/entdec.c"
|
||||
#include "../libcelt/entcode.c"
|
||||
#include "../libcelt/cwrs.c"
|
||||
#include "../libcelt/mathops.c"
|
||||
|
||||
#define NMAX (14)
|
||||
#define KMAX (32767)
|
||||
|
||||
static const int kmax[15]={
|
||||
32767,32767,32767,32767, 1172,
|
||||
238, 95, 53, 36, 27,
|
||||
22, 18, 16, 15, 13
|
||||
};
|
||||
|
||||
|
||||
int main(int _argc,char **_argv){
|
||||
int n;
|
||||
ALLOC_STACK;
|
||||
for(n=2;n<=NMAX;n++){
|
||||
int dk;
|
||||
int k;
|
||||
dk=kmax[n]>7?kmax[n]/7:1;
|
||||
k=1-dk;
|
||||
do{
|
||||
celt_uint32 uu[KMAX+2U];
|
||||
celt_uint32 inc;
|
||||
celt_uint32 nc;
|
||||
celt_uint32 i;
|
||||
k=kmax[n]-dk<k?kmax[n]:k+dk;
|
||||
printf("Testing CWRS with N=%i, K=%i...\n",n,k);
|
||||
nc=ncwrs_urow(n,k,uu);
|
||||
inc=nc/10000;
|
||||
if(inc<1)inc=1;
|
||||
for(i=0;i<nc;i+=inc){
|
||||
celt_uint32 u[KMAX+2U];
|
||||
int y[NMAX];
|
||||
int yy[5];
|
||||
celt_uint32 v;
|
||||
celt_uint32 ii;
|
||||
int kk;
|
||||
int j;
|
||||
memcpy(u,uu,(k+2U)*sizeof(*u));
|
||||
cwrsi(n,k,i,y,u);
|
||||
/*printf("%6u of %u:",i,nc);
|
||||
for(j=0;j<n;j++)printf(" %+3i",y[j]);
|
||||
printf(" ->");*/
|
||||
ii=icwrs(n,k,&v,y,u);
|
||||
if(ii!=i){
|
||||
fprintf(stderr,"Combination-index mismatch (%lu!=%lu).\n",
|
||||
(long)ii,(long)i);
|
||||
return 1;
|
||||
}
|
||||
if(v!=nc){
|
||||
fprintf(stderr,"Combination count mismatch (%lu!=%lu).\n",
|
||||
(long)v,(long)nc);
|
||||
return 2;
|
||||
}
|
||||
#ifndef SMALL_FOOTPRINT
|
||||
if(n==2){
|
||||
cwrsi2(k,i,yy);
|
||||
for(j=0;j<2;j++)if(yy[j]!=y[j]){
|
||||
fprintf(stderr,"N=2 pulse vector mismatch ({%i,%i}!={%i,%i}).\n",
|
||||
yy[0],yy[1],y[0],y[1]);
|
||||
return 3;
|
||||
}
|
||||
ii=icwrs2(yy,&kk);
|
||||
if(ii!=i){
|
||||
fprintf(stderr,"N=2 combination-index mismatch (%lu!=%lu).\n",
|
||||
(long)ii,(long)i);
|
||||
return 4;
|
||||
}
|
||||
if(kk!=k){
|
||||
fprintf(stderr,"N=2 pulse count mismatch (%i,%i).\n",kk,k);
|
||||
return 5;
|
||||
}
|
||||
v=ncwrs2(k);
|
||||
if(v!=nc){
|
||||
fprintf(stderr,"N=2 combination count mismatch (%lu,%lu).\n",
|
||||
(long)v,(long)nc);
|
||||
return 6;
|
||||
}
|
||||
}
|
||||
else if(n==3){
|
||||
cwrsi3(k,i,yy);
|
||||
for(j=0;j<3;j++)if(yy[j]!=y[j]){
|
||||
fprintf(stderr,"N=3 pulse vector mismatch "
|
||||
"({%i,%i,%i}!={%i,%i,%i}).\n",yy[0],yy[1],yy[2],y[0],y[1],y[2]);
|
||||
return 7;
|
||||
}
|
||||
ii=icwrs3(yy,&kk);
|
||||
if(ii!=i){
|
||||
fprintf(stderr,"N=3 combination-index mismatch (%lu!=%lu).\n",
|
||||
(long)ii,(long)i);
|
||||
return 8;
|
||||
}
|
||||
if(kk!=k){
|
||||
fprintf(stderr,"N=3 pulse count mismatch (%i!=%i).\n",kk,k);
|
||||
return 9;
|
||||
}
|
||||
v=ncwrs3(k);
|
||||
if(v!=nc){
|
||||
fprintf(stderr,"N=3 combination count mismatch (%lu!=%lu).\n",
|
||||
(long)v,(long)nc);
|
||||
return 10;
|
||||
}
|
||||
}
|
||||
else if(n==4){
|
||||
cwrsi4(k,i,yy);
|
||||
for(j=0;j<4;j++)if(yy[j]!=y[j]){
|
||||
fprintf(stderr,"N=4 pulse vector mismatch "
|
||||
"({%i,%i,%i,%i}!={%i,%i,%i,%i}.\n",
|
||||
yy[0],yy[1],yy[2],yy[3],y[0],y[1],y[2],y[3]);
|
||||
return 11;
|
||||
}
|
||||
ii=icwrs4(yy,&kk);
|
||||
if(ii!=i){
|
||||
fprintf(stderr,"N=4 combination-index mismatch (%lu!=%lu).\n",
|
||||
(long)ii,(long)i);
|
||||
return 12;
|
||||
}
|
||||
if(kk!=k){
|
||||
fprintf(stderr,"N=4 pulse count mismatch (%i!=%i).\n",kk,k);
|
||||
return 13;
|
||||
}
|
||||
v=ncwrs4(k);
|
||||
if(v!=nc){
|
||||
fprintf(stderr,"N=4 combination count mismatch (%lu!=%lu).\n",
|
||||
(long)v,(long)nc);
|
||||
return 14;
|
||||
}
|
||||
}
|
||||
else if(n==5){
|
||||
cwrsi5(k,i,yy);
|
||||
for(j=0;j<5;j++)if(yy[j]!=y[j]){
|
||||
fprintf(stderr,"N=5 pulse vector mismatch "
|
||||
"({%i,%i,%i,%i,%i}!={%i,%i,%i,%i,%i}).\n",
|
||||
yy[0],yy[1],yy[2],yy[3],yy[4],y[0],y[1],y[2],y[3],y[4]);
|
||||
return 15;
|
||||
}
|
||||
ii=icwrs5(yy,&kk);
|
||||
if(ii!=i){
|
||||
fprintf(stderr,"N=5 combination-index mismatch (%lu!=%lu).\n",
|
||||
(long)ii,(long)i);
|
||||
return 16;
|
||||
}
|
||||
if(kk!=k){
|
||||
fprintf(stderr,"N=5 pulse count mismatch (%i!=%i).\n",kk,k);
|
||||
return 17;
|
||||
}
|
||||
v=ncwrs5(k);
|
||||
if(v!=nc){
|
||||
fprintf(stderr,"N=5 combination count mismatch (%lu!=%lu).\n",
|
||||
(long)v,(long)nc);
|
||||
return 18;
|
||||
}
|
||||
}
|
||||
#endif /* SMALL_FOOTPRINT */
|
||||
|
||||
/*printf(" %6u\n",i);*/
|
||||
}
|
||||
/*printf("\n");*/
|
||||
}
|
||||
while(k<kmax[n]);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,142 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define SKIP_CONFIG_H
|
||||
|
||||
#ifndef CUSTOM_MODES
|
||||
#define CUSTOM_MODES
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "kiss_fft.h"
|
||||
|
||||
#define CELT_C
|
||||
#include "../libcelt/stack_alloc.h"
|
||||
#include "../libcelt/kiss_fft.c"
|
||||
#include "../libcelt/mathops.c"
|
||||
#include "../libcelt/entcode.c"
|
||||
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.141592653
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
long long celt_mips=0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
void check(kiss_fft_cpx * in,kiss_fft_cpx * out,int nfft,int isinverse)
|
||||
{
|
||||
int bin,k;
|
||||
double errpow=0,sigpow=0, snr;
|
||||
|
||||
for (bin=0;bin<nfft;++bin) {
|
||||
double ansr = 0;
|
||||
double ansi = 0;
|
||||
double difr;
|
||||
double difi;
|
||||
|
||||
for (k=0;k<nfft;++k) {
|
||||
double phase = -2*M_PI*bin*k/nfft;
|
||||
double re = cos(phase);
|
||||
double im = sin(phase);
|
||||
if (isinverse)
|
||||
im = -im;
|
||||
|
||||
if (!isinverse)
|
||||
{
|
||||
re /= nfft;
|
||||
im /= nfft;
|
||||
}
|
||||
|
||||
ansr += in[k].r * re - in[k].i * im;
|
||||
ansi += in[k].r * im + in[k].i * re;
|
||||
}
|
||||
/*printf ("%d %d ", (int)ansr, (int)ansi);*/
|
||||
difr = ansr - out[bin].r;
|
||||
difi = ansi - out[bin].i;
|
||||
errpow += difr*difr + difi*difi;
|
||||
sigpow += ansr*ansr+ansi*ansi;
|
||||
}
|
||||
snr = 10*log10(sigpow/errpow);
|
||||
printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
|
||||
if (snr<60) {
|
||||
printf( "** poor snr: %f ** \n", snr);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void test1d(int nfft,int isinverse)
|
||||
{
|
||||
size_t buflen = sizeof(kiss_fft_cpx)*nfft;
|
||||
|
||||
kiss_fft_cpx * in = (kiss_fft_cpx*)malloc(buflen);
|
||||
kiss_fft_cpx * out= (kiss_fft_cpx*)malloc(buflen);
|
||||
kiss_fft_state *cfg = kiss_fft_alloc(nfft,0,0);
|
||||
int k;
|
||||
|
||||
for (k=0;k<nfft;++k) {
|
||||
in[k].r = (rand() % 32767) - 16384;
|
||||
in[k].i = (rand() % 32767) - 16384;
|
||||
}
|
||||
|
||||
#ifdef DOUBLE_PRECISION
|
||||
for (k=0;k<nfft;++k) {
|
||||
in[k].r *= 32768;
|
||||
in[k].i *= 32768;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isinverse)
|
||||
{
|
||||
for (k=0;k<nfft;++k) {
|
||||
in[k].r /= nfft;
|
||||
in[k].i /= nfft;
|
||||
}
|
||||
}
|
||||
|
||||
/*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
|
||||
|
||||
if (isinverse)
|
||||
kiss_ifft(cfg,in,out);
|
||||
else
|
||||
kiss_fft(cfg,in,out);
|
||||
|
||||
/*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
|
||||
|
||||
check(in,out,nfft,isinverse);
|
||||
|
||||
free(in);
|
||||
free(out);
|
||||
free(cfg);
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
ALLOC_STACK;
|
||||
if (argc>1) {
|
||||
int k;
|
||||
for (k=1;k<argc;++k) {
|
||||
test1d(atoi(argv[k]),0);
|
||||
test1d(atoi(argv[k]),1);
|
||||
}
|
||||
}else{
|
||||
test1d(32,0);
|
||||
test1d(32,1);
|
||||
test1d(128,0);
|
||||
test1d(128,1);
|
||||
test1d(256,0);
|
||||
test1d(256,1);
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
test1d(36,0);
|
||||
test1d(36,1);
|
||||
test1d(50,0);
|
||||
test1d(50,1);
|
||||
test1d(120,0);
|
||||
test1d(120,1);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <time.h>
|
||||
#include "entcode.h"
|
||||
#include "entenc.h"
|
||||
#include "entdec.h"
|
||||
#include <string.h>
|
||||
|
||||
#include "../libcelt/entenc.c"
|
||||
#include "../libcelt/entdec.c"
|
||||
#include "../libcelt/entcode.c"
|
||||
|
||||
#ifndef M_LOG2E
|
||||
# define M_LOG2E 1.4426950408889634074
|
||||
#endif
|
||||
#define DATA_SIZE 10000000
|
||||
#define DATA_SIZE2 10000
|
||||
|
||||
int main(int _argc,char **_argv){
|
||||
ec_enc enc;
|
||||
ec_dec dec;
|
||||
long nbits;
|
||||
long nbits2;
|
||||
double entropy;
|
||||
int ft;
|
||||
int ftb;
|
||||
int sym;
|
||||
int sz;
|
||||
int i;
|
||||
int ret;
|
||||
unsigned int seed;
|
||||
unsigned char *ptr;
|
||||
ret=0;
|
||||
entropy=0;
|
||||
if (_argc > 2) {
|
||||
fprintf(stderr, "Usage: %s [<seed>]\n", _argv[0]);
|
||||
return 1;
|
||||
}
|
||||
if (_argc > 1)
|
||||
seed = atoi(_argv[1]);
|
||||
else
|
||||
seed = time(NULL);
|
||||
/*Testing encoding of raw bit values.*/
|
||||
ptr = malloc(DATA_SIZE);
|
||||
ec_enc_init(&enc,ptr, DATA_SIZE);
|
||||
for(ft=2;ft<1024;ft++){
|
||||
for(i=0;i<ft;i++){
|
||||
entropy+=log(ft)*M_LOG2E;
|
||||
ec_enc_uint(&enc,i,ft);
|
||||
}
|
||||
}
|
||||
/*Testing encoding of raw bit values.*/
|
||||
for(ftb=0;ftb<16;ftb++){
|
||||
for(i=0;i<(1<<ftb);i++){
|
||||
entropy+=ftb;
|
||||
nbits=ec_tell(&enc);
|
||||
ec_enc_bits(&enc,i,ftb);
|
||||
nbits2=ec_tell(&enc);
|
||||
if(nbits2-nbits!=ftb){
|
||||
fprintf(stderr,"Used %li bits to encode %i bits directly.\n",
|
||||
nbits2-nbits,ftb);
|
||||
ret=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
nbits=ec_tell_frac(&enc);
|
||||
ec_enc_done(&enc);
|
||||
fprintf(stderr,
|
||||
"Encoded %0.2lf bits of entropy to %0.2lf bits (%0.3lf%% wasted).\n",
|
||||
entropy,ldexp(nbits,-3),100*(nbits-ldexp(entropy,3))/nbits);
|
||||
fprintf(stderr,"Packed to %li bytes.\n",(long)ec_range_bytes(&enc));
|
||||
ec_dec_init(&dec,ptr,DATA_SIZE);
|
||||
for(ft=2;ft<1024;ft++){
|
||||
for(i=0;i<ft;i++){
|
||||
sym=ec_dec_uint(&dec,ft);
|
||||
if(sym!=i){
|
||||
fprintf(stderr,"Decoded %i instead of %i with ft of %i.\n",sym,i,ft);
|
||||
ret=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
for(ftb=0;ftb<16;ftb++){
|
||||
for(i=0;i<(1<<ftb);i++){
|
||||
sym=ec_dec_bits(&dec,ftb);
|
||||
if(sym!=i){
|
||||
fprintf(stderr,"Decoded %i instead of %i with ftb of %i.\n",sym,i,ftb);
|
||||
ret=-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
nbits2=ec_tell_frac(&dec);
|
||||
if(nbits!=nbits2){
|
||||
fprintf(stderr,
|
||||
"Reported number of bits used was %0.2lf, should be %0.2lf.\n",
|
||||
ldexp(nbits2,-3),ldexp(nbits,-3));
|
||||
ret=-1;
|
||||
}
|
||||
srand(seed);
|
||||
fprintf(stderr,"Testing random streams... Random seed: %u (%.4X)\n", seed, rand() % 65536);
|
||||
for(i=0;i<409600;i++){
|
||||
unsigned *data;
|
||||
unsigned *tell;
|
||||
int j;
|
||||
int tell_bits;
|
||||
int zeros;
|
||||
ft=rand()/((RAND_MAX>>(rand()%11))+1)+10;
|
||||
sz=rand()/((RAND_MAX>>(rand()%9))+1);
|
||||
data=(unsigned *)malloc(sz*sizeof(*data));
|
||||
tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
|
||||
ec_enc_init(&enc,ptr,DATA_SIZE2);
|
||||
zeros = rand()%13==0;
|
||||
tell[0]=ec_tell_frac(&enc);
|
||||
for(j=0;j<sz;j++){
|
||||
if (zeros)
|
||||
data[j]=0;
|
||||
else
|
||||
data[j]=rand()%ft;
|
||||
ec_enc_uint(&enc,data[j],ft);
|
||||
tell[j+1]=ec_tell_frac(&enc);
|
||||
}
|
||||
if (rand()%2==0)
|
||||
while(ec_tell(&enc)%8 != 0)
|
||||
ec_enc_uint(&enc, rand()%2, 2);
|
||||
tell_bits = ec_tell(&enc);
|
||||
ec_enc_done(&enc);
|
||||
if(tell_bits!=ec_tell(&enc)){
|
||||
fprintf(stderr,"ec_tell() changed after ec_enc_done(): %i instead of %i (Random seed: %u)\n",
|
||||
ec_tell(&enc),tell_bits,seed);
|
||||
ret=-1;
|
||||
}
|
||||
if ((tell_bits+7)/8 < ec_range_bytes(&enc))
|
||||
{
|
||||
fprintf (stderr, "ec_tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
|
||||
ec_range_bytes(&enc), (tell_bits+7)/8,seed);
|
||||
ret=-1;
|
||||
}
|
||||
tell_bits -= 8*ec_range_bytes(&enc);
|
||||
ec_dec_init(&dec,ptr,DATA_SIZE2);
|
||||
if(ec_tell_frac(&dec)!=tell[0]){
|
||||
fprintf(stderr,
|
||||
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
|
||||
0,ec_tell_frac(&dec),tell[0],seed);
|
||||
}
|
||||
for(j=0;j<sz;j++){
|
||||
sym=ec_dec_uint(&dec,ft);
|
||||
if(sym!=data[j]){
|
||||
fprintf(stderr,
|
||||
"Decoded %i instead of %i with ft of %i at position %i of %i (Random seed: %u).\n",
|
||||
sym,data[j],ft,j,sz,seed);
|
||||
ret=-1;
|
||||
}
|
||||
if(ec_tell_frac(&dec)!=tell[j+1]){
|
||||
fprintf(stderr,
|
||||
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
|
||||
j+1,ec_tell_frac(&dec),tell[j+1],seed);
|
||||
}
|
||||
}
|
||||
free(tell);
|
||||
free(data);
|
||||
}
|
||||
/*Test compatibility between multiple different encode/decode routines.*/
|
||||
for(i=0;i<409600;i++){
|
||||
unsigned *logp1;
|
||||
unsigned *data;
|
||||
unsigned *tell;
|
||||
unsigned *enc_method;
|
||||
int j;
|
||||
sz=rand()/((RAND_MAX>>(rand()%9))+1);
|
||||
logp1=(unsigned *)malloc(sz*sizeof(*logp1));
|
||||
data=(unsigned *)malloc(sz*sizeof(*data));
|
||||
tell=(unsigned *)malloc((sz+1)*sizeof(*tell));
|
||||
enc_method=(unsigned *)malloc(sz*sizeof(*enc_method));
|
||||
ec_enc_init(&enc,ptr,DATA_SIZE2);
|
||||
tell[0]=ec_tell_frac(&enc);
|
||||
for(j=0;j<sz;j++){
|
||||
data[j]=rand()/((RAND_MAX>>1)+1);
|
||||
logp1[j]=(rand()%15)+1;
|
||||
enc_method[j]=rand()/((RAND_MAX>>2)+1);
|
||||
switch(enc_method[j]){
|
||||
case 0:{
|
||||
ec_encode(&enc,data[j]?(1<<logp1[j])-1:0,
|
||||
(1<<logp1[j])-(data[j]?0:1),1<<logp1[j]);
|
||||
}break;
|
||||
case 1:{
|
||||
ec_encode_bin(&enc,data[j]?(1<<logp1[j])-1:0,
|
||||
(1<<logp1[j])-(data[j]?0:1),logp1[j]);
|
||||
}break;
|
||||
case 2:{
|
||||
ec_enc_bit_logp(&enc,data[j],logp1[j]);
|
||||
}break;
|
||||
case 3:{
|
||||
unsigned char icdf[2];
|
||||
icdf[0]=1;
|
||||
icdf[1]=0;
|
||||
ec_enc_icdf(&enc,data[j],icdf,logp1[j]);
|
||||
}break;
|
||||
}
|
||||
tell[j+1]=ec_tell_frac(&enc);
|
||||
}
|
||||
ec_enc_done(&enc);
|
||||
if((ec_tell(&enc)+7)/8<ec_range_bytes(&enc)){
|
||||
fprintf(stderr,"tell() lied, there's %i bytes instead of %d (Random seed: %u)\n",
|
||||
ec_range_bytes(&enc),(ec_tell(&enc)+7)/8,seed);
|
||||
ret=-1;
|
||||
}
|
||||
ec_dec_init(&dec,ptr,DATA_SIZE2);
|
||||
if(ec_tell_frac(&dec)!=tell[0]){
|
||||
fprintf(stderr,
|
||||
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
|
||||
0,ec_tell_frac(&dec),tell[0],seed);
|
||||
}
|
||||
for(j=0;j<sz;j++){
|
||||
int fs;
|
||||
int dec_method;
|
||||
dec_method=rand()/((RAND_MAX>>2)+1);
|
||||
switch(dec_method){
|
||||
case 0:{
|
||||
fs=ec_decode(&dec,1<<logp1[j]);
|
||||
sym=fs>=(1<<logp1[j])-1;
|
||||
ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
|
||||
(1<<logp1[j])-(sym?0:1),1<<logp1[j]);
|
||||
}break;
|
||||
case 1:{
|
||||
fs=ec_decode_bin(&dec,logp1[j]);
|
||||
sym=fs>=(1<<logp1[j])-1;
|
||||
ec_dec_update(&dec,sym?(1<<logp1[j])-1:0,
|
||||
(1<<logp1[j])-(sym?0:1),1<<logp1[j]);
|
||||
}break;
|
||||
case 2:{
|
||||
sym=ec_dec_bit_logp(&dec,logp1[j]);
|
||||
}break;
|
||||
case 3:{
|
||||
unsigned char icdf[2];
|
||||
icdf[0]=1;
|
||||
icdf[1]=0;
|
||||
sym=ec_dec_icdf(&dec,icdf,logp1[j]);
|
||||
}break;
|
||||
}
|
||||
if(sym!=data[j]){
|
||||
fprintf(stderr,
|
||||
"Decoded %i instead of %i with logp1 of %i at position %i of %i (Random seed: %u).\n",
|
||||
sym,data[j],logp1[j],j,sz,seed);
|
||||
fprintf(stderr,"Encoding method: %i, decoding method: %i\n",
|
||||
enc_method[j],dec_method);
|
||||
ret=-1;
|
||||
}
|
||||
if(ec_tell_frac(&dec)!=tell[j+1]){
|
||||
fprintf(stderr,
|
||||
"Tell mismatch between encoder and decoder at symbol %i: %i instead of %i (Random seed: %u).\n",
|
||||
j+1,ec_tell_frac(&dec),tell[j+1],seed);
|
||||
}
|
||||
}
|
||||
free(enc_method);
|
||||
free(tell);
|
||||
free(data);
|
||||
free(logp1);
|
||||
}
|
||||
free(ptr);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "laplace.h"
|
||||
#define CELT_C
|
||||
#include "../libcelt/stack_alloc.h"
|
||||
|
||||
#include "../libcelt/entenc.c"
|
||||
#include "../libcelt/entdec.c"
|
||||
#include "../libcelt/entcode.c"
|
||||
#include "../libcelt/laplace.c"
|
||||
|
||||
#define DATA_SIZE 40000
|
||||
|
||||
int ec_laplace_get_start_freq(int decay)
|
||||
{
|
||||
celt_uint32 ft = 32768 - LAPLACE_MINP*(2*LAPLACE_NMIN+1);
|
||||
int fs = (ft*(16384-decay))/(16384+decay);
|
||||
return fs+LAPLACE_MINP;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
int ret = 0;
|
||||
ec_enc enc;
|
||||
ec_dec dec;
|
||||
unsigned char *ptr;
|
||||
int val[10000], decay[10000];
|
||||
ALLOC_STACK;
|
||||
ptr = malloc(DATA_SIZE);
|
||||
ec_enc_init(&enc,ptr,DATA_SIZE);
|
||||
|
||||
val[0] = 3; decay[0] = 6000;
|
||||
val[1] = 0; decay[1] = 5800;
|
||||
val[2] = -1; decay[2] = 5600;
|
||||
for (i=3;i<10000;i++)
|
||||
{
|
||||
val[i] = rand()%15-7;
|
||||
decay[i] = rand()%11000+5000;
|
||||
}
|
||||
for (i=0;i<10000;i++)
|
||||
ec_laplace_encode(&enc, &val[i],
|
||||
ec_laplace_get_start_freq(decay[i]), decay[i]);
|
||||
|
||||
ec_enc_done(&enc);
|
||||
|
||||
ec_dec_init(&dec,ec_get_buffer(&enc),ec_range_bytes(&enc));
|
||||
|
||||
for (i=0;i<10000;i++)
|
||||
{
|
||||
int d = ec_laplace_decode(&dec,
|
||||
ec_laplace_get_start_freq(decay[i]), decay[i]);
|
||||
if (d != val[i])
|
||||
{
|
||||
fprintf (stderr, "Got %d instead of %d\n", d, val[i]);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "mathops.c"
|
||||
#include "entcode.c"
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#define WORD "%d"
|
||||
#else
|
||||
#define WORD "%f"
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
long long celt_mips=0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
|
||||
void testdiv(void)
|
||||
{
|
||||
celt_int32 i;
|
||||
for (i=1;i<=327670;i++)
|
||||
{
|
||||
double prod;
|
||||
celt_word32 val;
|
||||
val = celt_rcp(i);
|
||||
#ifdef FIXED_POINT
|
||||
prod = (1./32768./65526.)*val*i;
|
||||
#else
|
||||
prod = val*i;
|
||||
#endif
|
||||
if (fabs(prod-1) > .00025)
|
||||
{
|
||||
fprintf (stderr, "div failed: 1/%d="WORD" (product = %f)\n", i, val, prod);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testsqrt(void)
|
||||
{
|
||||
celt_int32 i;
|
||||
for (i=1;i<=1000000000;i++)
|
||||
{
|
||||
double ratio;
|
||||
celt_word16 val;
|
||||
val = celt_sqrt(i);
|
||||
ratio = val/sqrt(i);
|
||||
if (fabs(ratio - 1) > .0005 && fabs(val-sqrt(i)) > 2)
|
||||
{
|
||||
fprintf (stderr, "sqrt failed: sqrt(%d)="WORD" (ratio = %f)\n", i, val, ratio);
|
||||
ret = 1;
|
||||
}
|
||||
i+= i>>10;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef FIXED_POINT
|
||||
void testlog2(void)
|
||||
{
|
||||
float x;
|
||||
for (x=0.001;x<1677700.0;x+=(x/8.0))
|
||||
{
|
||||
float error = fabs((1.442695040888963387*log(x))-celt_log2(x));
|
||||
if (error>0.0009)
|
||||
{
|
||||
fprintf (stderr, "celt_log2 failed: fabs((1.442695040888963387*log(x))-celt_log2(x))>0.001 (x = %f, error = %f)\n", x,error);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testexp2(void)
|
||||
{
|
||||
float x;
|
||||
for (x=-11.0;x<24.0;x+=0.0007)
|
||||
{
|
||||
float error = fabs(x-(1.442695040888963387*log(celt_exp2(x))));
|
||||
if (error>0.0002)
|
||||
{
|
||||
fprintf (stderr, "celt_exp2 failed: fabs(x-(1.442695040888963387*log(celt_exp2(x))))>0.0005 (x = %f, error = %f)\n", x,error);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testexp2log2(void)
|
||||
{
|
||||
float x;
|
||||
for (x=-11.0;x<24.0;x+=0.0007)
|
||||
{
|
||||
float error = fabs(x-(celt_log2(celt_exp2(x))));
|
||||
if (error>0.001)
|
||||
{
|
||||
fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_log2(celt_exp2(x))))>0.001 (x = %f, error = %f)\n", x,error);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
void testlog2(void)
|
||||
{
|
||||
celt_word32 x;
|
||||
for (x=8;x<1073741824;x+=(x>>3))
|
||||
{
|
||||
float error = fabs((1.442695040888963387*log(x/16384.0))-celt_log2(x)/1024.0);
|
||||
if (error>0.003)
|
||||
{
|
||||
fprintf (stderr, "celt_log2 failed: x = %ld, error = %f\n", (long)x,error);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testexp2(void)
|
||||
{
|
||||
celt_word16 x;
|
||||
for (x=-32768;x<-30720;x++)
|
||||
{
|
||||
float error1 = fabs(x/2048.0-(1.442695040888963387*log(celt_exp2(x)/65536.0)));
|
||||
float error2 = fabs(exp(0.6931471805599453094*x/2048.0)-celt_exp2(x)/65536.0);
|
||||
if (error1>0.0002&&error2>0.00004)
|
||||
{
|
||||
fprintf (stderr, "celt_exp2 failed: x = "WORD", error1 = %f, error2 = %f\n", x,error1,error2);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testexp2log2(void)
|
||||
{
|
||||
celt_word32 x;
|
||||
for (x=8;x<65536;x+=(x>>3))
|
||||
{
|
||||
float error = fabs(x-0.25*celt_exp2(celt_log2(x)<<1))/16384;
|
||||
if (error>0.004)
|
||||
{
|
||||
fprintf (stderr, "celt_log2/celt_exp2 failed: fabs(x-(celt_exp2(celt_log2(x))))>0.001 (x = %ld, error = %f)\n", (long)x,error);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void testilog2(void)
|
||||
{
|
||||
celt_word32 x;
|
||||
for (x=1;x<=268435455;x+=127)
|
||||
{
|
||||
celt_word32 error = abs(celt_ilog2(x)-(int)floor(log2(x)));
|
||||
if (error!=0)
|
||||
{
|
||||
printf("celt_ilog2 failed: celt_ilog2(x)!=floor(log2(x)) (x = %d, error = %d)\n",x,error);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(void)
|
||||
{
|
||||
testdiv();
|
||||
testsqrt();
|
||||
testlog2();
|
||||
testexp2();
|
||||
testexp2log2();
|
||||
#ifdef FIXED_POINT
|
||||
testilog2();
|
||||
#endif
|
||||
return ret;
|
||||
}
|
||||
@@ -1,169 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#define SKIP_CONFIG_H
|
||||
|
||||
#ifndef CUSTOM_MODES
|
||||
#define CUSTOM_MODES
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include "mdct.h"
|
||||
#define CELT_C
|
||||
#include "../libcelt/stack_alloc.h"
|
||||
|
||||
#include "../libcelt/kiss_fft.c"
|
||||
#include "../libcelt/mdct.c"
|
||||
#include "../libcelt/mathops.c"
|
||||
#include "../libcelt/entcode.c"
|
||||
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.141592653
|
||||
#endif
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
long long celt_mips=0;
|
||||
#endif
|
||||
int ret = 0;
|
||||
void check(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
|
||||
{
|
||||
int bin,k;
|
||||
double errpow=0,sigpow=0;
|
||||
double snr;
|
||||
for (bin=0;bin<nfft/2;++bin) {
|
||||
double ansr = 0;
|
||||
double difr;
|
||||
|
||||
for (k=0;k<nfft;++k) {
|
||||
double phase = 2*M_PI*(k+.5+.25*nfft)*(bin+.5)/nfft;
|
||||
double re = cos(phase);
|
||||
|
||||
re /= nfft/4;
|
||||
|
||||
ansr += in[k] * re;
|
||||
}
|
||||
/*printf ("%f %f\n", ansr, out[bin]);*/
|
||||
difr = ansr - out[bin];
|
||||
errpow += difr*difr;
|
||||
sigpow += ansr*ansr;
|
||||
}
|
||||
snr = 10*log10(sigpow/errpow);
|
||||
printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
|
||||
if (snr<60) {
|
||||
printf( "** poor snr: %f **\n", snr);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
void check_inv(kiss_fft_scalar * in,kiss_fft_scalar * out,int nfft,int isinverse)
|
||||
{
|
||||
int bin,k;
|
||||
double errpow=0,sigpow=0;
|
||||
double snr;
|
||||
for (bin=0;bin<nfft;++bin) {
|
||||
double ansr = 0;
|
||||
double difr;
|
||||
|
||||
for (k=0;k<nfft/2;++k) {
|
||||
double phase = 2*M_PI*(bin+.5+.25*nfft)*(k+.5)/nfft;
|
||||
double re = cos(phase);
|
||||
|
||||
//re *= 2;
|
||||
|
||||
ansr += in[k] * re;
|
||||
}
|
||||
/*printf ("%f %f\n", ansr, out[bin]);*/
|
||||
difr = ansr - out[bin];
|
||||
errpow += difr*difr;
|
||||
sigpow += ansr*ansr;
|
||||
}
|
||||
snr = 10*log10(sigpow/errpow);
|
||||
printf("nfft=%d inverse=%d,snr = %f\n",nfft,isinverse,snr );
|
||||
if (snr<60) {
|
||||
printf( "** poor snr: %f **\n", snr);
|
||||
ret = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void test1d(int nfft,int isinverse)
|
||||
{
|
||||
mdct_lookup cfg;
|
||||
size_t buflen = sizeof(kiss_fft_scalar)*nfft;
|
||||
|
||||
kiss_fft_scalar * in = (kiss_fft_scalar*)malloc(buflen);
|
||||
kiss_fft_scalar * out= (kiss_fft_scalar*)malloc(buflen);
|
||||
celt_word16 * window= (celt_word16*)malloc(sizeof(celt_word16)*nfft/2);
|
||||
int k;
|
||||
|
||||
clt_mdct_init(&cfg, nfft, 0);
|
||||
for (k=0;k<nfft;++k) {
|
||||
in[k] = (rand() % 32768) - 16384;
|
||||
}
|
||||
|
||||
for (k=0;k<nfft/2;++k) {
|
||||
window[k] = Q15ONE;
|
||||
}
|
||||
#ifdef DOUBLE_PRECISION
|
||||
for (k=0;k<nfft;++k) {
|
||||
in[k] *= 32768;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (isinverse)
|
||||
{
|
||||
for (k=0;k<nfft;++k) {
|
||||
in[k] /= nfft;
|
||||
}
|
||||
}
|
||||
|
||||
/*for (k=0;k<nfft;++k) printf("%d %d ", in[k].r, in[k].i);printf("\n");*/
|
||||
|
||||
if (isinverse)
|
||||
{
|
||||
for (k=0;k<nfft;++k)
|
||||
out[k] = 0;
|
||||
clt_mdct_backward(&cfg,in,out, window, nfft/2, 0);
|
||||
check_inv(in,out,nfft,isinverse);
|
||||
} else {
|
||||
clt_mdct_forward(&cfg,in,out,window, nfft/2, 0);
|
||||
check(in,out,nfft,isinverse);
|
||||
}
|
||||
/*for (k=0;k<nfft;++k) printf("%d %d ", out[k].r, out[k].i);printf("\n");*/
|
||||
|
||||
|
||||
free(in);
|
||||
free(out);
|
||||
clt_mdct_clear(&cfg);
|
||||
}
|
||||
|
||||
int main(int argc,char ** argv)
|
||||
{
|
||||
ALLOC_STACK;
|
||||
if (argc>1) {
|
||||
int k;
|
||||
for (k=1;k<argc;++k) {
|
||||
test1d(atoi(argv[k]),0);
|
||||
test1d(atoi(argv[k]),1);
|
||||
}
|
||||
}else{
|
||||
test1d(32,0);
|
||||
test1d(32,1);
|
||||
test1d(256,0);
|
||||
test1d(256,1);
|
||||
test1d(512,0);
|
||||
test1d(512,1);
|
||||
#ifndef RADIX_TWO_ONLY
|
||||
test1d(40,0);
|
||||
test1d(40,1);
|
||||
test1d(120,0);
|
||||
test1d(120,1);
|
||||
test1d(240,0);
|
||||
test1d(240,1);
|
||||
test1d(480,0);
|
||||
test1d(480,1);
|
||||
#endif
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "kiss_fftr.h"
|
||||
#include "_kiss_fft_guts.h"
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CELT_C
|
||||
#include "../libcelt/stack_alloc.h"
|
||||
#include "../libcelt/kiss_fft.c"
|
||||
#include "../libcelt/kiss_fftr.c"
|
||||
|
||||
#ifdef FIXED_DEBUG
|
||||
long long celt_mips=0;
|
||||
#endif
|
||||
int ret=0;
|
||||
|
||||
static
|
||||
kiss_fft_scalar rand_scalar(void)
|
||||
{
|
||||
return (rand()%32767)-16384;
|
||||
}
|
||||
|
||||
static
|
||||
double snr_compare( kiss_fft_cpx * vec1,kiss_fft_scalar * vec2, int n)
|
||||
{
|
||||
int k;
|
||||
double sigpow=1e-10, noisepow=1e-10, err,snr;
|
||||
|
||||
vec1[0].i = vec1[n].r;
|
||||
for (k=0;k<n;++k) {
|
||||
sigpow += (double)vec1[k].r * (double)vec1[k].r +
|
||||
(double)vec1[k].i * (double)vec1[k].i;
|
||||
err = (double)vec1[k].r - (double)vec2[2*k];
|
||||
/*printf ("%f %f\n", (double)vec1[k].r, (double)vec2[2*k]);*/
|
||||
noisepow += err * err;
|
||||
err = (double)vec1[k].i - (double)vec2[2*k+1];
|
||||
/*printf ("%f %f\n", (double)vec1[k].i, (double)vec2[2*k+1]);*/
|
||||
noisepow += err * err;
|
||||
|
||||
}
|
||||
snr = 10*log10( sigpow / noisepow );
|
||||
if (snr<60) {
|
||||
printf( "** poor snr: %f **\n", snr);
|
||||
ret = 1;
|
||||
}
|
||||
return snr;
|
||||
}
|
||||
|
||||
static
|
||||
double snr_compare_scal( kiss_fft_scalar * vec1,kiss_fft_scalar * vec2, int n)
|
||||
{
|
||||
int k;
|
||||
double sigpow=1e-10, noisepow=1e-10, err,snr;
|
||||
|
||||
for (k=0;k<n;++k) {
|
||||
sigpow += (double)vec1[k] * (double)vec1[k];
|
||||
err = (double)vec1[k] - (double)vec2[k];
|
||||
noisepow += err * err;
|
||||
}
|
||||
snr = 10*log10( sigpow / noisepow );
|
||||
if (snr<60) {
|
||||
printf( "\npoor snr: %f\n", snr);
|
||||
ret = 1;
|
||||
}
|
||||
return snr;
|
||||
}
|
||||
#ifdef RADIX_TWO_ONLY
|
||||
#define NFFT 1024
|
||||
#else
|
||||
#define NFFT 8*3*5
|
||||
#endif
|
||||
|
||||
#ifndef NUMFFTS
|
||||
#define NUMFFTS 10000
|
||||
#endif
|
||||
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int i;
|
||||
kiss_fft_cpx cin[NFFT];
|
||||
kiss_fft_cpx cout[NFFT];
|
||||
kiss_fft_scalar fin[NFFT];
|
||||
kiss_fft_scalar sout[NFFT];
|
||||
kiss_fft_cfg kiss_fft_state;
|
||||
kiss_fftr_cfg kiss_fftr_state;
|
||||
|
||||
kiss_fft_scalar rin[NFFT+2];
|
||||
kiss_fft_scalar rout[NFFT+2];
|
||||
kiss_fft_scalar zero;
|
||||
ALLOC_STACK;
|
||||
memset(&zero,0,sizeof(zero) ); // ugly way of setting short,int,float,double, or __m128 to zero
|
||||
|
||||
for (i=0;i<NFFT;++i) {
|
||||
rin[i] = rand_scalar();
|
||||
#if defined(FIXED_POINT) && defined(DOUBLE_PRECISION)
|
||||
rin[i] *= 32768;
|
||||
#endif
|
||||
cin[i].r = rin[i];
|
||||
cin[i].i = zero;
|
||||
}
|
||||
|
||||
kiss_fft_state = kiss_fft_alloc(NFFT,0,0);
|
||||
kiss_fftr_state = kiss_fftr_alloc(NFFT,0,0);
|
||||
kiss_fft(kiss_fft_state,cin,cout);
|
||||
kiss_fftr(kiss_fftr_state,rin,sout);
|
||||
|
||||
printf( "nfft=%d, inverse=%d, snr=%g\n",
|
||||
NFFT,0, snr_compare(cout,sout,(NFFT/2)) );
|
||||
|
||||
memset(cin,0,sizeof(cin));
|
||||
cin[0].r = rand_scalar();
|
||||
cin[NFFT/2].r = rand_scalar();
|
||||
for (i=1;i< NFFT/2;++i) {
|
||||
//cin[i].r = (kiss_fft_scalar)(rand()-RAND_MAX/2);
|
||||
cin[i].r = rand_scalar();
|
||||
cin[i].i = rand_scalar();
|
||||
}
|
||||
|
||||
// conjugate symmetry of real signal
|
||||
for (i=1;i< NFFT/2;++i) {
|
||||
cin[NFFT-i].r = cin[i].r;
|
||||
cin[NFFT-i].i = - cin[i].i;
|
||||
}
|
||||
|
||||
|
||||
#ifdef FIXED_POINT
|
||||
#ifdef DOUBLE_PRECISION
|
||||
for (i=0;i< NFFT;++i) {
|
||||
cin[i].r *= 32768;
|
||||
cin[i].i *= 32768;
|
||||
}
|
||||
#endif
|
||||
for (i=0;i< NFFT;++i) {
|
||||
cin[i].r /= NFFT;
|
||||
cin[i].i /= NFFT;
|
||||
}
|
||||
#endif
|
||||
|
||||
fin[0] = cin[0].r;
|
||||
fin[1] = cin[NFFT/2].r;
|
||||
for (i=1;i< NFFT/2;++i)
|
||||
{
|
||||
fin[2*i] = cin[i].r;
|
||||
fin[2*i+1] = cin[i].i;
|
||||
}
|
||||
|
||||
kiss_ifft(kiss_fft_state,cin,cout);
|
||||
kiss_fftri(kiss_fftr_state,fin,rout);
|
||||
/*
|
||||
printf(" results from inverse kiss_fft : (%f,%f), (%f,%f), (%f,%f), (%f,%f), (%f,%f) ...\n "
|
||||
, (float)cout[0].r , (float)cout[0].i , (float)cout[1].r , (float)cout[1].i , (float)cout[2].r , (float)cout[2].i , (float)cout[3].r , (float)cout[3].i , (float)cout[4].r , (float)cout[4].i
|
||||
);
|
||||
|
||||
printf(" results from inverse kiss_fftr: %f,%f,%f,%f,%f ... \n"
|
||||
,(float)rout[0] ,(float)rout[1] ,(float)rout[2] ,(float)rout[3] ,(float)rout[4]);
|
||||
*/
|
||||
for (i=0;i<NFFT;++i) {
|
||||
sout[i] = cout[i].r;
|
||||
}
|
||||
|
||||
printf( "nfft=%d, inverse=%d, snr=%g\n",
|
||||
NFFT,1, snr_compare_scal(rout,sout,NFFT) );
|
||||
free(kiss_fft_state);
|
||||
free(kiss_fftr_state);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "celt_types.h"
|
||||
#include "bands.h"
|
||||
#include <math.h>
|
||||
#define MAX_SIZE 100
|
||||
|
||||
int ret=0;
|
||||
void test_rotation(int N, int K)
|
||||
{
|
||||
int i;
|
||||
double err = 0, ener = 0, snr, snr0;
|
||||
celt_word16 x0[MAX_SIZE];
|
||||
celt_word16 x1[MAX_SIZE];
|
||||
int nb_rotations = (N+4*K)/(8*K);
|
||||
for (i=0;i<N;i++)
|
||||
x1[i] = x0[i] = rand()%32767-16384;
|
||||
exp_rotation(x1, N, 1, 1, nb_rotations);
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
|
||||
ener += x0[i]*(double)x0[i];
|
||||
}
|
||||
snr0 = 20*log10(ener/err);
|
||||
err = ener = 0;
|
||||
exp_rotation(x1, N, -1, 1, nb_rotations);
|
||||
for (i=0;i<N;i++)
|
||||
{
|
||||
err += (x0[i]-(double)x1[i])*(x0[i]-(double)x1[i]);
|
||||
ener += x0[i]*(double)x0[i];
|
||||
}
|
||||
snr = 20*log10(ener/err);
|
||||
printf ("SNR for size %d (%d pulses) is %f (was %f without inverse)\n", N, K, snr, snr0);
|
||||
if (snr < 60 || snr0 > 20)
|
||||
ret = 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
test_rotation(15, 3);
|
||||
test_rotation(23, 5);
|
||||
test_rotation(50, 3);
|
||||
test_rotation(80, 1);
|
||||
return ret;
|
||||
}
|
||||
@@ -1,204 +0,0 @@
|
||||
/* (C) 2009 Gregory Maxwell
|
||||
|
||||
This test runs pink noise through the encoder and decoder many times
|
||||
while feeding the output back into the input. It checks that after
|
||||
a number of cycles the energy has not increased or decreased by too
|
||||
large an amount.
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt.h"
|
||||
#include "arch.h"
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
int async_tandem(int rate, int frame_size, int channels, int bitrate_min,
|
||||
int bitrate_max)
|
||||
{
|
||||
int error;
|
||||
unsigned char data[648];
|
||||
CELTMode *mode = NULL;
|
||||
CELTEncoder *enc;
|
||||
short carry[2];
|
||||
short pcm[960 * 2];
|
||||
CELTDecoder *dec;
|
||||
int bmin, bmax;
|
||||
float ms;
|
||||
int ret, i, j, bytes_per_frame;
|
||||
int increment = 1;
|
||||
|
||||
bmin = floor((bitrate_min / (rate / (float) frame_size)) / 8.0);
|
||||
bmax = ceil((bitrate_max / (rate / (float) frame_size)) / 8.0);
|
||||
if (bmin < 8)
|
||||
bmin = 8;
|
||||
if (bmax > 640)
|
||||
bmax = 640;
|
||||
if (bmin >= bmax)
|
||||
bmax = bmin + 8;
|
||||
|
||||
increment += (bmax - bmin) / 128;
|
||||
|
||||
printf ("Testing asynchronous tandeming (%dHz, %dch, %d samples, %d - %d bytes).\n",
|
||||
rate, channels, frame_size, bmin, bmax);
|
||||
|
||||
mode = celt_mode_create(rate, frame_size, &error);
|
||||
if (mode == NULL || error) {
|
||||
fprintf(stderr, "Error: failed to create a mode: %s\n", celt_strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
dec = celt_decoder_create_custom(mode, channels, &error);
|
||||
if (error){
|
||||
fprintf(stderr, "Error: celt_decoder_create returned %s\n", celt_strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
enc = celt_encoder_create_custom(mode, channels, &error);
|
||||
if (error){
|
||||
fprintf(stderr, "Error: celt_encoder_create returned %s\n", celt_strerror(error));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for (j = 0; j < frame_size * channels; j++)
|
||||
pcm[j] = 0;
|
||||
|
||||
for (bytes_per_frame = bmin; bytes_per_frame <= bmax;
|
||||
bytes_per_frame += increment) {
|
||||
/*Prime the encoder and decoder */
|
||||
for (i = 0; i < (1024 + (frame_size >> 1)) / frame_size + 2; i++) {
|
||||
|
||||
for (j = 0; j < channels; j++)
|
||||
pcm[j] = pcm[frame_size * channels - (channels - j + 1)];
|
||||
for (j = channels; j < frame_size * channels - 1; j++)
|
||||
pcm[j] = ((rand() % 4096) - 2048) + .9 * pcm[j - channels];
|
||||
|
||||
ret = celt_encode(enc, pcm, frame_size, data, bytes_per_frame);
|
||||
if (ret != bytes_per_frame) {
|
||||
fprintf(stderr, "Error: celt_encode returned %s\n", celt_strerror(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = celt_decode(dec, data, ret, pcm, frame_size);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error: celt_decode returned %s\n", celt_strerror(ret));
|
||||
}
|
||||
}
|
||||
|
||||
for (j = 0; j < channels; j++)
|
||||
pcm[j] = pcm[frame_size * channels - (channels - j)];
|
||||
for (j = channels; j < frame_size * channels - 1; j++)
|
||||
pcm[j] = ((rand() % 4096) - 2048) + .9 * pcm[j - channels];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
for (j = 0; j < channels; j++)
|
||||
carry[j] = pcm[frame_size * channels - (channels - j)];
|
||||
memmove(pcm + channels, pcm, sizeof(short) * frame_size * channels);
|
||||
for (j = 0; j < channels; j++)
|
||||
pcm[j] = carry[j];
|
||||
|
||||
ret = celt_encode(enc, pcm, frame_size, data, bytes_per_frame);
|
||||
if (ret != bytes_per_frame) {
|
||||
fprintf(stderr, "Error: at %d bytes_per_frame celt_encode returned %s\n",
|
||||
bytes_per_frame, celt_strerror(ret));
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = celt_decode(dec, data, ret, pcm, frame_size);
|
||||
if (ret < 0) {
|
||||
fprintf(stderr, "Error: at %d bytes_per_frame celt_decode returned %s\n",
|
||||
bytes_per_frame, celt_strerror(ret));
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
ms = 0;
|
||||
for (j = 0; j < frame_size * channels; j++)
|
||||
ms += pcm[j] * pcm[j];
|
||||
ms = sqrt(ms / (frame_size * channels));
|
||||
if (ms > 7000 || ms < 1000) {
|
||||
fprintf(stderr, "Error: Signal out of expected range. %d %d %d %d %f\n",
|
||||
rate, channels, frame_size, bytes_per_frame, ms);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
celt_encoder_destroy(enc);
|
||||
celt_decoder_destroy(dec);
|
||||
celt_mode_destroy(mode);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
#ifdef CUSTOM_MODES
|
||||
int sizes[8]={960,512,480,256,240,128,120,64};
|
||||
#else
|
||||
int sizes[4]={960,480,240,120};
|
||||
#endif
|
||||
unsigned int seed;
|
||||
int ch, n;
|
||||
|
||||
if (argc > 2) {
|
||||
fprintf(stderr, "Usage: %s [<seed>]\n", argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (argc > 1)
|
||||
seed = atoi(argv[1]);
|
||||
else
|
||||
seed = (time(NULL) ^ ((getpid() % 65536) << 16));
|
||||
|
||||
srand(seed);
|
||||
printf("CELT codec tests. Random seed: %u (%.4X)\n", seed, rand() % 65536);
|
||||
|
||||
#ifdef CUSTOM_MODES
|
||||
for (n = 0; n < 8; n++) {
|
||||
for (ch = 1; ch <= 2; ch++) {
|
||||
async_tandem(48000, sizes[n], ch, 12000 * ch, 128000 * ch);
|
||||
async_tandem(44100, sizes[n], ch, 12000 * ch, 128000 * ch);
|
||||
if(n>0)async_tandem(32000, sizes[n], ch, 12000 * ch, 128000 * ch);
|
||||
if(n>2)async_tandem(16000, sizes[n], ch, 12000 * ch, 64000 * ch);
|
||||
}
|
||||
}
|
||||
#else
|
||||
for (n = 0; n < 4; n++) {
|
||||
for (ch = 1; ch <= 2; ch++) {
|
||||
async_tandem(48000, sizes[n], ch, 12000 * ch, 128000 * ch);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "celt_types.h"
|
||||
#include <stdio.h>
|
||||
|
||||
int main(void)
|
||||
{
|
||||
celt_int16 i = 1;
|
||||
i <<= 14;
|
||||
if (i>>14 != 1)
|
||||
{
|
||||
fprintf(stderr, "celt_int16 isn't 16 bits\n");
|
||||
return 1;
|
||||
}
|
||||
if (sizeof(celt_int16)*2 != sizeof(celt_int32))
|
||||
{
|
||||
fprintf(stderr, "16*2 != 32\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
## Process this file with automake to produce Makefile.in. -*-Makefile-*-
|
||||
|
||||
# $Id: Makefile.am,v 1.11 2004/02/18 06:59:40 jm Exp $
|
||||
|
||||
# Disable automatic dependency tracking if using other tools than gcc and gmake
|
||||
#AUTOMAKE_OPTIONS = no-dependencies
|
||||
|
||||
INCLUDES = -I$(top_srcdir)/libcelt -I$(top_builddir)/ @OGG_CFLAGS@
|
||||
|
||||
EXTRA_DIST = getopt_win.h getopt.c getopt1.c wave_out.c wave_out.h skeleton.h
|
||||
|
||||
include_HEADERS =
|
||||
noinst_HEADERS = wav_io.h
|
||||
|
||||
bin_PROGRAMS = celtenc celtdec
|
||||
|
||||
celtenc_SOURCES = celtenc.c wav_io.c skeleton.c
|
||||
celtenc_LDADD = $(top_builddir)/libcelt/libcelt@LIBCELT_SUFFIX@.la $(OGG_LIBS)
|
||||
|
||||
celtdec_SOURCES = celtdec.c wav_io.c
|
||||
celtdec_LDADD = $(top_builddir)/libcelt/libcelt@LIBCELT_SUFFIX@.la $(OGG_LIBS)
|
||||
@@ -1,429 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2004-2006 Jean-Marc Valin
|
||||
Copyright (C) 2006 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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.
|
||||
*/
|
||||
|
||||
#include "alsa_device.h"
|
||||
#include <stdlib.h>
|
||||
#include <alsa/asoundlib.h>
|
||||
|
||||
struct AlsaDevice_ {
|
||||
char *device_name;
|
||||
int channels;
|
||||
int period;
|
||||
snd_pcm_t *capture_handle;
|
||||
snd_pcm_t *playback_handle;
|
||||
int readN, writeN;
|
||||
struct pollfd *read_fd, *write_fd;
|
||||
};
|
||||
|
||||
#define PERIODS 3
|
||||
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period)
|
||||
{
|
||||
int dir;
|
||||
int err;
|
||||
snd_pcm_hw_params_t *hw_params;
|
||||
snd_pcm_sw_params_t *sw_params;
|
||||
snd_pcm_uframes_t period_size = period;
|
||||
snd_pcm_uframes_t buffer_size = PERIODS*period;
|
||||
static snd_output_t *jcd_out;
|
||||
AlsaDevice *dev = malloc(sizeof(*dev));
|
||||
if (!dev)
|
||||
return NULL;
|
||||
dev->device_name = malloc(1+strlen(device_name));
|
||||
if (!dev->device_name)
|
||||
{
|
||||
free(dev);
|
||||
return NULL;
|
||||
}
|
||||
strcpy(dev->device_name, device_name);
|
||||
dev->channels = channels;
|
||||
dev->period = period;
|
||||
err = snd_output_stdio_attach(&jcd_out, stdout, 0);
|
||||
|
||||
if ((err = snd_pcm_open (&dev->capture_handle, dev->device_name, SND_PCM_STREAM_CAPTURE, 0)) < 0) {
|
||||
fprintf (stderr, "cannot open audio device %s (%s)\n",
|
||||
dev->device_name,
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_any (dev->capture_handle, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_access (dev->capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
fprintf (stderr, "cannot set access type (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_format (dev->capture_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
||||
fprintf (stderr, "cannot set sample format (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_rate_near (dev->capture_handle, hw_params, &rate, 0)) < 0) {
|
||||
fprintf (stderr, "cannot set sample rate (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
/*fprintf (stderr, "rate = %d\n", rate);*/
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_channels (dev->capture_handle, hw_params, channels)) < 0) {
|
||||
fprintf (stderr, "cannot set channel count (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
period_size = period;
|
||||
dir = 0;
|
||||
if ((err = snd_pcm_hw_params_set_period_size_near (dev->capture_handle, hw_params, &period_size, &dir)) < 0) {
|
||||
fprintf (stderr, "cannot set period size (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_periods (dev->capture_handle, hw_params, PERIODS, 0)) < 0) {
|
||||
fprintf (stderr, "cannot set number of periods (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
buffer_size = period_size * PERIODS;
|
||||
dir=0;
|
||||
if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->capture_handle, hw_params, &buffer_size)) < 0) {
|
||||
fprintf (stderr, "cannot set buffer time (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params (dev->capture_handle, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot set capture parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
/*snd_pcm_dump_setup(dev->capture_handle, jcd_out);*/
|
||||
snd_pcm_hw_params_free (hw_params);
|
||||
|
||||
if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
|
||||
fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_current (dev->capture_handle, sw_params)) < 0) {
|
||||
fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_set_avail_min (dev->capture_handle, sw_params, period)) < 0) {
|
||||
fprintf (stderr, "cannot set minimum available count (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params (dev->capture_handle, sw_params)) < 0) {
|
||||
fprintf (stderr, "cannot set software parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
if ((err = snd_pcm_open (&dev->playback_handle, dev->device_name, SND_PCM_STREAM_PLAYBACK, 0)) < 0) {
|
||||
fprintf (stderr, "cannot open audio device %s (%s)\n",
|
||||
dev->device_name,
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot allocate hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_any (dev->playback_handle, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot initialize hardware parameter structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_access (dev->playback_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {
|
||||
fprintf (stderr, "cannot set access type (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_format (dev->playback_handle, hw_params, SND_PCM_FORMAT_S16_LE)) < 0) {
|
||||
fprintf (stderr, "cannot set sample format (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_rate_near (dev->playback_handle, hw_params, &rate, 0)) < 0) {
|
||||
fprintf (stderr, "cannot set sample rate (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
/*fprintf (stderr, "rate = %d\n", rate);*/
|
||||
|
||||
if ((err = snd_pcm_hw_params_set_channels (dev->playback_handle, hw_params, channels)) < 0) {
|
||||
fprintf (stderr, "cannot set channel count (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
period_size = period;
|
||||
dir = 0;
|
||||
if ((err = snd_pcm_hw_params_set_period_size_near (dev->playback_handle, hw_params, &period_size, &dir)) < 0) {
|
||||
fprintf (stderr, "cannot set period size (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_hw_params_set_periods (dev->playback_handle, hw_params, PERIODS, 0)) < 0) {
|
||||
fprintf (stderr, "cannot set number of periods (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
buffer_size = period_size * PERIODS;
|
||||
dir=0;
|
||||
if ((err = snd_pcm_hw_params_set_buffer_size_near (dev->playback_handle, hw_params, &buffer_size)) < 0) {
|
||||
fprintf (stderr, "cannot set buffer time (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
if ((err = snd_pcm_hw_params (dev->playback_handle, hw_params)) < 0) {
|
||||
fprintf (stderr, "cannot set playback parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/*snd_pcm_dump_setup(dev->playback_handle, jcd_out);*/
|
||||
snd_pcm_hw_params_free (hw_params);
|
||||
|
||||
|
||||
if ((err = snd_pcm_sw_params_malloc (&sw_params)) < 0) {
|
||||
fprintf (stderr, "cannot allocate software parameters structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_current (dev->playback_handle, sw_params)) < 0) {
|
||||
fprintf (stderr, "cannot initialize software parameters structure (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_set_avail_min (dev->playback_handle, sw_params, period)) < 0) {
|
||||
fprintf (stderr, "cannot set minimum available count (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params_set_start_threshold (dev->playback_handle, sw_params, period)) < 0) {
|
||||
fprintf (stderr, "cannot set start mode (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_sw_params (dev->playback_handle, sw_params)) < 0) {
|
||||
fprintf (stderr, "cannot set software parameters (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
|
||||
snd_pcm_link(dev->capture_handle, dev->playback_handle);
|
||||
if ((err = snd_pcm_prepare (dev->capture_handle)) < 0) {
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
if ((err = snd_pcm_prepare (dev->playback_handle)) < 0) {
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
dev->readN = snd_pcm_poll_descriptors_count(dev->capture_handle);
|
||||
dev->writeN = snd_pcm_poll_descriptors_count(dev->playback_handle);
|
||||
|
||||
dev->read_fd = malloc(dev->readN*sizeof(*dev->read_fd));
|
||||
/*printf ("descriptors: %d %d\n", dev->readN, dev->writeN);*/
|
||||
if (snd_pcm_poll_descriptors(dev->capture_handle, dev->read_fd, dev->readN) != dev->readN)
|
||||
{
|
||||
fprintf (stderr, "cannot obtain capture file descriptors (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
|
||||
dev->write_fd = malloc(dev->writeN*sizeof(*dev->read_fd));
|
||||
if (snd_pcm_poll_descriptors(dev->playback_handle, dev->write_fd, dev->writeN) != dev->writeN)
|
||||
{
|
||||
fprintf (stderr, "cannot obtain playback file descriptors (%s)\n",
|
||||
snd_strerror (err));
|
||||
assert(0);
|
||||
}
|
||||
return dev;
|
||||
}
|
||||
|
||||
void alsa_device_close(AlsaDevice *dev)
|
||||
{
|
||||
snd_pcm_close(dev->capture_handle);
|
||||
snd_pcm_close(dev->playback_handle);
|
||||
free(dev->device_name);
|
||||
free(dev);
|
||||
}
|
||||
|
||||
int alsa_device_read(AlsaDevice *dev, short *pcm, int len)
|
||||
{
|
||||
int err;
|
||||
/*fprintf (stderr, "-");*/
|
||||
if ((err = snd_pcm_readi (dev->capture_handle, pcm, len)) != len)
|
||||
{
|
||||
if (err<0)
|
||||
{
|
||||
//fprintf(stderr, "error %d, EPIPE = %d\n", err, EPIPE);
|
||||
if (err == -EPIPE)
|
||||
{
|
||||
fprintf (stderr, "An overrun has occured, reseting capture\n");
|
||||
} else
|
||||
{
|
||||
fprintf (stderr, "read from audio interface failed (%s)\n",
|
||||
snd_strerror (err));
|
||||
}
|
||||
if ((err = snd_pcm_prepare (dev->capture_handle)) < 0)
|
||||
{
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
}
|
||||
if ((err = snd_pcm_start (dev->capture_handle)) < 0)
|
||||
{
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
}
|
||||
/*alsa_device_read(dev,pcm,len);*/
|
||||
} else {
|
||||
fprintf (stderr, "Couldn't read as many samples as I wanted (%d instead of %d)\n", err, len);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_device_write(AlsaDevice *dev, const short *pcm, int len)
|
||||
{
|
||||
int err;
|
||||
/*fprintf (stderr, "+");*/
|
||||
if ((err = snd_pcm_writei (dev->playback_handle, pcm, len)) != len)
|
||||
{
|
||||
if (err<0)
|
||||
{
|
||||
if (err == -EPIPE)
|
||||
{
|
||||
fprintf (stderr, "An underrun has occured, reseting playback, len=%d\n", len);
|
||||
} else
|
||||
{
|
||||
fprintf (stderr, "write to audio interface failed (%s)\n",
|
||||
snd_strerror (err));
|
||||
}
|
||||
if ((err = snd_pcm_prepare (dev->playback_handle)) < 0)
|
||||
{
|
||||
fprintf (stderr, "cannot prepare audio interface for use (%s)\n",
|
||||
snd_strerror (err));
|
||||
}
|
||||
} else {
|
||||
fprintf (stderr, "Couldn't write as many samples as I wanted (%d instead of %d)\n", err, len);
|
||||
}
|
||||
/*alsa_device_write(dev,pcm,len);*/
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int alsa_device_capture_ready(AlsaDevice *dev, struct pollfd *pfds, unsigned int nfds)
|
||||
{
|
||||
unsigned short revents=0;
|
||||
int err;
|
||||
if ((err = snd_pcm_poll_descriptors_revents(dev->capture_handle, pfds, dev->readN, &revents)) < 0)
|
||||
{
|
||||
//cerr << "error in snd_pcm_poll_descriptors_revents for capture: " << snd_strerror (err) << endl;
|
||||
//FIXME: This is a kludge
|
||||
fprintf (stderr, "error in alsa_device_capture_ready: %s\n", snd_strerror (err));
|
||||
return pfds[0].revents & POLLIN;
|
||||
}
|
||||
//cerr << (revents & POLLERR) << endl;
|
||||
return revents & POLLIN;
|
||||
}
|
||||
|
||||
int alsa_device_playback_ready(AlsaDevice *dev, struct pollfd *pfds, unsigned int nfds)
|
||||
{
|
||||
unsigned short revents=0;
|
||||
int err;
|
||||
if ((err = snd_pcm_poll_descriptors_revents(dev->playback_handle, pfds+dev->readN, dev->writeN, &revents)) < 0)
|
||||
{
|
||||
//cerr << "error in snd_pcm_poll_descriptors_revents for playback: " << snd_strerror (err) << endl;
|
||||
//FIXME: This is a kludge
|
||||
fprintf (stderr, "error in alsa_device_playback_ready: %s\n", snd_strerror (err));
|
||||
return pfds[1].revents & POLLOUT;
|
||||
}
|
||||
//cerr << (revents & POLLERR) << endl;
|
||||
return revents & POLLOUT;
|
||||
}
|
||||
|
||||
void alsa_device_start(AlsaDevice *dev)
|
||||
{
|
||||
int i;
|
||||
short pcm[dev->period*dev->channels];
|
||||
for (i=0;i<dev->period*dev->channels;i++)
|
||||
pcm[i] = 0;
|
||||
alsa_device_write(dev, pcm, dev->period);
|
||||
alsa_device_write(dev, pcm, dev->period);
|
||||
snd_pcm_start(dev->capture_handle);
|
||||
snd_pcm_start(dev->playback_handle);
|
||||
}
|
||||
|
||||
int alsa_device_nfds(AlsaDevice *dev)
|
||||
{
|
||||
return dev->writeN+dev->readN;
|
||||
}
|
||||
|
||||
void alsa_device_getfds(AlsaDevice *dev, struct pollfd *pfds, unsigned int nfds)
|
||||
{
|
||||
int i;
|
||||
assert (nfds >= dev->writeN+dev->readN);
|
||||
for (i=0;i<dev->readN;i++)
|
||||
pfds[i] = dev->read_fd[i];
|
||||
for (i=0;i<dev->writeN;i++)
|
||||
pfds[i+dev->readN] = dev->write_fd[i];
|
||||
}
|
||||
@@ -1,66 +0,0 @@
|
||||
/*
|
||||
Copyright (C) 2004-2006 Jean-Marc Valin
|
||||
Copyright (C) 2006 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
|
||||
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 ALSA_DEVICE_H
|
||||
#define ALSA_DEVICE_H
|
||||
|
||||
#include <sys/poll.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct AlsaDevice_;
|
||||
|
||||
typedef struct AlsaDevice_ AlsaDevice;
|
||||
|
||||
AlsaDevice *alsa_device_open(char *device_name, unsigned int rate, int channels, int period);
|
||||
|
||||
void alsa_device_close(AlsaDevice *dev);
|
||||
|
||||
int alsa_device_read(AlsaDevice *dev, short *pcm, int len);
|
||||
|
||||
int alsa_device_write(AlsaDevice *dev, const short *pcm, int len);
|
||||
|
||||
int alsa_device_capture_ready(AlsaDevice *dev, struct pollfd *pfds, unsigned int nfds);
|
||||
|
||||
int alsa_device_playback_ready(AlsaDevice *dev, struct pollfd *pfds, unsigned int nfds);
|
||||
|
||||
void alsa_device_start(AlsaDevice *dev);
|
||||
|
||||
int alsa_device_nfds(AlsaDevice *dev);
|
||||
|
||||
void alsa_device_getfds(AlsaDevice *dev, struct pollfd *pfds, unsigned int nfds);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,256 +0,0 @@
|
||||
/***************************************************************************
|
||||
Copyright (C) 2004-2006 by Jean-Marc Valin
|
||||
Copyright (C) 2006 Commonwealth Scientific and Industrial Research
|
||||
Organisation (CSIRO) Australia
|
||||
Copyright (C) 2008-2009 Gregory Maxwell
|
||||
Copyright (c) 2007-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 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.
|
||||
|
||||
****************************************************************************/
|
||||
|
||||
/* Compile with something like:
|
||||
* gcc -oceltclient celtclient.c alsa_device.c -I../libcelt/ -lspeexdsp -lasound -lcelt -lm
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h> /* close() */
|
||||
#include <string.h> /* memset() */
|
||||
|
||||
#include "alsa_device.h"
|
||||
#include <celt.h>
|
||||
#include <speex/speex_jitter.h>
|
||||
|
||||
#include <sched.h>
|
||||
|
||||
#define MAX_MSG 1500
|
||||
#define SAMPLING_RATE 48000
|
||||
#define FRAME_SIZE 256
|
||||
#define PACKETSIZE 43
|
||||
#define CHANNELS 1
|
||||
#define HAS_SPEEX_AEC
|
||||
|
||||
#if CHANNELS == 2
|
||||
/* FIXME: The Speex AEC has multichannel support; but that API isn't being
|
||||
used here yet. */
|
||||
#undef HAS_SPEEX_AEC
|
||||
#endif
|
||||
|
||||
#ifdef HAS_SPEEX_AEC
|
||||
#include <speex/speex_echo.h>
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
int sd, rc, n;
|
||||
int i;
|
||||
struct sockaddr_in cliAddr, remoteAddr;
|
||||
char msg[MAX_MSG];
|
||||
struct hostent *h;
|
||||
int local_port, remote_port;
|
||||
int nfds;
|
||||
struct pollfd *pfds;
|
||||
AlsaDevice *audio_dev;
|
||||
int tmp;
|
||||
|
||||
if (argc != 5)
|
||||
{
|
||||
fprintf(stderr, "Usage %s plughw:0,0 remote_host local_udp_port remote_udp_port\n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
h = gethostbyname(argv[2]);
|
||||
if(h==NULL) {
|
||||
fprintf(stderr, "%s: unknown host '%s' \n", argv[0], argv[2]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
local_port = atoi(argv[3]);
|
||||
remote_port = atoi(argv[4]);
|
||||
|
||||
printf("%s: sending data to '%s' (IP : %s) \n", argv[0], h->h_name,
|
||||
inet_ntoa(*(struct in_addr *)h->h_addr_list[0]));
|
||||
|
||||
{
|
||||
remoteAddr.sin_family = h->h_addrtype;
|
||||
memcpy((char *) &remoteAddr.sin_addr.s_addr,
|
||||
h->h_addr_list[0], h->h_length);
|
||||
remoteAddr.sin_port = htons(remote_port);
|
||||
}
|
||||
/* socket creation */
|
||||
sd=socket(AF_INET, SOCK_DGRAM, 0);
|
||||
if(sd<0) {
|
||||
printf("%s: cannot open socket \n",argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* bind any port */
|
||||
cliAddr.sin_family = AF_INET;
|
||||
cliAddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
cliAddr.sin_port = htons(local_port);
|
||||
|
||||
rc = bind(sd, (struct sockaddr *) &cliAddr, sizeof(cliAddr));
|
||||
if(rc<0) {
|
||||
printf("%s: cannot bind port\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Setup audio device */
|
||||
audio_dev = alsa_device_open(argv[1], SAMPLING_RATE, CHANNELS, FRAME_SIZE);
|
||||
|
||||
/* Setup the encoder and decoder in wideband */
|
||||
CELTEncoder *enc_state;
|
||||
CELTDecoder *dec_state;
|
||||
CELTMode *mode = celt_mode_create(SAMPLING_RATE, FRAME_SIZE, NULL);
|
||||
enc_state = celt_encoder_create_custom(mode, CHANNELS, NULL);
|
||||
dec_state = celt_decoder_create_custom(mode, CHANNELS, NULL);
|
||||
struct sched_param param;
|
||||
/*param.sched_priority = 40; */
|
||||
param.sched_priority = sched_get_priority_min(SCHED_FIFO);
|
||||
if (sched_setscheduler(0,SCHED_FIFO,¶m))
|
||||
perror("sched_setscheduler");
|
||||
|
||||
int send_timestamp = 0;
|
||||
int recv_started=0;
|
||||
|
||||
/* Setup all file descriptors for poll()ing */
|
||||
nfds = alsa_device_nfds(audio_dev);
|
||||
pfds = malloc(sizeof(*pfds)*(nfds+1));
|
||||
alsa_device_getfds(audio_dev, pfds, nfds);
|
||||
pfds[nfds].fd = sd;
|
||||
pfds[nfds].events = POLLIN;
|
||||
|
||||
/* Setup jitter buffer using decoder */
|
||||
JitterBuffer *jitter;
|
||||
jitter = jitter_buffer_init(FRAME_SIZE);
|
||||
tmp = FRAME_SIZE;
|
||||
jitter_buffer_ctl(jitter, JITTER_BUFFER_SET_MARGIN, &tmp);
|
||||
#ifdef HAS_SPEEX_AEC
|
||||
/* Echo canceller with 200 ms tail length */
|
||||
SpeexEchoState *echo_state = speex_echo_state_init(FRAME_SIZE, 10*FRAME_SIZE);
|
||||
tmp = SAMPLING_RATE;
|
||||
speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &tmp);
|
||||
#endif
|
||||
alsa_device_start(audio_dev);
|
||||
|
||||
/* Infinite loop on capture, playback and receiving packets */
|
||||
while (1)
|
||||
{
|
||||
/* Wait for either 1) capture 2) playback 3) socket data */
|
||||
poll(pfds, nfds+1, -1);
|
||||
/* Received packets */
|
||||
if (pfds[nfds].revents & POLLIN)
|
||||
{
|
||||
n = recv(sd, msg, MAX_MSG, 0);
|
||||
int recv_timestamp = ((int*)msg)[0];
|
||||
|
||||
JitterBufferPacket packet;
|
||||
packet.data = msg+4;
|
||||
packet.len = n-4;
|
||||
packet.timestamp = recv_timestamp;
|
||||
packet.span = FRAME_SIZE;
|
||||
packet.sequence = 0;
|
||||
/* Put content of the packet into the jitter buffer, except for the pseudo-header */
|
||||
jitter_buffer_put(jitter, &packet);
|
||||
recv_started = 1;
|
||||
|
||||
}
|
||||
/* Ready to play a frame (playback) */
|
||||
if (alsa_device_playback_ready(audio_dev, pfds, nfds))
|
||||
{
|
||||
short pcm[FRAME_SIZE*CHANNELS];
|
||||
if (recv_started)
|
||||
{
|
||||
JitterBufferPacket packet;
|
||||
/* Get audio from the jitter buffer */
|
||||
packet.data = msg;
|
||||
packet.len = MAX_MSG;
|
||||
jitter_buffer_tick(jitter);
|
||||
jitter_buffer_get(jitter, &packet, FRAME_SIZE, NULL);
|
||||
if (packet.len==0)
|
||||
packet.data=NULL;
|
||||
celt_decode(dec_state, packet.data, packet.len, pcm, FRAME_SIZE);
|
||||
} else {
|
||||
for (i=0;i<FRAME_SIZE*CHANNELS;i++)
|
||||
pcm[i] = 0;
|
||||
}
|
||||
/* Playback the audio and reset the echo canceller if we got an underrun */
|
||||
|
||||
#ifdef HAS_SPEEX_AEC
|
||||
if (alsa_device_write(audio_dev, pcm, FRAME_SIZE))
|
||||
speex_echo_state_reset(echo_state);
|
||||
/* Put frame into playback buffer */
|
||||
speex_echo_playback(echo_state, pcm);
|
||||
#else
|
||||
alsa_device_write(audio_dev, pcm, FRAME_SIZE);
|
||||
#endif
|
||||
}
|
||||
/* Audio available from the soundcard (capture) */
|
||||
if (alsa_device_capture_ready(audio_dev, pfds, nfds))
|
||||
{
|
||||
short pcm[FRAME_SIZE*CHANNELS], pcm2[FRAME_SIZE*CHANNELS];
|
||||
char outpacket[MAX_MSG];
|
||||
/* Get audio from the soundcard */
|
||||
alsa_device_read(audio_dev, pcm, FRAME_SIZE);
|
||||
|
||||
#ifdef HAS_SPEEX_AEC
|
||||
/* Perform echo cancellation */
|
||||
speex_echo_capture(echo_state, pcm, pcm2);
|
||||
for (i=0;i<FRAME_SIZE*CHANNELS;i++)
|
||||
pcm[i] = pcm2[i];
|
||||
#endif
|
||||
/* Encode */
|
||||
celt_encode(enc_state, pcm, FRAME_SIZE, outpacket+4, PACKETSIZE);
|
||||
|
||||
/* Pseudo header: four null bytes and a 32-bit timestamp */
|
||||
((int*)outpacket)[0] = send_timestamp;
|
||||
send_timestamp += FRAME_SIZE;
|
||||
rc = sendto(sd, outpacket, PACKETSIZE+4, 0,
|
||||
(struct sockaddr *) &remoteAddr,
|
||||
sizeof(remoteAddr));
|
||||
|
||||
if(rc<0) {
|
||||
perror("cannot send to socket");
|
||||
close(sd);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user