First Commit
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
|
||||
=====================================================================
|
||||
|
||||
I've incorporated FLAC directly into the JUCE codebase because it makes
|
||||
things much easier than having to make all your builds link correctly to
|
||||
the appropriate libraries on every different platform.
|
||||
|
||||
I've made minimal changes to the FLAC code - just tweaked a few include paths
|
||||
to make it build smoothly, added some headers to allow you to turn off FLAC
|
||||
compilation, and commented-out a couple of unused bits of code.
|
||||
|
||||
=====================================================================
|
||||
|
||||
|
||||
The following license is the BSD-style license that comes with the
|
||||
Flac distribution, and which applies just to the files I've
|
||||
included in this directory. For more info, and to get the rest of the
|
||||
distribution, visit the Flac homepage: https://xiph.org/flac/
|
||||
|
||||
=====================================================================
|
||||
|
||||
libFLAC - Free Lossless Audio Codec library
|
||||
Copyright (C) 2000-2009 Josh Coalson
|
||||
Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.Org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,55 @@
|
||||
The files in this directory are from the FLAC 1.4.3 release downloaded in a tarball from
|
||||
https://github.com/xiph/flac/releases/tag/1.4.3
|
||||
|
||||
They have been modified as little as possible, so that when they are included by
|
||||
juce_FlacAudioFormat.cpp they compile without warnings and work correctly on the supported
|
||||
platforms.
|
||||
|
||||
Below I will refer to the contents of the tarball as RELEASE and to our repo as JUCE.
|
||||
|
||||
The steps carried out when including the 1.4.3 version
|
||||
* The contents of RELEASE/include/FLAC and RELEASE/include/share were copied to
|
||||
JUCE/[..]/codecs/flac
|
||||
* The contents of RELEASE/libFLAC were copied to JUCE/[..]/codecs/flac/libFLAC
|
||||
* The includes in all these files were retargeted, to be relative to the file that does the
|
||||
including, so that we don't have to rely on e.g. flac/libFLAC/include being among the include
|
||||
directories, like it is when building FLAC with the official makefiles. All this retargeting is
|
||||
done per-line with a Python script. All the rules used for the retargeting can be seen in the code
|
||||
excerpt at [1].
|
||||
* Then I will do a compile/test/modify loop, until it works and compiles without warnings. The
|
||||
changes made are mostly C to C++ conversions like adding explicit casts, or fixing warnings, like
|
||||
eliminating always true branches that refer to preprocessor defines.
|
||||
* Then I delete all library files, and only re-add those that are needed for successful compilation.
|
||||
This delete step is propagated back to older commits, so that unneeded files are never added to
|
||||
the GIT repo.
|
||||
|
||||
|
||||
[1]: Code excerpt used for retargeting includes in the copied files
|
||||
```
|
||||
def transform(path: Path, line: str) -> str:
|
||||
if path.match("libFLAC/*"):
|
||||
line = line.replace('#include "private', '#include "include/private')
|
||||
line = line.replace('#include "protected', '#include "include/protected')
|
||||
line = line.replace('#include "share/', '#include "../')
|
||||
line = line.replace('#include "FLAC/', '#include "../')
|
||||
|
||||
if path.match("libFLAC/include/private/*") or path.match(
|
||||
"libFLAC/include/public/*"
|
||||
):
|
||||
line = line.replace('#include "share/', '#include "../../../')
|
||||
line = line.replace('#include "FLAC/', '#include "../../../')
|
||||
|
||||
if path.match("*"):
|
||||
line = line.replace('#include "share/', '#include "')
|
||||
|
||||
if path.match("libFLAC/include/private/*"):
|
||||
line = line.replace('#include "private/', '#include "')
|
||||
|
||||
if path.match("libFLAC/include/protected/*"):
|
||||
line = line.replace('#include "private/', '#include "../private/')
|
||||
line = line.replace('#include "FLAC/', '#include "../../../')
|
||||
|
||||
line = line.replace('#include "include/private/macros.h"', "")
|
||||
|
||||
return line
|
||||
```
|
||||
@@ -0,0 +1,454 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ALL_H
|
||||
#define FLAC__ALL_H
|
||||
|
||||
#ifndef FLAC__HAS_OGG
|
||||
#define FLAC__HAS_OGG 0
|
||||
#endif
|
||||
|
||||
#include "export.h"
|
||||
|
||||
#include "assert.h"
|
||||
#include "callback.h"
|
||||
#include "format.h"
|
||||
#include "metadata.h"
|
||||
#include "ordinals.h"
|
||||
#include "stream_decoder.h"
|
||||
#include "stream_encoder.h"
|
||||
|
||||
/** \mainpage
|
||||
*
|
||||
* \section intro Introduction
|
||||
*
|
||||
* This is the documentation for the FLAC C and C++ APIs. It is
|
||||
* highly interconnected; this introduction should give you a top
|
||||
* level idea of the structure and how to find the information you
|
||||
* need. As a prerequisite you should have at least a basic
|
||||
* knowledge of the FLAC format, documented
|
||||
* <A HREF="https://xiph.org/flac/format.html">here</A>.
|
||||
*
|
||||
* \section c_api FLAC C API
|
||||
*
|
||||
* The FLAC C API is the interface to libFLAC, a set of structures
|
||||
* describing the components of FLAC streams, and functions for
|
||||
* encoding and decoding streams, as well as manipulating FLAC
|
||||
* metadata in files. The public include files will be installed
|
||||
* in your include area (for example /usr/include/FLAC/...).
|
||||
*
|
||||
* By writing a little code and linking against libFLAC, it is
|
||||
* relatively easy to add FLAC support to another program. The
|
||||
* library is licensed under <A HREF="https://xiph.org/flac/license.html">Xiph's BSD license</A>.
|
||||
* Complete source code of libFLAC as well as the command-line
|
||||
* encoder and plugins is available and is a useful source of
|
||||
* examples.
|
||||
*
|
||||
* Aside from encoders and decoders, libFLAC provides a powerful
|
||||
* metadata interface for manipulating metadata in FLAC files. It
|
||||
* allows the user to add, delete, and modify FLAC metadata blocks
|
||||
* and it can automatically take advantage of PADDING blocks to avoid
|
||||
* rewriting the entire FLAC file when changing the size of the
|
||||
* metadata.
|
||||
*
|
||||
* libFLAC usually only requires the standard C library and C math
|
||||
* library. In particular, threading is not used so there is no
|
||||
* dependency on a thread library. However, libFLAC does not use
|
||||
* global variables and should be thread-safe.
|
||||
*
|
||||
* libFLAC also supports encoding to and decoding from Ogg FLAC.
|
||||
* However the metadata editing interfaces currently have limited
|
||||
* read-only support for Ogg FLAC files.
|
||||
*
|
||||
* \section cpp_api FLAC C++ API
|
||||
*
|
||||
* The FLAC C++ API is a set of classes that encapsulate the
|
||||
* structures and functions in libFLAC. They provide slightly more
|
||||
* functionality with respect to metadata but are otherwise
|
||||
* equivalent. For the most part, they share the same usage as
|
||||
* their counterparts in libFLAC, and the FLAC C API documentation
|
||||
* can be used as a supplement. The public include files
|
||||
* for the C++ API will be installed in your include area (for
|
||||
* example /usr/include/FLAC++/...).
|
||||
*
|
||||
* libFLAC++ is also licensed under
|
||||
* <A HREF="https://xiph.org/flac/license.html">Xiph's BSD license</A>.
|
||||
*
|
||||
* \section getting_started Getting Started
|
||||
*
|
||||
* A good starting point for learning the API is to browse through
|
||||
* the <A HREF="modules.html">modules</A>. Modules are logical
|
||||
* groupings of related functions or classes, which correspond roughly
|
||||
* to header files or sections of header files. Each module includes a
|
||||
* detailed description of the general usage of its functions or
|
||||
* classes.
|
||||
*
|
||||
* From there you can go on to look at the documentation of
|
||||
* individual functions. You can see different views of the individual
|
||||
* functions through the links in top bar across this page.
|
||||
*
|
||||
* If you prefer a more hands-on approach, you can jump right to some
|
||||
* <A HREF="https://xiph.org/flac/documentation_example_code.html">example code</A>.
|
||||
*
|
||||
* \section porting_guide Porting Guide
|
||||
*
|
||||
* Starting with FLAC 1.1.3 a \link porting Porting Guide \endlink
|
||||
* has been introduced which gives detailed instructions on how to
|
||||
* port your code to newer versions of FLAC.
|
||||
*
|
||||
* \section embedded_developers Embedded Developers
|
||||
*
|
||||
* libFLAC has grown larger over time as more functionality has been
|
||||
* included, but much of it may be unnecessary for a particular embedded
|
||||
* implementation. Unused parts may be pruned by some simple editing of
|
||||
* src/libFLAC/Makefile.am. In general, the decoders, encoders, and
|
||||
* metadata interface are all independent from each other.
|
||||
*
|
||||
* It is easiest to just describe the dependencies:
|
||||
*
|
||||
* - All modules depend on the \link flac_format Format \endlink module.
|
||||
* - The decoders and encoders depend on the bitbuffer.
|
||||
* - The decoder is independent of the encoder. The encoder uses the
|
||||
* decoder because of the verify feature, but this can be removed if
|
||||
* not needed.
|
||||
* - Parts of the metadata interface require the stream decoder (but not
|
||||
* the encoder).
|
||||
* - Ogg support is selectable through the compile time macro
|
||||
* \c FLAC__HAS_OGG.
|
||||
*
|
||||
* For example, if your application only requires the stream decoder, no
|
||||
* encoder, and no metadata interface, you can remove the stream encoder
|
||||
* and the metadata interface, which will greatly reduce the size of the
|
||||
* library.
|
||||
*
|
||||
* Also, there are several places in the libFLAC code with comments marked
|
||||
* with "OPT:" where a \#define can be changed to enable code that might be
|
||||
* faster on a specific platform. Experimenting with these can yield faster
|
||||
* binaries.
|
||||
*/
|
||||
|
||||
/** \defgroup porting Porting Guide for New Versions
|
||||
*
|
||||
* This module describes differences in the library interfaces from
|
||||
* version to version. It assists in the porting of code that uses
|
||||
* the libraries to newer versions of FLAC.
|
||||
*
|
||||
* One simple facility for making porting easier that has been added
|
||||
* in FLAC 1.1.3 is a set of \#defines in \c export.h of each
|
||||
* library's includes (e.g. \c include/FLAC/export.h). The
|
||||
* \#defines mirror the libraries'
|
||||
* <A HREF="http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning">libtool version numbers</A>,
|
||||
* e.g. in libFLAC there are \c FLAC_API_VERSION_CURRENT,
|
||||
* \c FLAC_API_VERSION_REVISION, and \c FLAC_API_VERSION_AGE.
|
||||
* These can be used to support multiple versions of an API during the
|
||||
* transition phase, e.g.
|
||||
*
|
||||
* \code
|
||||
* #if !defined(FLAC_API_VERSION_CURRENT) || FLAC_API_VERSION_CURRENT <= 7
|
||||
* legacy code
|
||||
* #else
|
||||
* new code
|
||||
* #endif
|
||||
* \endcode
|
||||
*
|
||||
* The source will work for multiple versions and the legacy code can
|
||||
* easily be removed when the transition is complete.
|
||||
*
|
||||
* Another available symbol is FLAC_API_SUPPORTS_OGG_FLAC (defined in
|
||||
* include/FLAC/export.h), which can be used to determine whether or not
|
||||
* the library has been compiled with support for Ogg FLAC. This is
|
||||
* simpler than trying to call an Ogg init function and catching the
|
||||
* error.
|
||||
*/
|
||||
|
||||
/** \defgroup porting_1_1_2_to_1_1_3 Porting from FLAC 1.1.2 to 1.1.3
|
||||
* \ingroup porting
|
||||
*
|
||||
* \brief
|
||||
* This module describes porting from FLAC 1.1.2 to FLAC 1.1.3.
|
||||
*
|
||||
* The main change between the APIs in 1.1.2 and 1.1.3 is that they have
|
||||
* been simplified. First, libOggFLAC has been merged into libFLAC and
|
||||
* libOggFLAC++ has been merged into libFLAC++. Second, both the three
|
||||
* decoding layers and three encoding layers have been merged into a
|
||||
* single stream decoder and stream encoder. That is, the functionality
|
||||
* of FLAC__SeekableStreamDecoder and FLAC__FileDecoder has been merged
|
||||
* into FLAC__StreamDecoder, and FLAC__SeekableStreamEncoder and
|
||||
* FLAC__FileEncoder into FLAC__StreamEncoder. Only the
|
||||
* FLAC__StreamDecoder and FLAC__StreamEncoder remain. What this means
|
||||
* is there is now a single API that can be used to encode or decode
|
||||
* streams to/from native FLAC or Ogg FLAC and the single API can work
|
||||
* on both seekable and non-seekable streams.
|
||||
*
|
||||
* Instead of creating an encoder or decoder of a certain layer, now the
|
||||
* client will always create a FLAC__StreamEncoder or
|
||||
* FLAC__StreamDecoder. The old layers are now differentiated by the
|
||||
* initialization function. For example, for the decoder,
|
||||
* FLAC__stream_decoder_init() has been replaced by
|
||||
* FLAC__stream_decoder_init_stream(). This init function takes
|
||||
* callbacks for the I/O, and the seeking callbacks are optional. This
|
||||
* allows the client to use the same object for seekable and
|
||||
* non-seekable streams. For decoding a FLAC file directly, the client
|
||||
* can use FLAC__stream_decoder_init_file() and pass just a filename
|
||||
* and fewer callbacks; most of the other callbacks are supplied
|
||||
* internally. For situations where fopen()ing by filename is not
|
||||
* possible (e.g. Unicode filenames on Windows) the client can instead
|
||||
* open the file itself and supply the FILE* to
|
||||
* FLAC__stream_decoder_init_FILE(). The init functions now returns a
|
||||
* FLAC__StreamDecoderInitStatus instead of FLAC__StreamDecoderState.
|
||||
* Since the callbacks and client data are now passed to the init
|
||||
* function, the FLAC__stream_decoder_set_*_callback() functions and
|
||||
* FLAC__stream_decoder_set_client_data() are no longer needed. The
|
||||
* rest of the calls to the decoder are the same as before.
|
||||
*
|
||||
* There are counterpart init functions for Ogg FLAC, e.g.
|
||||
* FLAC__stream_decoder_init_ogg_stream(). All the rest of the calls
|
||||
* and callbacks are the same as for native FLAC.
|
||||
*
|
||||
* As an example, in FLAC 1.1.2 a seekable stream decoder would have
|
||||
* been set up like so:
|
||||
*
|
||||
* \code
|
||||
* FLAC__SeekableStreamDecoder *decoder = FLAC__seekable_stream_decoder_new();
|
||||
* if(decoder == NULL) do_something;
|
||||
* FLAC__seekable_stream_decoder_set_md5_checking(decoder, true);
|
||||
* [... other settings ...]
|
||||
* FLAC__seekable_stream_decoder_set_read_callback(decoder, my_read_callback);
|
||||
* FLAC__seekable_stream_decoder_set_seek_callback(decoder, my_seek_callback);
|
||||
* FLAC__seekable_stream_decoder_set_tell_callback(decoder, my_tell_callback);
|
||||
* FLAC__seekable_stream_decoder_set_length_callback(decoder, my_length_callback);
|
||||
* FLAC__seekable_stream_decoder_set_eof_callback(decoder, my_eof_callback);
|
||||
* FLAC__seekable_stream_decoder_set_write_callback(decoder, my_write_callback);
|
||||
* FLAC__seekable_stream_decoder_set_metadata_callback(decoder, my_metadata_callback);
|
||||
* FLAC__seekable_stream_decoder_set_error_callback(decoder, my_error_callback);
|
||||
* FLAC__seekable_stream_decoder_set_client_data(decoder, my_client_data);
|
||||
* if(FLAC__seekable_stream_decoder_init(decoder) != FLAC__SEEKABLE_STREAM_DECODER_OK) do_something;
|
||||
* \endcode
|
||||
*
|
||||
* In FLAC 1.1.3 it is like this:
|
||||
*
|
||||
* \code
|
||||
* FLAC__StreamDecoder *decoder = FLAC__stream_decoder_new();
|
||||
* if(decoder == NULL) do_something;
|
||||
* FLAC__stream_decoder_set_md5_checking(decoder, true);
|
||||
* [... other settings ...]
|
||||
* if(FLAC__stream_decoder_init_stream(
|
||||
* decoder,
|
||||
* my_read_callback,
|
||||
* my_seek_callback, // or NULL
|
||||
* my_tell_callback, // or NULL
|
||||
* my_length_callback, // or NULL
|
||||
* my_eof_callback, // or NULL
|
||||
* my_write_callback,
|
||||
* my_metadata_callback, // or NULL
|
||||
* my_error_callback,
|
||||
* my_client_data
|
||||
* ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something;
|
||||
* \endcode
|
||||
*
|
||||
* or you could do;
|
||||
*
|
||||
* \code
|
||||
* [...]
|
||||
* FILE *file = fopen("somefile.flac","rb");
|
||||
* if(file == NULL) do_somthing;
|
||||
* if(FLAC__stream_decoder_init_FILE(
|
||||
* decoder,
|
||||
* file,
|
||||
* my_write_callback,
|
||||
* my_metadata_callback, // or NULL
|
||||
* my_error_callback,
|
||||
* my_client_data
|
||||
* ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something;
|
||||
* \endcode
|
||||
*
|
||||
* or just:
|
||||
*
|
||||
* \code
|
||||
* [...]
|
||||
* if(FLAC__stream_decoder_init_file(
|
||||
* decoder,
|
||||
* "somefile.flac",
|
||||
* my_write_callback,
|
||||
* my_metadata_callback, // or NULL
|
||||
* my_error_callback,
|
||||
* my_client_data
|
||||
* ) != FLAC__STREAM_DECODER_INIT_STATUS_OK) do_something;
|
||||
* \endcode
|
||||
*
|
||||
* Another small change to the decoder is in how it handles unparseable
|
||||
* streams. Before, when the decoder found an unparseable stream
|
||||
* (reserved for when the decoder encounters a stream from a future
|
||||
* encoder that it can't parse), it changed the state to
|
||||
* \c FLAC__STREAM_DECODER_UNPARSEABLE_STREAM. Now the decoder instead
|
||||
* drops sync and calls the error callback with a new error code
|
||||
* \c FLAC__STREAM_DECODER_ERROR_STATUS_UNPARSEABLE_STREAM. This is
|
||||
* more robust. If your error callback does not discriminate on the the
|
||||
* error state, your code does not need to be changed.
|
||||
*
|
||||
* The encoder now has a new setting:
|
||||
* FLAC__stream_encoder_set_apodization(). This is for setting the
|
||||
* method used to window the data before LPC analysis. You only need to
|
||||
* add a call to this function if the default is not suitable. There
|
||||
* are also two new convenience functions that may be useful:
|
||||
* FLAC__metadata_object_cuesheet_calculate_cddb_id() and
|
||||
* FLAC__metadata_get_cuesheet().
|
||||
*
|
||||
* The \a bytes parameter to FLAC__StreamDecoderReadCallback,
|
||||
* FLAC__StreamEncoderReadCallback, and FLAC__StreamEncoderWriteCallback
|
||||
* is now \c size_t instead of \c uint32_t.
|
||||
*/
|
||||
|
||||
/** \defgroup porting_1_1_3_to_1_1_4 Porting from FLAC 1.1.3 to 1.1.4
|
||||
* \ingroup porting
|
||||
*
|
||||
* \brief
|
||||
* This module describes porting from FLAC 1.1.3 to FLAC 1.1.4.
|
||||
*
|
||||
* There were no changes to any of the interfaces from 1.1.3 to 1.1.4.
|
||||
* There was a slight change in the implementation of
|
||||
* FLAC__stream_encoder_set_metadata(); the function now makes a copy
|
||||
* of the \a metadata array of pointers so the client no longer needs
|
||||
* to maintain it after the call. The objects themselves that are
|
||||
* pointed to by the array are still not copied though and must be
|
||||
* maintained until the call to FLAC__stream_encoder_finish().
|
||||
*/
|
||||
|
||||
/** \defgroup porting_1_1_4_to_1_2_0 Porting from FLAC 1.1.4 to 1.2.0
|
||||
* \ingroup porting
|
||||
*
|
||||
* \brief
|
||||
* This module describes porting from FLAC 1.1.4 to FLAC 1.2.0.
|
||||
*
|
||||
* There were only very minor changes to the interfaces from 1.1.4 to 1.2.0.
|
||||
* In libFLAC, \c FLAC__format_sample_rate_is_subset() was added.
|
||||
* In libFLAC++, \c FLAC::Decoder::Stream::get_decode_position() was added.
|
||||
*
|
||||
* Finally, value of the constant \c FLAC__FRAME_HEADER_RESERVED_LEN
|
||||
* has changed to reflect the conversion of one of the reserved bits
|
||||
* into active use. It used to be \c 2 and now is \c 1. However the
|
||||
* FLAC frame header length has not changed, so to skip the proper
|
||||
* number of bits, use \c FLAC__FRAME_HEADER_RESERVED_LEN +
|
||||
* \c FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN
|
||||
*/
|
||||
|
||||
/** \defgroup porting_1_3_4_to_1_4_0 Porting from FLAC 1.3.4 to 1.4.0
|
||||
* \ingroup porting
|
||||
*
|
||||
* \brief
|
||||
* This module describes porting from FLAC 1.3.4 to FLAC 1.4.0.
|
||||
*
|
||||
* \section porting_1_3_4_to_1_4_0_summary Summary
|
||||
*
|
||||
* Between FLAC 1.3.4 and FLAC 1.4.0, there have four breaking changes
|
||||
* - the function get_client_data_from_decoder has been renamed to
|
||||
* FLAC__get_decoder_client_data
|
||||
* - some data types in the FLAC__Frame struct have changed
|
||||
* - all functions resizing metadata blocks now return the object
|
||||
* untouched if memory allocation fails, whereas previously the
|
||||
* handling varied and was more or less undefined
|
||||
* - all functions accepting a filename now take UTF-8 encoded filenames
|
||||
* on Windows instead of filenames in the current codepage
|
||||
*
|
||||
* Furthermore, there have been the following additions
|
||||
* - the functions FLAC__stream_encoder_set_limit_min_bitrate,
|
||||
* FLAC__stream_encoder_get_limit_min_bitrate,
|
||||
* FLAC::encoder::file::set_limit_min_bitrate() and
|
||||
* FLAC::encoder::file::get_limit_min_bitrate() have been added
|
||||
* - Added FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA to the
|
||||
* FLAC__StreamDecoderErrorStatus enum
|
||||
*
|
||||
* \section porting_1_3_4_to_1_4_0_breaking Breaking changes
|
||||
*
|
||||
* The function \b get_client_data_from_decoder was added in FLAC 1.3.3
|
||||
* but did not follow the API naming convention and was not properly
|
||||
* exported. The function is now renamed and properly integrated as
|
||||
* FLAC__stream_decoder_get_client_data
|
||||
*
|
||||
* To accomodate encoding and decoding 32-bit int PCM, some data types
|
||||
* in the \b FLAC__frame struct were changed. Specifically, warmup
|
||||
* in both the FLAC__Subframe_Fixed struc and the FLAC__Subframe_LPC
|
||||
* struct is changed from FLAC__int32 to FLAC__int64. Also, value
|
||||
* in the FLAC__Subframe_Constant is changed from FLAC__int32 to
|
||||
* FLAC__int64. Finally, in FLAC__Subframe_Verbatim struct data is
|
||||
* changes from a FLAC__int32 array to a union containing a FLAC__int32
|
||||
* array and a FLAC__int64 array. Also, a new member is added,
|
||||
* data_type, which clarifies whether the FLAC__int32 or FLAC__int64
|
||||
* array is in use.
|
||||
*
|
||||
* Furthermore, the following functions now return the object untouched
|
||||
* if memory allocation fails, whereas previously the handling varied
|
||||
* and was more or less undefined
|
||||
*
|
||||
* - FLAC__metadata_object_seektable_resize_points
|
||||
* - FLAC__metadata_object_vorbiscomment_resize_comments
|
||||
* - FLAC__metadata_object_cuesheet_track_resize_indices
|
||||
* - FLAC__metadata_object_cuesheet_resize_tracks
|
||||
*
|
||||
* The last breaking change is that all API functions taking a filename
|
||||
* as an argument now, on Windows, must be supplied with that filename
|
||||
* in the UTF-8 character encoding instead of using the current code
|
||||
* page. libFLAC internally translates these UTF-8 encoded filenames to
|
||||
* an appropriate representation to use with _wfopen. On all other
|
||||
* systems, filename is passed to fopen without any translation, as it
|
||||
* in libFLAC 1.3.4 and earlier.
|
||||
*
|
||||
* \section porting_1_3_4_to_1_4_0_additions Additions
|
||||
*
|
||||
* To aid in creating properly streamable FLAC files, a set of functions
|
||||
* was added to make it possible to enfore a minimum bitrate to files
|
||||
* created through libFLAC's stream_encoder.h interface. With this
|
||||
* function enabled the resulting FLAC files have a minimum bitrate of
|
||||
* 1bit/sample independent of the number of channels, i.e. 48kbit/s for
|
||||
* 48kHz. This can be beneficial for streaming, as very low bitrates for
|
||||
* silent sections compressed with 'constant' subframes can result in a
|
||||
* bitrate of 1kbit/s, creating problems with clients that aren't aware
|
||||
* of this possibility and buffer too much data.
|
||||
*
|
||||
* Finally, FLAC__STREAM_DECODER_ERROR_STATUS_BAD_METADATA was added to
|
||||
* the FLAC__StreamDecoderErrorStatus enum to signal that the decoder
|
||||
* encountered unreadable metadata.
|
||||
*
|
||||
*/
|
||||
|
||||
/** \defgroup flac FLAC C API
|
||||
*
|
||||
* The FLAC C API is the interface to libFLAC, a set of structures
|
||||
* describing the components of FLAC streams, and functions for
|
||||
* encoding and decoding streams, as well as manipulating FLAC
|
||||
* metadata in files.
|
||||
*
|
||||
* You should start with the format components as all other modules
|
||||
* are dependent on it.
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,321 @@
|
||||
/* alloc - Convenience routines for safely allocating memory
|
||||
* Copyright (C) 2007-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__SHARE__ALLOC_H
|
||||
#define FLAC__SHARE__ALLOC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
/* WATCHOUT: for c++ you may have to #define __STDC_LIMIT_MACROS 1 real early
|
||||
* before #including this file, otherwise SIZE_MAX might not be defined
|
||||
*/
|
||||
|
||||
// JUCE: removed as JUCE already includes standard headers and including
|
||||
// these in FlacNamespace will cause problems
|
||||
|
||||
//#include <limits.h> /* for SIZE_MAX */
|
||||
//#if HAVE_STDINT_H
|
||||
//#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */
|
||||
//#endif
|
||||
//#include <stdlib.h> /* for size_t, malloc(), etc */
|
||||
#include "compat.h"
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# ifndef SIZE_T_MAX
|
||||
# ifdef _MSC_VER
|
||||
# ifdef _WIN64
|
||||
# define SIZE_T_MAX FLAC__U64L(0xffffffffffffffff)
|
||||
# else
|
||||
# define SIZE_T_MAX 0xffffffff
|
||||
# endif
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
# endif
|
||||
# define SIZE_MAX SIZE_T_MAX
|
||||
#endif
|
||||
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
extern int alloc_check_threshold, alloc_check_counter;
|
||||
|
||||
static inline int alloc_check() {
|
||||
if(alloc_check_threshold == INT32_MAX)
|
||||
return 0;
|
||||
else if(alloc_check_counter++ == alloc_check_threshold)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* avoid malloc()ing 0 bytes, see:
|
||||
* https://www.securecoding.cert.org/confluence/display/seccode/MEM04-A.+Do+not+make+assumptions+about+the+result+of+allocating+0+bytes?focusedCommentId=5407003
|
||||
*/
|
||||
|
||||
static inline void *safe_malloc_(size_t size)
|
||||
{
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/* Fail if requested */
|
||||
if(alloc_check())
|
||||
return NULL;
|
||||
#endif
|
||||
/* malloc(0) is undefined; FLAC src convention is to always allocate */
|
||||
if(!size)
|
||||
size++;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
static inline void *malloc_(size_t size)
|
||||
{
|
||||
/* Fail if requested */
|
||||
if(alloc_check())
|
||||
return NULL;
|
||||
return malloc(size);
|
||||
}
|
||||
#else
|
||||
#define malloc_ malloc
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
static inline void *safe_calloc_(size_t nmemb, size_t size)
|
||||
{
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/* Fail if requested */
|
||||
if(alloc_check())
|
||||
return NULL;
|
||||
#endif
|
||||
if(!nmemb || !size)
|
||||
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
|
||||
return calloc(nmemb, size);
|
||||
}
|
||||
|
||||
/*@@@@ there's probably a better way to prevent overflows when allocating untrusted sums but this works for now */
|
||||
|
||||
static inline void *safe_malloc_add_2op_(size_t size1, size_t size2)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
return safe_malloc_(size2);
|
||||
}
|
||||
|
||||
static inline void *safe_malloc_add_3op_(size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
size3 += size2;
|
||||
if(size3 < size2)
|
||||
return 0;
|
||||
return safe_malloc_(size3);
|
||||
}
|
||||
|
||||
static inline void *safe_malloc_add_4op_(size_t size1, size_t size2, size_t size3, size_t size4)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
size3 += size2;
|
||||
if(size3 < size2)
|
||||
return 0;
|
||||
size4 += size3;
|
||||
if(size4 < size3)
|
||||
return 0;
|
||||
return safe_malloc_(size4);
|
||||
}
|
||||
|
||||
void *safe_malloc_mul_2op_(size_t size1, size_t size2) ;
|
||||
|
||||
static inline void *safe_malloc_mul_3op_(size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
if(!size1 || !size2 || !size3)
|
||||
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
|
||||
if(size1 > SIZE_MAX / size2)
|
||||
return 0;
|
||||
size1 *= size2;
|
||||
if(size1 > SIZE_MAX / size3)
|
||||
return 0;
|
||||
return malloc_(size1*size3);
|
||||
}
|
||||
|
||||
/* size1*size2 + size3 */
|
||||
static inline void *safe_malloc_mul2add_(size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
if(!size1 || !size2)
|
||||
return safe_malloc_(size3);
|
||||
if(size1 > SIZE_MAX / size2)
|
||||
return 0;
|
||||
return safe_malloc_add_2op_(size1*size2, size3);
|
||||
}
|
||||
|
||||
/* size1 * (size2 + size3) */
|
||||
static inline void *safe_malloc_muladd2_(size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
if(!size1 || (!size2 && !size3))
|
||||
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
|
||||
size2 += size3;
|
||||
if(size2 < size3)
|
||||
return 0;
|
||||
if(size1 > SIZE_MAX / size2)
|
||||
return 0;
|
||||
return malloc_(size1*size2);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_(void *ptr, size_t size)
|
||||
{
|
||||
void *oldptr;
|
||||
void *newptr;
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
/* Fail if requested */
|
||||
if(alloc_check() && size > 0) {
|
||||
free(ptr);
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
oldptr = ptr;
|
||||
newptr = realloc(ptr, size);
|
||||
if(size > 0 && newptr == 0)
|
||||
free(oldptr);
|
||||
return newptr;
|
||||
}
|
||||
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
static inline void *realloc_(void *ptr, size_t size)
|
||||
{
|
||||
/* Fail if requested */
|
||||
if(alloc_check())
|
||||
return NULL;
|
||||
return realloc(ptr, size);
|
||||
}
|
||||
#else
|
||||
#define realloc_ realloc
|
||||
#endif
|
||||
|
||||
|
||||
static inline void *safe_realloc_nofree_add_2op_(void *ptr, size_t size1, size_t size2)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
return realloc_(ptr, size2);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1) {
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
size3 += size2;
|
||||
if(size3 < size2) {
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
return safe_realloc_(ptr, size3);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_nofree_add_3op_(void *ptr, size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
size3 += size2;
|
||||
if(size3 < size2)
|
||||
return 0;
|
||||
return realloc_(ptr, size3);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_nofree_add_4op_(void *ptr, size_t size1, size_t size2, size_t size3, size_t size4)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
size3 += size2;
|
||||
if(size3 < size2)
|
||||
return 0;
|
||||
size4 += size3;
|
||||
if(size4 < size3)
|
||||
return 0;
|
||||
return realloc_(ptr, size4);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_mul_2op_(void *ptr, size_t size1, size_t size2)
|
||||
{
|
||||
if(!size1 || !size2)
|
||||
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
|
||||
if(size1 > SIZE_MAX / size2) {
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
return safe_realloc_(ptr, size1*size2);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_nofree_mul_2op_(void *ptr, size_t size1, size_t size2)
|
||||
{
|
||||
if(!size1 || !size2)
|
||||
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
|
||||
if(size1 > SIZE_MAX / size2)
|
||||
return 0;
|
||||
return realloc_(ptr, size1*size2);
|
||||
}
|
||||
|
||||
/* size1 * (size2 + size3) */
|
||||
static inline void *safe_realloc_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
if(!size1 || (!size2 && !size3))
|
||||
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
|
||||
size2 += size3;
|
||||
if(size2 < size3) {
|
||||
free(ptr);
|
||||
return 0;
|
||||
}
|
||||
return safe_realloc_mul_2op_(ptr, size1, size2);
|
||||
}
|
||||
|
||||
/* size1 * (size2 + size3) */
|
||||
static inline void *safe_realloc_nofree_muladd2_(void *ptr, size_t size1, size_t size2, size_t size3)
|
||||
{
|
||||
if(!size1 || (!size2 && !size3))
|
||||
return realloc(ptr, 0); /* preserve POSIX realloc(ptr, 0) semantics */
|
||||
size2 += size3;
|
||||
if(size2 < size3)
|
||||
return 0;
|
||||
return safe_realloc_nofree_mul_2op_(ptr, size1, size2);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ASSERT_H
|
||||
#define FLAC__ASSERT_H
|
||||
|
||||
/* we need this since some compilers (like MSVC) leave assert()s on release code (and we don't want to use their ASSERT) */
|
||||
#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
|
||||
#define FLAC__ASSERT(x) if(!(x)) __builtin_abort();
|
||||
#define FLAC__ASSERT_DECLARATION(x) x
|
||||
#else
|
||||
#ifndef NDEBUG
|
||||
#include <assert.h>
|
||||
#define FLAC__ASSERT(x) assert(x)
|
||||
#define FLAC__ASSERT_DECLARATION(x) x
|
||||
#else
|
||||
#define FLAC__ASSERT(x)
|
||||
#define FLAC__ASSERT_DECLARATION(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,190 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__CALLBACK_H
|
||||
#define FLAC__CALLBACK_H
|
||||
|
||||
#include "ordinals.h"
|
||||
#include <stdlib.h> /* for size_t */
|
||||
|
||||
/** \file include/FLAC/callback.h
|
||||
*
|
||||
* \brief
|
||||
* This module defines the structures for describing I/O callbacks
|
||||
* to the other FLAC interfaces.
|
||||
*
|
||||
* See the detailed documentation for callbacks in the
|
||||
* \link flac_callbacks callbacks \endlink module.
|
||||
*/
|
||||
|
||||
/** \defgroup flac_callbacks FLAC/callback.h: I/O callback structures
|
||||
* \ingroup flac
|
||||
*
|
||||
* \brief
|
||||
* This module defines the structures for describing I/O callbacks
|
||||
* to the other FLAC interfaces.
|
||||
*
|
||||
* The purpose of the I/O callback functions is to create a common way
|
||||
* for the metadata interfaces to handle I/O.
|
||||
*
|
||||
* Originally the metadata interfaces required filenames as the way of
|
||||
* specifying FLAC files to operate on. This is problematic in some
|
||||
* environments so there is an additional option to specify a set of
|
||||
* callbacks for doing I/O on the FLAC file, instead of the filename.
|
||||
*
|
||||
* In addition to the callbacks, a FLAC__IOHandle type is defined as an
|
||||
* opaque structure for a data source.
|
||||
*
|
||||
* The callback function prototypes are similar (but not identical) to the
|
||||
* stdio functions fread, fwrite, fseek, ftell, feof, and fclose. If you use
|
||||
* stdio streams to implement the callbacks, you can pass fread, fwrite, and
|
||||
* fclose anywhere a FLAC__IOCallback_Read, FLAC__IOCallback_Write, or
|
||||
* FLAC__IOCallback_Close is required, and a FILE* anywhere a FLAC__IOHandle
|
||||
* is required. \warning You generally CANNOT directly use fseek or ftell
|
||||
* for FLAC__IOCallback_Seek or FLAC__IOCallback_Tell since on most systems
|
||||
* these use 32-bit offsets and FLAC requires 64-bit offsets to deal with
|
||||
* large files. You will have to find an equivalent function (e.g. ftello),
|
||||
* or write a wrapper. The same is true for feof() since this is usually
|
||||
* implemented as a macro, not as a function whose address can be taken.
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** This is the opaque handle type used by the callbacks. Typically
|
||||
* this is a \c FILE* or address of a file descriptor.
|
||||
*/
|
||||
typedef void* FLAC__IOHandle;
|
||||
|
||||
/** Signature for the read callback.
|
||||
* The signature and semantics match POSIX fread() implementations
|
||||
* and can generally be used interchangeably. Note that the global
|
||||
* variable errno from errno.h is read by some libFLAC functions to
|
||||
* detect read errors.
|
||||
*
|
||||
* \param ptr The address of the read buffer.
|
||||
* \param size The size of the records to be read.
|
||||
* \param nmemb The number of records to be read.
|
||||
* \param handle The handle to the data source.
|
||||
* \retval size_t
|
||||
* The number of records read.
|
||||
*/
|
||||
typedef size_t (*FLAC__IOCallback_Read) (void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle);
|
||||
|
||||
/** Signature for the write callback.
|
||||
* The signature and semantics match POSIX fwrite() implementations
|
||||
* and can generally be used interchangeably.
|
||||
*
|
||||
* \param ptr The address of the write buffer.
|
||||
* \param size The size of the records to be written.
|
||||
* \param nmemb The number of records to be written.
|
||||
* \param handle The handle to the data source.
|
||||
* \retval size_t
|
||||
* The number of records written.
|
||||
*/
|
||||
typedef size_t (*FLAC__IOCallback_Write) (const void *ptr, size_t size, size_t nmemb, FLAC__IOHandle handle);
|
||||
|
||||
/** Signature for the seek callback.
|
||||
* The signature and semantics mostly match POSIX fseek() WITH ONE IMPORTANT
|
||||
* EXCEPTION: the offset is a 64-bit type whereas fseek() is generally 'long'
|
||||
* and 32-bits wide.
|
||||
*
|
||||
* \param handle The handle to the data source.
|
||||
* \param offset The new position, relative to \a whence
|
||||
* \param whence \c SEEK_SET, \c SEEK_CUR, or \c SEEK_END
|
||||
* \retval int
|
||||
* \c 0 on success, \c -1 on error.
|
||||
*/
|
||||
typedef int (*FLAC__IOCallback_Seek) (FLAC__IOHandle handle, FLAC__int64 offset, int whence);
|
||||
|
||||
/** Signature for the tell callback.
|
||||
* The signature and semantics mostly match POSIX ftell() WITH ONE IMPORTANT
|
||||
* EXCEPTION: the offset is a 64-bit type whereas ftell() is generally 'long'
|
||||
* and 32-bits wide.
|
||||
*
|
||||
* \param handle The handle to the data source.
|
||||
* \retval FLAC__int64
|
||||
* The current position on success, \c -1 on error.
|
||||
*/
|
||||
typedef FLAC__int64 (*FLAC__IOCallback_Tell) (FLAC__IOHandle handle);
|
||||
|
||||
/** Signature for the EOF callback.
|
||||
* The signature and semantics mostly match POSIX feof() but WATCHOUT:
|
||||
* on many systems, feof() is a macro, so in this case a wrapper function
|
||||
* must be provided instead.
|
||||
*
|
||||
* \param handle The handle to the data source.
|
||||
* \retval int
|
||||
* \c 0 if not at end of file, nonzero if at end of file.
|
||||
*/
|
||||
typedef int (*FLAC__IOCallback_Eof) (FLAC__IOHandle handle);
|
||||
|
||||
/** Signature for the close callback.
|
||||
* The signature and semantics match POSIX fclose() implementations
|
||||
* and can generally be used interchangeably.
|
||||
*
|
||||
* \param handle The handle to the data source.
|
||||
* \retval int
|
||||
* \c 0 on success, \c EOF on error.
|
||||
*/
|
||||
typedef int (*FLAC__IOCallback_Close) (FLAC__IOHandle handle);
|
||||
|
||||
/** A structure for holding a set of callbacks.
|
||||
* Each FLAC interface that requires a FLAC__IOCallbacks structure will
|
||||
* describe which of the callbacks are required. The ones that are not
|
||||
* required may be set to NULL.
|
||||
*
|
||||
* If the seek requirement for an interface is optional, you can signify that
|
||||
* a data source is not seekable by setting the \a seek field to \c NULL.
|
||||
*
|
||||
* See the detailed documentation for callbacks in the
|
||||
* \link flac_callbacks callbacks \endlink module.
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__IOCallback_Read read; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Write write; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Seek seek; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Tell tell; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Eof eof; /**< See FLAC__IOCallbacks */
|
||||
FLAC__IOCallback_Close close; /**< See FLAC__IOCallbacks */
|
||||
} FLAC__IOCallbacks;
|
||||
|
||||
/* \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,243 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2012-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* This is the preferred location of all CPP hackery to make $random_compiler
|
||||
* work like something approaching a C99 (or maybe more accurately GNU99)
|
||||
* compiler.
|
||||
*
|
||||
* It is assumed that this header will be included after "config.h".
|
||||
*/
|
||||
|
||||
#ifndef FLAC__SHARE__COMPAT_H
|
||||
#define FLAC__SHARE__COMPAT_H
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
/* where MSVC puts unlink() */
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
|
||||
#include <sys/types.h> /* for off_t */
|
||||
#define FLAC__off_t __int64 /* use this instead of off_t to fix the 2 GB limit */
|
||||
#define FLAC__OFF_T_MAX INT64_MAX
|
||||
#if !defined __MINGW32__
|
||||
#define fseeko _fseeki64
|
||||
#define ftello _ftelli64
|
||||
#else /* MinGW */
|
||||
#if !defined(HAVE_FSEEKO)
|
||||
#define fseeko fseeko64
|
||||
#define ftello ftello64
|
||||
#endif
|
||||
#endif
|
||||
#else
|
||||
#define FLAC__off_t off_t
|
||||
#define FLAC__OFF_T_MAX OFF_T_MAX
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef HAVE_INTTYPES_H
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#define strtoll _strtoi64
|
||||
#define strtoull _strtoui64
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && !defined(__cplusplus)
|
||||
#define inline __inline
|
||||
#endif
|
||||
|
||||
#if defined __INTEL_COMPILER || (defined _MSC_VER && defined _WIN64)
|
||||
/* MSVS generates VERY slow 32-bit code with __restrict */
|
||||
#define flac_restrict __restrict
|
||||
#elif defined __GNUC__
|
||||
#define flac_restrict __restrict__
|
||||
#else
|
||||
#define flac_restrict
|
||||
#endif
|
||||
|
||||
#define FLAC__U64L(x) x##ULL
|
||||
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
#define FLAC__STRCASECMP _stricmp
|
||||
#define FLAC__STRNCASECMP _strnicmp
|
||||
#elif defined __BORLANDC__
|
||||
#define FLAC__STRCASECMP stricmp
|
||||
#define FLAC__STRNCASECMP strnicmp
|
||||
#else
|
||||
#define FLAC__STRCASECMP strcasecmp
|
||||
#define FLAC__STRNCASECMP strncasecmp
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __MINGW32__ || defined __EMX__
|
||||
#include <io.h> /* for _setmode(), chmod() */
|
||||
#include <fcntl.h> /* for _O_BINARY */
|
||||
#else
|
||||
#include <unistd.h> /* for chown(), unlink() */
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
|
||||
#if defined __BORLANDC__
|
||||
#include <utime.h> /* for utime() */
|
||||
#else
|
||||
#include <sys/utime.h> /* for utime() */
|
||||
#endif
|
||||
#else
|
||||
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
|
||||
#include <fcntl.h>
|
||||
#else
|
||||
#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
|
||||
#include <utime.h> /* for utime() */
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER
|
||||
# if _MSC_VER >= 1800
|
||||
# include <inttypes.h>
|
||||
# elif _MSC_VER >= 1600
|
||||
/* Visual Studio 2010 has decent C99 support */
|
||||
# include <stdint.h>
|
||||
# define PRIu64 "llu"
|
||||
# define PRId64 "lld"
|
||||
# define PRIx64 "llx"
|
||||
# else
|
||||
# include <limits.h>
|
||||
# ifndef UINT32_MAX
|
||||
# define UINT32_MAX _UI32_MAX
|
||||
# endif
|
||||
# define PRIu64 "I64u"
|
||||
# define PRId64 "I64d"
|
||||
# define PRIx64 "I64x"
|
||||
# endif
|
||||
# if defined(_USING_V110_SDK71_) && !defined(_DLL)
|
||||
# pragma message("WARNING: This compile will NOT FUNCTION PROPERLY on Windows XP. See comments in include/share/compat.h for details")
|
||||
#define FLAC__USE_FILELENGTHI64
|
||||
/*
|
||||
*************************************************************************************
|
||||
* V110_SDK71, in MSVC 2017 also known as v141_xp, is a platform toolset that is supposed
|
||||
* to target Windows XP. It turns out however that certain functions provided silently fail
|
||||
* on Windows XP only, which makes debugging challenging. This only occurs when building with
|
||||
* /MT. This problem has been reported to Microsoft, but there hasn't been a fix for years. See
|
||||
* https://web.archive.org/web/20170327195018/https://connect.microsoft.com/VisualStudio/feedback/details/1557168/wstat64-returns-1-on-xp-always
|
||||
*
|
||||
* It is known that this problem affects the functions _wstat64 (used by flac_stat i.e.
|
||||
* stat64_utf8) and _fstat64 (i.e. flac_fstat) and therefore affects both libFLAC in
|
||||
* several places as well as the flac and metaflac command line tools
|
||||
*
|
||||
* As the extent of this problem is unknown and Microsoft seems unwilling to fix it,
|
||||
* users of libFLAC building with Visual Studio are encouraged to not use the /MT compile
|
||||
* switch when explicitly targeting Windows XP. When use of /MT is deemed necessary with
|
||||
* this toolset, be sure to check whether your application works properly on Windows XP.
|
||||
* It is also possible to build for Windows XP with MinGW instead.
|
||||
*************************************************************************************
|
||||
*/
|
||||
# endif
|
||||
#endif /* defined _MSC_VER */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* All char* strings are in UTF-8 format. Added to support Unicode files on Windows */
|
||||
|
||||
#if 0
|
||||
#include "win_utf8_io.h"
|
||||
#define flac_printf printf_utf8
|
||||
#define flac_fprintf fprintf_utf8
|
||||
#define flac_vfprintf vfprintf_utf8
|
||||
#endif
|
||||
|
||||
#define flac_fopen fopen_utf8
|
||||
#define flac_chmod chmod_utf8
|
||||
#define flac_utime utime_utf8
|
||||
#define flac_unlink unlink_utf8
|
||||
#define flac_rename rename_utf8
|
||||
#define flac_stat stat64_utf8
|
||||
|
||||
#else
|
||||
|
||||
#define flac_printf printf
|
||||
#define flac_fprintf fprintf
|
||||
#define flac_vfprintf vfprintf
|
||||
|
||||
#define flac_fopen fopen
|
||||
#define flac_chmod chmod
|
||||
#define flac_unlink unlink
|
||||
#define flac_rename rename
|
||||
#define flac_stat stat
|
||||
|
||||
#if defined(_POSIX_C_SOURCE) && (_POSIX_C_SOURCE >= 200809L)
|
||||
#define flac_utime(a, b) utimensat (AT_FDCWD, a, *b, 0)
|
||||
#else
|
||||
#define flac_utime utime
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define flac_stat_s __stat64 /* stat struct */
|
||||
#define flac_fstat _fstat64
|
||||
#else
|
||||
#define flac_stat_s stat /* stat struct */
|
||||
#define flac_fstat fstat
|
||||
#endif
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <limits.h>
|
||||
#endif
|
||||
|
||||
#ifndef M_LN2
|
||||
#define M_LN2 0.69314718055994530942
|
||||
#endif
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
/* FLAC needs to compile and work correctly on systems with a normal ISO C99
|
||||
* snprintf as well as Microsoft Visual Studio which has an non-standards
|
||||
* conformant snprint_s function.
|
||||
*
|
||||
* This function wraps the MS version to behave more like the ISO version.
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
int flac_snprintf(char *str, size_t size, const char *fmt, ...);
|
||||
int flac_vsnprintf(char *str, size_t size, const char *fmt, va_list va);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* FLAC__SHARE__COMPAT_H */
|
||||
@@ -0,0 +1,84 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2012-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* It is assumed that this header will be included after "config.h". */
|
||||
|
||||
#ifdef HAVE_BSWAP32 /* GCC and Clang */
|
||||
|
||||
/* GCC prior to 4.8 didn't provide bswap16 on x86_64 */
|
||||
#ifndef HAVE_BSWAP16
|
||||
static inline unsigned short __builtin_bswap16(unsigned short a)
|
||||
{
|
||||
return (a<<8)|(a>>8);
|
||||
}
|
||||
#endif
|
||||
|
||||
#define ENDSWAP_16(x) (__builtin_bswap16 (x))
|
||||
#define ENDSWAP_32(x) (__builtin_bswap32 (x))
|
||||
#define ENDSWAP_64(x) (__builtin_bswap64 (x))
|
||||
|
||||
#elif defined _MSC_VER /* Windows */
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define ENDSWAP_16(x) (_byteswap_ushort (x))
|
||||
#define ENDSWAP_32(x) (_byteswap_ulong (x))
|
||||
#define ENDSWAP_64(x) (_byteswap_uint64 (x))
|
||||
|
||||
#elif defined HAVE_BYTESWAP_H /* Linux */
|
||||
|
||||
#include <byteswap.h>
|
||||
|
||||
#define ENDSWAP_16(x) (bswap_16 (x))
|
||||
#define ENDSWAP_32(x) (bswap_32 (x))
|
||||
#define ENDSWAP_64(x) (bswap_64 (x))
|
||||
|
||||
#else
|
||||
|
||||
#define ENDSWAP_16(x) ((((x) >> 8) & 0xFF) | (((x) & 0xFF) << 8))
|
||||
#define ENDSWAP_32(x) ((((x) >> 24) & 0xFF) | (((x) >> 8) & 0xFF00) | (((x) & 0xFF00) << 8) | (((x) & 0xFF) << 24))
|
||||
#define ENDSWAP_64(x) ((ENDSWAP_32(((x) >> 32) & 0xFFFFFFFF)) | (ENDSWAP_32((x) & 0xFFFFFFFF) << 32))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Host to little-endian byte swapping (for MD5 calculation) */
|
||||
#if CPU_IS_BIG_ENDIAN
|
||||
|
||||
#define H2LE_16(x) ENDSWAP_16 (x)
|
||||
#define H2LE_32(x) ENDSWAP_32 (x)
|
||||
|
||||
#else
|
||||
|
||||
#define H2LE_16(x) (x)
|
||||
#define H2LE_32(x) (x)
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,115 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__EXPORT_H
|
||||
#define FLAC__EXPORT_H
|
||||
|
||||
/** \file include/FLAC/export.h
|
||||
*
|
||||
* \brief
|
||||
* This module contains \#defines and symbols for exporting function
|
||||
* calls, and providing version information and compiled-in features.
|
||||
*
|
||||
* See the \link flac_export export \endlink module.
|
||||
*/
|
||||
|
||||
/** \defgroup flac_export FLAC/export.h: export symbols
|
||||
* \ingroup flac
|
||||
*
|
||||
* \brief
|
||||
* This module contains \#defines and symbols for exporting function
|
||||
* calls, and providing version information and compiled-in features.
|
||||
*
|
||||
* If you are compiling for Windows (with Visual Studio or MinGW for
|
||||
* example) and will link to the static library (libFLAC++.lib) you
|
||||
* should define FLAC__NO_DLL in your project to make sure the symbols
|
||||
* are exported properly.
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
/** This \#define is used internally in libFLAC and its headers to make
|
||||
* sure the correct symbols are exported when working with shared
|
||||
* libraries. On Windows, this \#define is set to __declspec(dllexport)
|
||||
* when compiling libFLAC into a library and to __declspec(dllimport)
|
||||
* when the headers are used to link to that DLL. On non-Windows systems
|
||||
* it is used to set symbol visibility.
|
||||
*
|
||||
* Because of this, the define FLAC__NO_DLL must be defined when linking
|
||||
* to libFLAC statically or linking will fail.
|
||||
*/
|
||||
/* This has grown quite complicated. FLAC__NO_DLL is used by MSVC sln
|
||||
* files and CMake, which build either static or shared. autotools can
|
||||
* build static, shared or **both**. Therefore, DLL_EXPORT, which is set
|
||||
* by libtool, must override FLAC__NO_DLL on building shared components
|
||||
*/
|
||||
#if defined(_WIN32)
|
||||
|
||||
#if defined(FLAC__NO_DLL) && !(defined(DLL_EXPORT))
|
||||
#define FLAC_API
|
||||
#else
|
||||
#ifdef FLAC_API_EXPORTS
|
||||
#define FLAC_API __declspec(dllexport)
|
||||
#else
|
||||
#define FLAC_API __declspec(dllimport)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(FLAC__USE_VISIBILITY_ATTR)
|
||||
#define FLAC_API __attribute__ ((visibility ("default")))
|
||||
|
||||
#else
|
||||
#define FLAC_API
|
||||
|
||||
#endif
|
||||
|
||||
/** These \#defines will mirror the libtool-based library version number, see
|
||||
* http://www.gnu.org/software/libtool/manual/libtool.html#Libtool-versioning
|
||||
*/
|
||||
#define FLAC_API_VERSION_CURRENT 13
|
||||
#define FLAC_API_VERSION_REVISION 0 /**< see above */
|
||||
#define FLAC_API_VERSION_AGE 1 /**< see above */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** \c 1 if the library has been compiled with support for Ogg FLAC, else \c 0. */
|
||||
extern FLAC_API int FLAC_API_SUPPORTS_OGG_FLAC;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/* \} */
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,73 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "include/private/bitmath.h"
|
||||
|
||||
/* An example of what FLAC__bitmath_silog2() computes:
|
||||
*
|
||||
* silog2(-10) = 5
|
||||
* silog2(- 9) = 5
|
||||
* silog2(- 8) = 4
|
||||
* silog2(- 7) = 4
|
||||
* silog2(- 6) = 4
|
||||
* silog2(- 5) = 4
|
||||
* silog2(- 4) = 3
|
||||
* silog2(- 3) = 3
|
||||
* silog2(- 2) = 2
|
||||
* silog2(- 1) = 2
|
||||
* silog2( 0) = 0
|
||||
* silog2( 1) = 2
|
||||
* silog2( 2) = 3
|
||||
* silog2( 3) = 3
|
||||
* silog2( 4) = 4
|
||||
* silog2( 5) = 4
|
||||
* silog2( 6) = 4
|
||||
* silog2( 7) = 4
|
||||
* silog2( 8) = 5
|
||||
* silog2( 9) = 5
|
||||
* silog2( 10) = 5
|
||||
*/
|
||||
uint32_t FLAC__bitmath_silog2(FLAC__int64 v)
|
||||
{
|
||||
if(v == 0)
|
||||
return 0;
|
||||
|
||||
if(v == -1)
|
||||
return 2;
|
||||
|
||||
v = (v < 0) ? (-(v+1)) : v;
|
||||
return FLAC__bitmath_ilog2_wide(v)+2;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,955 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "include/private/bitwriter.h"
|
||||
#include "include/private/crc.h"
|
||||
#include "include/private/format.h"
|
||||
|
||||
#include "include/private/stream_encoder.h"
|
||||
#include "../assert.h"
|
||||
#include "../alloc.h"
|
||||
#include "../compat.h"
|
||||
#include "../endswap.h"
|
||||
|
||||
/* Things should be fastest when this matches the machine word size */
|
||||
/* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */
|
||||
/* WATCHOUT: there are a few places where the code will not work unless bwword is >= 32 bits wide */
|
||||
|
||||
#if (ENABLE_64_BIT_WORDS == 0)
|
||||
|
||||
typedef FLAC__uint32 bwword;
|
||||
typedef FLAC__uint64 FLAC__bwtemp;
|
||||
#define FLAC__BYTES_PER_WORD 4 /* sizeof bwword */
|
||||
#define FLAC__BITS_PER_WORD 32
|
||||
#define FLAC__TEMP_BITS 64
|
||||
#define FLAC__HALF_TEMP_BITS 32
|
||||
/* SWAP_BE_WORD_TO_HOST swaps bytes in a bwword (which is always big-endian) if necessary to match host byte order */
|
||||
#if WORDS_BIGENDIAN
|
||||
#define SWAP_BE_WORD_TO_HOST(x) (x)
|
||||
#else
|
||||
#define SWAP_BE_WORD_TO_HOST(x) ENDSWAP_32(x)
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
typedef FLAC__uint64 bwword;
|
||||
typedef FLAC__uint64 FLAC__bwtemp;
|
||||
#define FLAC__BYTES_PER_WORD 8 /* sizeof bwword */
|
||||
#define FLAC__BITS_PER_WORD 64
|
||||
#define FLAC__TEMP_BITS 64
|
||||
#define FLAC__HALF_TEMP_BITS 32
|
||||
/* SWAP_BE_WORD_TO_HOST swaps bytes in a bwword (which is always big-endian) if necessary to match host byte order */
|
||||
#if WORDS_BIGENDIAN
|
||||
#define SWAP_BE_WORD_TO_HOST(x) (x)
|
||||
#else
|
||||
#define SWAP_BE_WORD_TO_HOST(x) ENDSWAP_64(x)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default capacity here doesn't matter too much. The buffer always grows
|
||||
* to hold whatever is written to it. Usually the encoder will stop adding at
|
||||
* a frame or metadata block, then write that out and clear the buffer for the
|
||||
* next one.
|
||||
*/
|
||||
static const uint32_t FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(bwword); /* size in words */
|
||||
/* When growing, increment 4K at a time */
|
||||
static const uint32_t FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(bwword); /* size in words */
|
||||
|
||||
#define FLAC__WORDS_TO_BITS(words) ((words) * FLAC__BITS_PER_WORD)
|
||||
#define FLAC__TOTAL_BITS(bw) (FLAC__WORDS_TO_BITS((bw)->words) + (bw)->bits)
|
||||
|
||||
struct FLAC__BitWriter {
|
||||
bwword *buffer;
|
||||
bwword accum; /* accumulator; bits are right-justified; when full, accum is appended to buffer */
|
||||
uint32_t capacity; /* capacity of buffer in words */
|
||||
uint32_t words; /* # of complete words in buffer */
|
||||
uint32_t bits; /* # of used bits in accum */
|
||||
};
|
||||
|
||||
/* * WATCHOUT: The current implementation only grows the buffer. */
|
||||
#ifndef __SUNPRO_C
|
||||
static
|
||||
#endif
|
||||
FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, uint32_t bits_to_add)
|
||||
{
|
||||
uint32_t new_capacity;
|
||||
bwword *new_buffer;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
/* calculate total words needed to store 'bits_to_add' additional bits */
|
||||
new_capacity = bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD);
|
||||
|
||||
/* it's possible (due to pessimism in the growth estimation that
|
||||
* leads to this call) that we don't actually need to grow
|
||||
*/
|
||||
if(bw->capacity >= new_capacity)
|
||||
return true;
|
||||
|
||||
if(new_capacity * sizeof(bwword) > (1u << FLAC__STREAM_METADATA_LENGTH_LEN))
|
||||
/* Requested new capacity is larger than the largest possible metadata block,
|
||||
* which is also larger than the largest sane framesize. That means something
|
||||
* went very wrong somewhere and previous checks failed.
|
||||
* To prevent chrashing, give up */
|
||||
return false;
|
||||
|
||||
/* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */
|
||||
if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT)
|
||||
new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
|
||||
/* make sure we got everything right */
|
||||
FLAC__ASSERT(0 == (new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
|
||||
FLAC__ASSERT(new_capacity > bw->capacity);
|
||||
FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD));
|
||||
|
||||
new_buffer = (bwword*) safe_realloc_nofree_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity);
|
||||
if(new_buffer == 0)
|
||||
return false;
|
||||
bw->buffer = new_buffer;
|
||||
bw->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Class constructor/destructor
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__BitWriter *FLAC__bitwriter_new(void)
|
||||
{
|
||||
FLAC__BitWriter *bw = (FLAC__BitWriter*) calloc(1, sizeof(FLAC__BitWriter));
|
||||
/* note that calloc() sets all members to 0 for us */
|
||||
return bw;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_delete(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
FLAC__bitwriter_free(bw);
|
||||
free(bw);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Public class methods
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
bw->words = bw->bits = 0;
|
||||
bw->capacity = FLAC__BITWRITER_DEFAULT_CAPACITY;
|
||||
bw->buffer = (bwword*) malloc(sizeof(bwword) * bw->capacity);
|
||||
if(bw->buffer == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_free(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
if(0 != bw->buffer)
|
||||
free(bw->buffer);
|
||||
bw->buffer = 0;
|
||||
bw->capacity = 0;
|
||||
bw->words = bw->bits = 0;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_clear(FLAC__BitWriter *bw)
|
||||
{
|
||||
bw->words = bw->bits = 0;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc)
|
||||
{
|
||||
const FLAC__byte *buffer;
|
||||
size_t bytes;
|
||||
|
||||
FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */
|
||||
|
||||
if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes))
|
||||
return false;
|
||||
|
||||
*crc = (FLAC__uint16)FLAC__crc16(buffer, bytes);
|
||||
FLAC__bitwriter_release_buffer(bw);
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc)
|
||||
{
|
||||
const FLAC__byte *buffer;
|
||||
size_t bytes;
|
||||
|
||||
FLAC__ASSERT((bw->bits & 7) == 0); /* assert that we're byte-aligned */
|
||||
|
||||
if(!FLAC__bitwriter_get_buffer(bw, &buffer, &bytes))
|
||||
return false;
|
||||
|
||||
*crc = FLAC__crc8(buffer, bytes);
|
||||
FLAC__bitwriter_release_buffer(bw);
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw)
|
||||
{
|
||||
return ((bw->bits & 7) == 0);
|
||||
}
|
||||
|
||||
uint32_t FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw)
|
||||
{
|
||||
return FLAC__TOTAL_BITS(bw);
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes)
|
||||
{
|
||||
FLAC__ASSERT((bw->bits & 7) == 0);
|
||||
/* double protection */
|
||||
if(bw->bits & 7)
|
||||
return false;
|
||||
/* if we have bits in the accumulator we have to flush those to the buffer first */
|
||||
if(bw->bits) {
|
||||
FLAC__ASSERT(bw->words <= bw->capacity);
|
||||
if(bw->words == bw->capacity && !bitwriter_grow_(bw, FLAC__BITS_PER_WORD))
|
||||
return false;
|
||||
/* append bits as complete word to buffer, but don't change bw->accum or bw->bits */
|
||||
bw->buffer[bw->words] = SWAP_BE_WORD_TO_HOST(bw->accum << (FLAC__BITS_PER_WORD-bw->bits));
|
||||
}
|
||||
/* now we can just return what we have */
|
||||
*buffer = (FLAC__byte*)bw->buffer;
|
||||
*bytes = (FLAC__BYTES_PER_WORD * bw->words) + (bw->bits >> 3);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw)
|
||||
{
|
||||
/* nothing to do. in the future, strict checking of a 'writer-is-in-
|
||||
* get-mode' flag could be added everywhere and then cleared here
|
||||
*/
|
||||
(void)bw;
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, uint32_t bits)
|
||||
{
|
||||
uint32_t n;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
if(bits == 0)
|
||||
return true;
|
||||
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
|
||||
if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits))
|
||||
return false;
|
||||
/* first part gets to word alignment */
|
||||
if(bw->bits) {
|
||||
n = flac_min(FLAC__BITS_PER_WORD - bw->bits, bits);
|
||||
bw->accum <<= n;
|
||||
bits -= n;
|
||||
bw->bits += n;
|
||||
if(bw->bits == FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->bits = 0;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
/* do whole words */
|
||||
while(bits >= FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = 0;
|
||||
bits -= FLAC__BITS_PER_WORD;
|
||||
}
|
||||
/* do any leftovers */
|
||||
if(bits > 0) {
|
||||
bw->accum = 0;
|
||||
bw->bits = bits;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static inline FLAC__bool FLAC__bitwriter_write_raw_uint32_nocheck(FLAC__BitWriter *bw, FLAC__uint32 val, uint32_t bits)
|
||||
{
|
||||
uint32_t left;
|
||||
|
||||
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
|
||||
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
|
||||
|
||||
if(bw == 0 || bw->buffer == 0)
|
||||
return false;
|
||||
|
||||
if (bits > 32)
|
||||
return false;
|
||||
|
||||
if(bits == 0)
|
||||
return true;
|
||||
|
||||
FLAC__ASSERT((bits == 32) || (val>>bits == 0));
|
||||
|
||||
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+bits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
|
||||
if(bw->capacity <= bw->words + bits && !bitwriter_grow_(bw, bits))
|
||||
return false;
|
||||
|
||||
left = FLAC__BITS_PER_WORD - bw->bits;
|
||||
if(bits < left) {
|
||||
bw->accum <<= bits;
|
||||
bw->accum |= val;
|
||||
bw->bits += bits;
|
||||
}
|
||||
else if(bw->bits) { /* WATCHOUT: if bw->bits == 0, left==FLAC__BITS_PER_WORD and bw->accum<<=left is a NOP instead of setting to 0 */
|
||||
bw->accum <<= left;
|
||||
bw->accum |= val >> (bw->bits = bits - left);
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->accum = val; /* unused top bits can contain garbage */
|
||||
}
|
||||
else { /* at this point bits == FLAC__BITS_PER_WORD == 32 and bw->bits == 0 */
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST((bwword)val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, uint32_t bits)
|
||||
{
|
||||
/* check that unused bits are unset */
|
||||
if((bits < 32) && (val>>bits != 0))
|
||||
return false;
|
||||
|
||||
return FLAC__bitwriter_write_raw_uint32_nocheck(bw, val, bits);
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t bits)
|
||||
{
|
||||
/* zero-out unused bits */
|
||||
if(bits < 32)
|
||||
val &= (~(0xffffffff << bits));
|
||||
|
||||
return FLAC__bitwriter_write_raw_uint32_nocheck(bw, (FLAC__uint32)val, bits);
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, uint32_t bits)
|
||||
{
|
||||
/* this could be a little faster but it's not used for much */
|
||||
if(bits > 32) {
|
||||
return
|
||||
FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)(val>>32), bits-32) &&
|
||||
FLAC__bitwriter_write_raw_uint32_nocheck(bw, (FLAC__uint32)val, 32);
|
||||
}
|
||||
else
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits);
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_int64(FLAC__BitWriter *bw, FLAC__int64 val, uint32_t bits)
|
||||
{
|
||||
FLAC__uint64 uval = val;
|
||||
/* zero-out unused bits */
|
||||
if(bits < 64)
|
||||
uval &= (~(UINT64_MAX << bits));
|
||||
return FLAC__bitwriter_write_raw_uint64(bw, uval, bits);
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val)
|
||||
{
|
||||
/* this doesn't need to be that fast as currently it is only used for vorbis comments */
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32_nocheck(bw, val & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32_nocheck(bw, (val>>8) & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32_nocheck(bw, (val>>16) & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32_nocheck(bw, val>>24, 8))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], uint32_t nvals)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* grow capacity upfront to prevent constant reallocation during writes */
|
||||
if(bw->capacity <= bw->words + nvals / (FLAC__BITS_PER_WORD / 8) + 1 && !bitwriter_grow_(bw, nvals * 8))
|
||||
return false;
|
||||
|
||||
/* this could be faster but currently we don't need it to be since it's only used for writing metadata */
|
||||
for(i = 0; i < nvals; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32_nocheck(bw, (FLAC__uint32)(vals[i]), 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, uint32_t val)
|
||||
{
|
||||
if(val < 32)
|
||||
return FLAC__bitwriter_write_raw_uint32_nocheck(bw, 1, ++val);
|
||||
else
|
||||
return
|
||||
FLAC__bitwriter_write_zeroes(bw, val) &&
|
||||
FLAC__bitwriter_write_raw_uint32_nocheck(bw, 1, 1);
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
uint32_t FLAC__bitwriter_rice_bits(FLAC__int32 val, uint32_t parameter)
|
||||
{
|
||||
FLAC__uint32 uval;
|
||||
|
||||
FLAC__ASSERT(parameter < 32);
|
||||
|
||||
/* fold signed to uint32_t; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = val;
|
||||
uval <<= 1;
|
||||
uval ^= (val>>31);
|
||||
|
||||
return 1 + parameter + (uval >> parameter);
|
||||
}
|
||||
|
||||
uint32_t FLAC__bitwriter_golomb_bits_signed(int val, uint32_t parameter)
|
||||
{
|
||||
uint32_t bits, msbs, uval;
|
||||
uint32_t k;
|
||||
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
/* fold signed to uint32_t */
|
||||
if(val < 0)
|
||||
uval = (uint32_t)(((-(++val)) << 1) + 1);
|
||||
else
|
||||
uval = (uint32_t)(val << 1);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
bits = 1 + k + msbs;
|
||||
}
|
||||
else {
|
||||
uint32_t q, r, d;
|
||||
|
||||
d = (1 << (k+1)) - parameter;
|
||||
q = uval / parameter;
|
||||
r = uval - (q * parameter);
|
||||
|
||||
bits = 1 + q + k;
|
||||
if(r >= d)
|
||||
bits++;
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
uint32_t FLAC__bitwriter_golomb_bits_unsigned(uint32_t uval, uint32_t parameter)
|
||||
{
|
||||
uint32_t bits, msbs;
|
||||
uint32_t k;
|
||||
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
bits = 1 + k + msbs;
|
||||
}
|
||||
else {
|
||||
uint32_t q, r, d;
|
||||
|
||||
d = (1 << (k+1)) - parameter;
|
||||
q = uval / parameter;
|
||||
r = uval - (q * parameter);
|
||||
|
||||
bits = 1 + q + k;
|
||||
if(r >= d)
|
||||
bits++;
|
||||
}
|
||||
return bits;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t parameter)
|
||||
{
|
||||
uint32_t total_bits, interesting_bits, msbs;
|
||||
FLAC__uint32 uval, pattern;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter < 32);
|
||||
|
||||
/* fold signed to uint32_t; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = val;
|
||||
uval <<= 1;
|
||||
uval ^= (val>>31);
|
||||
|
||||
msbs = uval >> parameter;
|
||||
interesting_bits = 1 + parameter;
|
||||
total_bits = interesting_bits + msbs;
|
||||
pattern = 1 << parameter; /* the unary end bit */
|
||||
pattern |= (uval & ((1<<parameter)-1)); /* the binary LSBs */
|
||||
|
||||
if(total_bits <= 32)
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits);
|
||||
else
|
||||
return
|
||||
FLAC__bitwriter_write_zeroes(bw, msbs) && /* write the unary MSBs */
|
||||
FLAC__bitwriter_write_raw_uint32(bw, pattern, interesting_bits); /* write the unary end bit and binary LSBs */
|
||||
}
|
||||
#endif /* UNUSED */
|
||||
|
||||
#if (ENABLE_64_BIT_WORDS == 0)
|
||||
|
||||
#define WIDE_ACCUM_TO_BW { \
|
||||
bw->accum = wide_accum >> FLAC__HALF_TEMP_BITS; \
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); \
|
||||
wide_accum <<= FLAC__HALF_TEMP_BITS; \
|
||||
bitpointer += FLAC__HALF_TEMP_BITS; \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define WIDE_ACCUM_TO_BW { \
|
||||
FLAC__ASSERT(bw->bits % FLAC__HALF_TEMP_BITS == 0); \
|
||||
if(bw->bits == 0) { \
|
||||
bw->accum = wide_accum >> FLAC__HALF_TEMP_BITS; \
|
||||
wide_accum <<= FLAC__HALF_TEMP_BITS; \
|
||||
bw->bits = FLAC__HALF_TEMP_BITS; \
|
||||
} \
|
||||
else { \
|
||||
bw->accum <<= FLAC__HALF_TEMP_BITS; \
|
||||
bw->accum += wide_accum >> FLAC__HALF_TEMP_BITS; \
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum); \
|
||||
wide_accum <<= FLAC__HALF_TEMP_BITS; \
|
||||
bw->bits = 0; \
|
||||
} \
|
||||
bitpointer += FLAC__HALF_TEMP_BITS; \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, uint32_t nvals, uint32_t parameter)
|
||||
{
|
||||
const FLAC__uint32 mask1 = (FLAC__uint32)0xffffffff << parameter; /* we val|=mask1 to set the stop bit above it... */
|
||||
const FLAC__uint32 mask2 = (FLAC__uint32)0xffffffff >> (31-parameter); /* ...then mask off the bits above the stop bit with val&=mask2 */
|
||||
FLAC__uint32 uval;
|
||||
const uint32_t lsbits = 1 + parameter;
|
||||
uint32_t msbits, total_bits;
|
||||
FLAC__bwtemp wide_accum = 0;
|
||||
FLAC__uint32 bitpointer = FLAC__TEMP_BITS;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter < 31);
|
||||
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
|
||||
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
|
||||
#if (ENABLE_64_BIT_WORDS == 0)
|
||||
if(bw->bits > 0) {
|
||||
bitpointer -= bw->bits;
|
||||
wide_accum = (FLAC__bwtemp)(bw->accum) << bitpointer;
|
||||
bw->bits = 0;
|
||||
}
|
||||
#else
|
||||
if(bw->bits > 0 && bw->bits < FLAC__HALF_TEMP_BITS) {
|
||||
bitpointer -= bw->bits;
|
||||
wide_accum = bw->accum << bitpointer;
|
||||
bw->bits = 0;
|
||||
}
|
||||
else if(bw->bits > FLAC__HALF_TEMP_BITS) {
|
||||
bitpointer -= (bw->bits - FLAC__HALF_TEMP_BITS);
|
||||
wide_accum = bw->accum << bitpointer;
|
||||
bw->accum >>= (bw->bits - FLAC__HALF_TEMP_BITS);
|
||||
bw->bits = FLAC__HALF_TEMP_BITS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Reserve one FLAC__TEMP_BITS per symbol, so checks for space are only necessary when very large symbols are encountered
|
||||
* this might be considered wasteful, but is only at most 8kB more than necessary for a blocksize of 4096 */
|
||||
if(bw->capacity * FLAC__BITS_PER_WORD <= bw->words * FLAC__BITS_PER_WORD + nvals * FLAC__TEMP_BITS + bw->bits && !bitwriter_grow_(bw, nvals * FLAC__TEMP_BITS))
|
||||
return false;
|
||||
|
||||
while(nvals) {
|
||||
/* fold signed to uint32_t; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = *vals;
|
||||
uval <<= 1;
|
||||
uval ^= (*vals>>31);
|
||||
|
||||
msbits = uval >> parameter;
|
||||
total_bits = lsbits + msbits;
|
||||
|
||||
uval |= mask1; /* set stop bit */
|
||||
uval &= mask2; /* mask off unused top bits */
|
||||
|
||||
|
||||
if(total_bits <= bitpointer) {
|
||||
/* There is room enough to store the symbol whole at once */
|
||||
wide_accum |= (FLAC__bwtemp)(uval) << (bitpointer - total_bits);
|
||||
bitpointer -= total_bits;
|
||||
if(bitpointer <= FLAC__HALF_TEMP_BITS) {
|
||||
/* A word is finished, copy the upper 32 bits of the wide_accum */
|
||||
WIDE_ACCUM_TO_BW
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* The symbol needs to be split. This code isn't used often */
|
||||
/* First check for space in the bitwriter */
|
||||
if(total_bits > FLAC__TEMP_BITS) {
|
||||
FLAC__uint32 oversize_in_bits = total_bits - FLAC__TEMP_BITS;
|
||||
FLAC__uint32 capacity_needed = bw->words * FLAC__BITS_PER_WORD + bw->bits + nvals * FLAC__TEMP_BITS + oversize_in_bits;
|
||||
if(bw->capacity * FLAC__BITS_PER_WORD <= capacity_needed && !bitwriter_grow_(bw, nvals * FLAC__TEMP_BITS + oversize_in_bits))
|
||||
return false;
|
||||
}
|
||||
if(msbits > bitpointer) {
|
||||
/* We have a lot of 0 bits to write, first align with bitwriter word */
|
||||
msbits -= bitpointer - FLAC__HALF_TEMP_BITS;
|
||||
bitpointer = FLAC__HALF_TEMP_BITS;
|
||||
WIDE_ACCUM_TO_BW
|
||||
while(msbits > bitpointer) {
|
||||
/* As the accumulator is already zero, we only need to
|
||||
* assign zeroes to the bitbuffer */
|
||||
WIDE_ACCUM_TO_BW
|
||||
bitpointer -= FLAC__HALF_TEMP_BITS;
|
||||
msbits -= FLAC__HALF_TEMP_BITS;
|
||||
}
|
||||
/* The remaining bits are zero, and the accumulator already is zero,
|
||||
* so just subtract the number of bits from bitpointer. When storing,
|
||||
* we can also just store 0 */
|
||||
bitpointer -= msbits;
|
||||
if(bitpointer <= FLAC__HALF_TEMP_BITS)
|
||||
WIDE_ACCUM_TO_BW
|
||||
}
|
||||
else {
|
||||
bitpointer -= msbits;
|
||||
if(bitpointer <= FLAC__HALF_TEMP_BITS)
|
||||
WIDE_ACCUM_TO_BW
|
||||
}
|
||||
/* The lsbs + stop bit always fit 32 bit, so this code mirrors the code above */
|
||||
wide_accum |= (FLAC__bwtemp)(uval) << (bitpointer - lsbits);
|
||||
bitpointer -= lsbits;
|
||||
if(bitpointer <= FLAC__HALF_TEMP_BITS) {
|
||||
/* A word is finished, copy the upper 32 bits of the wide_accum */
|
||||
WIDE_ACCUM_TO_BW
|
||||
}
|
||||
}
|
||||
vals++;
|
||||
nvals--;
|
||||
}
|
||||
/* Now fixup remainder of wide_accum */
|
||||
#if (ENABLE_64_BIT_WORDS == 0)
|
||||
if(bitpointer < FLAC__TEMP_BITS) {
|
||||
bw->accum = wide_accum >> bitpointer;
|
||||
bw->bits = FLAC__TEMP_BITS - bitpointer;
|
||||
}
|
||||
#else
|
||||
if(bitpointer < FLAC__TEMP_BITS) {
|
||||
if(bw->bits == 0) {
|
||||
bw->accum = wide_accum >> bitpointer;
|
||||
bw->bits = FLAC__TEMP_BITS - bitpointer;
|
||||
}
|
||||
else if (bw->bits == FLAC__HALF_TEMP_BITS) {
|
||||
bw->accum <<= FLAC__TEMP_BITS - bitpointer;
|
||||
bw->accum |= (wide_accum >> bitpointer);
|
||||
bw->bits = FLAC__HALF_TEMP_BITS + FLAC__TEMP_BITS - bitpointer;
|
||||
}
|
||||
else {
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, uint32_t parameter)
|
||||
{
|
||||
uint32_t total_bits, msbs, uval;
|
||||
uint32_t k;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
/* fold signed to uint32_t */
|
||||
if(val < 0)
|
||||
uval = (uint32_t)(((-(++val)) << 1) + 1);
|
||||
else
|
||||
uval = (uint32_t)(val << 1);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
uint32_t pattern;
|
||||
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
total_bits = 1 + k + msbs;
|
||||
pattern = 1 << k; /* the unary end bit */
|
||||
pattern |= (uval & ((1u<<k)-1)); /* the binary LSBs */
|
||||
|
||||
if(total_bits <= 32) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, msbs))
|
||||
return false;
|
||||
/* write the unary end bit and binary LSBs */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t q, r, d;
|
||||
|
||||
d = (1 << (k+1)) - parameter;
|
||||
q = uval / parameter;
|
||||
r = uval - (q * parameter);
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, q))
|
||||
return false;
|
||||
/* write the unary end bit */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1))
|
||||
return false;
|
||||
/* write the binary LSBs */
|
||||
if(r >= d) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r, k))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, uint32_t uval, uint32_t parameter)
|
||||
{
|
||||
uint32_t total_bits, msbs;
|
||||
uint32_t k;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
uint32_t pattern;
|
||||
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
total_bits = 1 + k + msbs;
|
||||
pattern = 1 << k; /* the unary end bit */
|
||||
pattern |= (uval & ((1u<<k)-1)); /* the binary LSBs */
|
||||
|
||||
if(total_bits <= 32) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, total_bits))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, msbs))
|
||||
return false;
|
||||
/* write the unary end bit and binary LSBs */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pattern, k+1))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
uint32_t q, r, d;
|
||||
|
||||
d = (1 << (k+1)) - parameter;
|
||||
q = uval / parameter;
|
||||
r = uval - (q * parameter);
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, q))
|
||||
return false;
|
||||
/* write the unary end bit */
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 1, 1))
|
||||
return false;
|
||||
/* write the binary LSBs */
|
||||
if(r >= d) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r+d, k+1))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, r, k))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
#endif /* UNUSED */
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_utf8_uint32(FLAC__BitWriter *bw, FLAC__uint32 val)
|
||||
{
|
||||
FLAC__bool ok = 1;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
if((val & 0x80000000) != 0) /* this version only handles 31 bits */
|
||||
return false;
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitwriter_write_raw_uint32_nocheck(bw, val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xC0 | (val>>6), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xE0 | (val>>12), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xF0 | (val>>18), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xF8 | (val>>24), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xFC | (val>>30), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 val)
|
||||
{
|
||||
FLAC__bool ok = 1;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
if((val & FLAC__U64L(0xFFFFFFF000000000)) != 0) /* this version only handles 36 bits */
|
||||
return false;
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitwriter_write_raw_uint32_nocheck(bw, (FLAC__uint32)val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xC0 | (FLAC__uint32)(val>>6), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xE0 | (FLAC__uint32)(val>>12), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xF0 | (FLAC__uint32)(val>>18), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xF8 | (FLAC__uint32)(val>>24), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x80000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xFC | (FLAC__uint32)(val>>30), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0xFE, 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32_nocheck(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw)
|
||||
{
|
||||
/* 0-pad to byte boundary */
|
||||
if(bw->bits & 7u)
|
||||
return FLAC__bitwriter_write_zeroes(bw, 8 - (bw->bits & 7u));
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/* These functions are declared inline in this file but are also callable as
|
||||
* externs from elsewhere.
|
||||
* According to the C99 spec, section 6.7.4, simply providing a function
|
||||
* prototype in a header file without 'inline' and making the function inline
|
||||
* in this file should be sufficient.
|
||||
* Unfortunately, the Microsoft VS compiler doesn't pick them up externally. To
|
||||
* fix that we add extern declarations here.
|
||||
*/
|
||||
extern FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, uint32_t bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, uint32_t bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, uint32_t bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_int64(FLAC__BitWriter *bw, FLAC__int64 val, uint32_t bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val);
|
||||
extern FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], uint32_t nvals);
|
||||
@@ -0,0 +1,261 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "include/private/cpu.h"
|
||||
#include "../compat.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if defined _MSC_VER
|
||||
#include <intrin.h> /* for __cpuid() and _xgetbv() */
|
||||
#elif defined __GNUC__ && defined HAVE_CPUID_H
|
||||
#include <cpuid.h> /* for __get_cpuid() and __get_cpuid_max() */
|
||||
#endif
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <stdio.h>
|
||||
#define dfprintf fprintf
|
||||
#else
|
||||
/* This is bad practice, it should be a static void empty function */
|
||||
#define dfprintf(file, format, ...)
|
||||
#endif
|
||||
|
||||
#if defined(HAVE_SYS_AUXV_H)
|
||||
#include <sys/auxv.h>
|
||||
#endif
|
||||
|
||||
#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN && !defined FLAC__NO_ASM
|
||||
|
||||
/* these are flags in EDX of CPUID AX=00000001 */
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_CMOV = 0x00008000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_MMX = 0x00800000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_SSE = 0x02000000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_SSE2 = 0x04000000;
|
||||
|
||||
/* these are flags in ECX of CPUID AX=00000001 */
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_SSE3 = 0x00000001;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_SSSE3 = 0x00000200;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_SSE41 = 0x00080000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_SSE42 = 0x00100000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_OSXSAVE = 0x08000000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_AVX = 0x10000000;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_FMA = 0x00001000;
|
||||
|
||||
/* these are flags in EBX of CPUID AX=00000007 */
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_AVX2 = 0x00000020;
|
||||
static const uint32_t FLAC__CPUINFO_X86_CPUID_BMI2 = 0x00000100;
|
||||
|
||||
#if FLAC__AVX_SUPPORTED
|
||||
static uint32_t
|
||||
cpu_xgetbv_x86(void)
|
||||
{
|
||||
#if (defined _MSC_VER || defined __INTEL_COMPILER) && FLAC__AVX_SUPPORTED
|
||||
return (uint32_t)_xgetbv(0);
|
||||
#elif defined __GNUC__
|
||||
uint32_t lo, hi;
|
||||
__asm__ volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0));
|
||||
return lo;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
static uint32_t
|
||||
cpu_have_cpuid(void)
|
||||
{
|
||||
#if defined FLAC__CPU_X86_64 || defined __i686__ || defined __SSE__ || (defined _M_IX86_FP && _M_IX86_FP > 0)
|
||||
/* target CPU does have CPUID instruction */
|
||||
return 1;
|
||||
#elif defined __GNUC__ && defined HAVE_CPUID_H
|
||||
if (__get_cpuid_max(0, 0) != 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
#elif defined _MSC_VER
|
||||
FLAC__uint32 flags1, flags2;
|
||||
__asm {
|
||||
pushfd
|
||||
pushfd
|
||||
pop eax
|
||||
mov flags1, eax
|
||||
xor eax, 0x200000
|
||||
push eax
|
||||
popfd
|
||||
pushfd
|
||||
pop eax
|
||||
mov flags2, eax
|
||||
popfd
|
||||
}
|
||||
if (((flags1^flags2) & 0x200000) != 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
cpuinfo_x86([[maybe_unused]] FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx)
|
||||
{
|
||||
#if defined _MSC_VER
|
||||
int cpuinfo[4];
|
||||
int ext = level & 0x80000000;
|
||||
__cpuid(cpuinfo, ext);
|
||||
if ((uint32_t)cpuinfo[0] >= level) {
|
||||
#if FLAC__AVX_SUPPORTED
|
||||
__cpuidex(cpuinfo, level, 0); /* for AVX2 detection */
|
||||
#else
|
||||
__cpuid(cpuinfo, level); /* some old compilers don't support __cpuidex */
|
||||
#endif
|
||||
*eax = cpuinfo[0]; *ebx = cpuinfo[1]; *ecx = cpuinfo[2]; *edx = cpuinfo[3];
|
||||
return;
|
||||
}
|
||||
#elif defined __GNUC__ && defined HAVE_CPUID_H
|
||||
FLAC__uint32 ext = level & 0x80000000;
|
||||
__cpuid(ext, *eax, *ebx, *ecx, *edx);
|
||||
if (*eax >= level) {
|
||||
__cpuid_count(level, 0, *eax, *ebx, *ecx, *edx);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
*eax = *ebx = *ecx = *edx = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void
|
||||
x86_cpu_info (FLAC__CPUInfo *info)
|
||||
{
|
||||
#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN && !defined FLAC__NO_ASM
|
||||
#if FLAC__AVX_SUPPORTED
|
||||
FLAC__bool x86_osxsave = false;
|
||||
#endif
|
||||
FLAC__bool os_avx = false;
|
||||
FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
|
||||
|
||||
info->use_asm = true; /* we assume a minimum of 80386 */
|
||||
if (!cpu_have_cpuid())
|
||||
return;
|
||||
|
||||
cpuinfo_x86(0, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
info->x86.intel = (flags_ebx == 0x756E6547 && flags_edx == 0x49656E69 && flags_ecx == 0x6C65746E) ? true : false; /* GenuineIntel */
|
||||
cpuinfo_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
|
||||
info->x86.cmov = (flags_edx & FLAC__CPUINFO_X86_CPUID_CMOV ) ? true : false;
|
||||
info->x86.mmx = (flags_edx & FLAC__CPUINFO_X86_CPUID_MMX ) ? true : false;
|
||||
info->x86.sse = (flags_edx & FLAC__CPUINFO_X86_CPUID_SSE ) ? true : false;
|
||||
info->x86.sse2 = (flags_edx & FLAC__CPUINFO_X86_CPUID_SSE2 ) ? true : false;
|
||||
info->x86.sse3 = (flags_ecx & FLAC__CPUINFO_X86_CPUID_SSE3 ) ? true : false;
|
||||
info->x86.ssse3 = (flags_ecx & FLAC__CPUINFO_X86_CPUID_SSSE3) ? true : false;
|
||||
info->x86.sse41 = (flags_ecx & FLAC__CPUINFO_X86_CPUID_SSE41) ? true : false;
|
||||
info->x86.sse42 = (flags_ecx & FLAC__CPUINFO_X86_CPUID_SSE42) ? true : false;
|
||||
|
||||
#if (FLAC__AVX_SUPPORTED)
|
||||
x86_osxsave = (flags_ecx & FLAC__CPUINFO_X86_CPUID_OSXSAVE) ? true : false;
|
||||
info->x86.avx = (flags_ecx & FLAC__CPUINFO_X86_CPUID_AVX ) ? true : false;
|
||||
info->x86.fma = (flags_ecx & FLAC__CPUINFO_X86_CPUID_FMA ) ? true : false;
|
||||
cpuinfo_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
info->x86.avx2 = (flags_ebx & FLAC__CPUINFO_X86_CPUID_AVX2 ) ? true : false;
|
||||
info->x86.bmi2 = (flags_ebx & FLAC__CPUINFO_X86_CPUID_BMI2 ) ? true : false;
|
||||
#endif
|
||||
|
||||
#if defined FLAC__CPU_IA32
|
||||
dfprintf(stderr, "CPU info (IA-32):\n", "");
|
||||
#else
|
||||
dfprintf(stderr, "CPU info (x86-64):\n", "");
|
||||
#endif
|
||||
dfprintf(stderr, " CMOV ....... %c\n", info->x86.cmov ? 'Y' : 'n');
|
||||
dfprintf(stderr, " MMX ........ %c\n", info->x86.mmx ? 'Y' : 'n');
|
||||
dfprintf(stderr, " SSE ........ %c\n", info->x86.sse ? 'Y' : 'n');
|
||||
dfprintf(stderr, " SSE2 ....... %c\n", info->x86.sse2 ? 'Y' : 'n');
|
||||
dfprintf(stderr, " SSE3 ....... %c\n", info->x86.sse3 ? 'Y' : 'n');
|
||||
dfprintf(stderr, " SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n');
|
||||
dfprintf(stderr, " SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n');
|
||||
dfprintf(stderr, " SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n');
|
||||
|
||||
if (FLAC__AVX_SUPPORTED) {
|
||||
dfprintf(stderr, " AVX ........ %c\n", info->x86.avx ? 'Y' : 'n');
|
||||
dfprintf(stderr, " FMA ........ %c\n", info->x86.fma ? 'Y' : 'n');
|
||||
dfprintf(stderr, " AVX2 ....... %c\n", info->x86.avx2 ? 'Y' : 'n');
|
||||
dfprintf(stderr, " BMI2 ....... %c\n", info->x86.bmi2 ? 'Y' : 'n');
|
||||
}
|
||||
|
||||
/*
|
||||
* now have to check for OS support of AVX instructions
|
||||
*/
|
||||
#if FLAC__AVX_SUPPORTED
|
||||
if (info->x86.avx && x86_osxsave && (cpu_xgetbv_x86() & 0x6) == 0x6) {
|
||||
os_avx = true;
|
||||
}
|
||||
#endif
|
||||
if (os_avx) {
|
||||
dfprintf(stderr, " AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n');
|
||||
}
|
||||
if (!os_avx) {
|
||||
/* no OS AVX support */
|
||||
info->x86.avx = false;
|
||||
info->x86.avx2 = false;
|
||||
info->x86.fma = false;
|
||||
}
|
||||
#else
|
||||
info->use_asm = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
void FLAC__cpu_info (FLAC__CPUInfo *info)
|
||||
{
|
||||
memset(info, 0, sizeof(*info));
|
||||
|
||||
#ifdef FLAC__CPU_IA32
|
||||
info->type = FLAC__CPUINFO_TYPE_IA32;
|
||||
#elif defined FLAC__CPU_X86_64
|
||||
info->type = FLAC__CPUINFO_TYPE_X86_64;
|
||||
#else
|
||||
info->type = FLAC__CPUINFO_TYPE_UNKNOWN;
|
||||
#endif
|
||||
|
||||
switch (info->type) {
|
||||
case FLAC__CPUINFO_TYPE_IA32: /* fallthrough */
|
||||
case FLAC__CPUINFO_TYPE_X86_64:
|
||||
x86_cpu_info (info);
|
||||
break;
|
||||
default:
|
||||
info->use_asm = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "include/private/crc.h"
|
||||
|
||||
/* CRC-8, poly = x^8 + x^2 + x^1 + x^0, init = 0 */
|
||||
|
||||
FLAC__uint8 const FLAC__crc8_table[256] = {
|
||||
0x00, 0x07, 0x0E, 0x09, 0x1C, 0x1B, 0x12, 0x15,
|
||||
0x38, 0x3F, 0x36, 0x31, 0x24, 0x23, 0x2A, 0x2D,
|
||||
0x70, 0x77, 0x7E, 0x79, 0x6C, 0x6B, 0x62, 0x65,
|
||||
0x48, 0x4F, 0x46, 0x41, 0x54, 0x53, 0x5A, 0x5D,
|
||||
0xE0, 0xE7, 0xEE, 0xE9, 0xFC, 0xFB, 0xF2, 0xF5,
|
||||
0xD8, 0xDF, 0xD6, 0xD1, 0xC4, 0xC3, 0xCA, 0xCD,
|
||||
0x90, 0x97, 0x9E, 0x99, 0x8C, 0x8B, 0x82, 0x85,
|
||||
0xA8, 0xAF, 0xA6, 0xA1, 0xB4, 0xB3, 0xBA, 0xBD,
|
||||
0xC7, 0xC0, 0xC9, 0xCE, 0xDB, 0xDC, 0xD5, 0xD2,
|
||||
0xFF, 0xF8, 0xF1, 0xF6, 0xE3, 0xE4, 0xED, 0xEA,
|
||||
0xB7, 0xB0, 0xB9, 0xBE, 0xAB, 0xAC, 0xA5, 0xA2,
|
||||
0x8F, 0x88, 0x81, 0x86, 0x93, 0x94, 0x9D, 0x9A,
|
||||
0x27, 0x20, 0x29, 0x2E, 0x3B, 0x3C, 0x35, 0x32,
|
||||
0x1F, 0x18, 0x11, 0x16, 0x03, 0x04, 0x0D, 0x0A,
|
||||
0x57, 0x50, 0x59, 0x5E, 0x4B, 0x4C, 0x45, 0x42,
|
||||
0x6F, 0x68, 0x61, 0x66, 0x73, 0x74, 0x7D, 0x7A,
|
||||
0x89, 0x8E, 0x87, 0x80, 0x95, 0x92, 0x9B, 0x9C,
|
||||
0xB1, 0xB6, 0xBF, 0xB8, 0xAD, 0xAA, 0xA3, 0xA4,
|
||||
0xF9, 0xFE, 0xF7, 0xF0, 0xE5, 0xE2, 0xEB, 0xEC,
|
||||
0xC1, 0xC6, 0xCF, 0xC8, 0xDD, 0xDA, 0xD3, 0xD4,
|
||||
0x69, 0x6E, 0x67, 0x60, 0x75, 0x72, 0x7B, 0x7C,
|
||||
0x51, 0x56, 0x5F, 0x58, 0x4D, 0x4A, 0x43, 0x44,
|
||||
0x19, 0x1E, 0x17, 0x10, 0x05, 0x02, 0x0B, 0x0C,
|
||||
0x21, 0x26, 0x2F, 0x28, 0x3D, 0x3A, 0x33, 0x34,
|
||||
0x4E, 0x49, 0x40, 0x47, 0x52, 0x55, 0x5C, 0x5B,
|
||||
0x76, 0x71, 0x78, 0x7F, 0x6A, 0x6D, 0x64, 0x63,
|
||||
0x3E, 0x39, 0x30, 0x37, 0x22, 0x25, 0x2C, 0x2B,
|
||||
0x06, 0x01, 0x08, 0x0F, 0x1A, 0x1D, 0x14, 0x13,
|
||||
0xAE, 0xA9, 0xA0, 0xA7, 0xB2, 0xB5, 0xBC, 0xBB,
|
||||
0x96, 0x91, 0x98, 0x9F, 0x8A, 0x8D, 0x84, 0x83,
|
||||
0xDE, 0xD9, 0xD0, 0xD7, 0xC2, 0xC5, 0xCC, 0xCB,
|
||||
0xE6, 0xE1, 0xE8, 0xEF, 0xFA, 0xFD, 0xF4, 0xF3
|
||||
};
|
||||
|
||||
/* CRC-16, poly = x^16 + x^15 + x^2 + x^0, init = 0 */
|
||||
|
||||
FLAC__uint16 const FLAC__crc16_table[8][256] = {
|
||||
{ 0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
|
||||
0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
|
||||
0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
|
||||
0x0050, 0x8055, 0x805f, 0x005a, 0x804b, 0x004e, 0x0044, 0x8041,
|
||||
0x80c3, 0x00c6, 0x00cc, 0x80c9, 0x00d8, 0x80dd, 0x80d7, 0x00d2,
|
||||
0x00f0, 0x80f5, 0x80ff, 0x00fa, 0x80eb, 0x00ee, 0x00e4, 0x80e1,
|
||||
0x00a0, 0x80a5, 0x80af, 0x00aa, 0x80bb, 0x00be, 0x00b4, 0x80b1,
|
||||
0x8093, 0x0096, 0x009c, 0x8099, 0x0088, 0x808d, 0x8087, 0x0082,
|
||||
0x8183, 0x0186, 0x018c, 0x8189, 0x0198, 0x819d, 0x8197, 0x0192,
|
||||
0x01b0, 0x81b5, 0x81bf, 0x01ba, 0x81ab, 0x01ae, 0x01a4, 0x81a1,
|
||||
0x01e0, 0x81e5, 0x81ef, 0x01ea, 0x81fb, 0x01fe, 0x01f4, 0x81f1,
|
||||
0x81d3, 0x01d6, 0x01dc, 0x81d9, 0x01c8, 0x81cd, 0x81c7, 0x01c2,
|
||||
0x0140, 0x8145, 0x814f, 0x014a, 0x815b, 0x015e, 0x0154, 0x8151,
|
||||
0x8173, 0x0176, 0x017c, 0x8179, 0x0168, 0x816d, 0x8167, 0x0162,
|
||||
0x8123, 0x0126, 0x012c, 0x8129, 0x0138, 0x813d, 0x8137, 0x0132,
|
||||
0x0110, 0x8115, 0x811f, 0x011a, 0x810b, 0x010e, 0x0104, 0x8101,
|
||||
0x8303, 0x0306, 0x030c, 0x8309, 0x0318, 0x831d, 0x8317, 0x0312,
|
||||
0x0330, 0x8335, 0x833f, 0x033a, 0x832b, 0x032e, 0x0324, 0x8321,
|
||||
0x0360, 0x8365, 0x836f, 0x036a, 0x837b, 0x037e, 0x0374, 0x8371,
|
||||
0x8353, 0x0356, 0x035c, 0x8359, 0x0348, 0x834d, 0x8347, 0x0342,
|
||||
0x03c0, 0x83c5, 0x83cf, 0x03ca, 0x83db, 0x03de, 0x03d4, 0x83d1,
|
||||
0x83f3, 0x03f6, 0x03fc, 0x83f9, 0x03e8, 0x83ed, 0x83e7, 0x03e2,
|
||||
0x83a3, 0x03a6, 0x03ac, 0x83a9, 0x03b8, 0x83bd, 0x83b7, 0x03b2,
|
||||
0x0390, 0x8395, 0x839f, 0x039a, 0x838b, 0x038e, 0x0384, 0x8381,
|
||||
0x0280, 0x8285, 0x828f, 0x028a, 0x829b, 0x029e, 0x0294, 0x8291,
|
||||
0x82b3, 0x02b6, 0x02bc, 0x82b9, 0x02a8, 0x82ad, 0x82a7, 0x02a2,
|
||||
0x82e3, 0x02e6, 0x02ec, 0x82e9, 0x02f8, 0x82fd, 0x82f7, 0x02f2,
|
||||
0x02d0, 0x82d5, 0x82df, 0x02da, 0x82cb, 0x02ce, 0x02c4, 0x82c1,
|
||||
0x8243, 0x0246, 0x024c, 0x8249, 0x0258, 0x825d, 0x8257, 0x0252,
|
||||
0x0270, 0x8275, 0x827f, 0x027a, 0x826b, 0x026e, 0x0264, 0x8261,
|
||||
0x0220, 0x8225, 0x822f, 0x022a, 0x823b, 0x023e, 0x0234, 0x8231,
|
||||
0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202 },
|
||||
|
||||
{ 0x0000, 0x8603, 0x8c03, 0x0a00, 0x9803, 0x1e00, 0x1400, 0x9203,
|
||||
0xb003, 0x3600, 0x3c00, 0xba03, 0x2800, 0xae03, 0xa403, 0x2200,
|
||||
0xe003, 0x6600, 0x6c00, 0xea03, 0x7800, 0xfe03, 0xf403, 0x7200,
|
||||
0x5000, 0xd603, 0xdc03, 0x5a00, 0xc803, 0x4e00, 0x4400, 0xc203,
|
||||
0x4003, 0xc600, 0xcc00, 0x4a03, 0xd800, 0x5e03, 0x5403, 0xd200,
|
||||
0xf000, 0x7603, 0x7c03, 0xfa00, 0x6803, 0xee00, 0xe400, 0x6203,
|
||||
0xa000, 0x2603, 0x2c03, 0xaa00, 0x3803, 0xbe00, 0xb400, 0x3203,
|
||||
0x1003, 0x9600, 0x9c00, 0x1a03, 0x8800, 0x0e03, 0x0403, 0x8200,
|
||||
0x8006, 0x0605, 0x0c05, 0x8a06, 0x1805, 0x9e06, 0x9406, 0x1205,
|
||||
0x3005, 0xb606, 0xbc06, 0x3a05, 0xa806, 0x2e05, 0x2405, 0xa206,
|
||||
0x6005, 0xe606, 0xec06, 0x6a05, 0xf806, 0x7e05, 0x7405, 0xf206,
|
||||
0xd006, 0x5605, 0x5c05, 0xda06, 0x4805, 0xce06, 0xc406, 0x4205,
|
||||
0xc005, 0x4606, 0x4c06, 0xca05, 0x5806, 0xde05, 0xd405, 0x5206,
|
||||
0x7006, 0xf605, 0xfc05, 0x7a06, 0xe805, 0x6e06, 0x6406, 0xe205,
|
||||
0x2006, 0xa605, 0xac05, 0x2a06, 0xb805, 0x3e06, 0x3406, 0xb205,
|
||||
0x9005, 0x1606, 0x1c06, 0x9a05, 0x0806, 0x8e05, 0x8405, 0x0206,
|
||||
0x8009, 0x060a, 0x0c0a, 0x8a09, 0x180a, 0x9e09, 0x9409, 0x120a,
|
||||
0x300a, 0xb609, 0xbc09, 0x3a0a, 0xa809, 0x2e0a, 0x240a, 0xa209,
|
||||
0x600a, 0xe609, 0xec09, 0x6a0a, 0xf809, 0x7e0a, 0x740a, 0xf209,
|
||||
0xd009, 0x560a, 0x5c0a, 0xda09, 0x480a, 0xce09, 0xc409, 0x420a,
|
||||
0xc00a, 0x4609, 0x4c09, 0xca0a, 0x5809, 0xde0a, 0xd40a, 0x5209,
|
||||
0x7009, 0xf60a, 0xfc0a, 0x7a09, 0xe80a, 0x6e09, 0x6409, 0xe20a,
|
||||
0x2009, 0xa60a, 0xac0a, 0x2a09, 0xb80a, 0x3e09, 0x3409, 0xb20a,
|
||||
0x900a, 0x1609, 0x1c09, 0x9a0a, 0x0809, 0x8e0a, 0x840a, 0x0209,
|
||||
0x000f, 0x860c, 0x8c0c, 0x0a0f, 0x980c, 0x1e0f, 0x140f, 0x920c,
|
||||
0xb00c, 0x360f, 0x3c0f, 0xba0c, 0x280f, 0xae0c, 0xa40c, 0x220f,
|
||||
0xe00c, 0x660f, 0x6c0f, 0xea0c, 0x780f, 0xfe0c, 0xf40c, 0x720f,
|
||||
0x500f, 0xd60c, 0xdc0c, 0x5a0f, 0xc80c, 0x4e0f, 0x440f, 0xc20c,
|
||||
0x400c, 0xc60f, 0xcc0f, 0x4a0c, 0xd80f, 0x5e0c, 0x540c, 0xd20f,
|
||||
0xf00f, 0x760c, 0x7c0c, 0xfa0f, 0x680c, 0xee0f, 0xe40f, 0x620c,
|
||||
0xa00f, 0x260c, 0x2c0c, 0xaa0f, 0x380c, 0xbe0f, 0xb40f, 0x320c,
|
||||
0x100c, 0x960f, 0x9c0f, 0x1a0c, 0x880f, 0x0e0c, 0x040c, 0x820f },
|
||||
|
||||
{ 0x0000, 0x8017, 0x802b, 0x003c, 0x8053, 0x0044, 0x0078, 0x806f,
|
||||
0x80a3, 0x00b4, 0x0088, 0x809f, 0x00f0, 0x80e7, 0x80db, 0x00cc,
|
||||
0x8143, 0x0154, 0x0168, 0x817f, 0x0110, 0x8107, 0x813b, 0x012c,
|
||||
0x01e0, 0x81f7, 0x81cb, 0x01dc, 0x81b3, 0x01a4, 0x0198, 0x818f,
|
||||
0x8283, 0x0294, 0x02a8, 0x82bf, 0x02d0, 0x82c7, 0x82fb, 0x02ec,
|
||||
0x0220, 0x8237, 0x820b, 0x021c, 0x8273, 0x0264, 0x0258, 0x824f,
|
||||
0x03c0, 0x83d7, 0x83eb, 0x03fc, 0x8393, 0x0384, 0x03b8, 0x83af,
|
||||
0x8363, 0x0374, 0x0348, 0x835f, 0x0330, 0x8327, 0x831b, 0x030c,
|
||||
0x8503, 0x0514, 0x0528, 0x853f, 0x0550, 0x8547, 0x857b, 0x056c,
|
||||
0x05a0, 0x85b7, 0x858b, 0x059c, 0x85f3, 0x05e4, 0x05d8, 0x85cf,
|
||||
0x0440, 0x8457, 0x846b, 0x047c, 0x8413, 0x0404, 0x0438, 0x842f,
|
||||
0x84e3, 0x04f4, 0x04c8, 0x84df, 0x04b0, 0x84a7, 0x849b, 0x048c,
|
||||
0x0780, 0x8797, 0x87ab, 0x07bc, 0x87d3, 0x07c4, 0x07f8, 0x87ef,
|
||||
0x8723, 0x0734, 0x0708, 0x871f, 0x0770, 0x8767, 0x875b, 0x074c,
|
||||
0x86c3, 0x06d4, 0x06e8, 0x86ff, 0x0690, 0x8687, 0x86bb, 0x06ac,
|
||||
0x0660, 0x8677, 0x864b, 0x065c, 0x8633, 0x0624, 0x0618, 0x860f,
|
||||
0x8a03, 0x0a14, 0x0a28, 0x8a3f, 0x0a50, 0x8a47, 0x8a7b, 0x0a6c,
|
||||
0x0aa0, 0x8ab7, 0x8a8b, 0x0a9c, 0x8af3, 0x0ae4, 0x0ad8, 0x8acf,
|
||||
0x0b40, 0x8b57, 0x8b6b, 0x0b7c, 0x8b13, 0x0b04, 0x0b38, 0x8b2f,
|
||||
0x8be3, 0x0bf4, 0x0bc8, 0x8bdf, 0x0bb0, 0x8ba7, 0x8b9b, 0x0b8c,
|
||||
0x0880, 0x8897, 0x88ab, 0x08bc, 0x88d3, 0x08c4, 0x08f8, 0x88ef,
|
||||
0x8823, 0x0834, 0x0808, 0x881f, 0x0870, 0x8867, 0x885b, 0x084c,
|
||||
0x89c3, 0x09d4, 0x09e8, 0x89ff, 0x0990, 0x8987, 0x89bb, 0x09ac,
|
||||
0x0960, 0x8977, 0x894b, 0x095c, 0x8933, 0x0924, 0x0918, 0x890f,
|
||||
0x0f00, 0x8f17, 0x8f2b, 0x0f3c, 0x8f53, 0x0f44, 0x0f78, 0x8f6f,
|
||||
0x8fa3, 0x0fb4, 0x0f88, 0x8f9f, 0x0ff0, 0x8fe7, 0x8fdb, 0x0fcc,
|
||||
0x8e43, 0x0e54, 0x0e68, 0x8e7f, 0x0e10, 0x8e07, 0x8e3b, 0x0e2c,
|
||||
0x0ee0, 0x8ef7, 0x8ecb, 0x0edc, 0x8eb3, 0x0ea4, 0x0e98, 0x8e8f,
|
||||
0x8d83, 0x0d94, 0x0da8, 0x8dbf, 0x0dd0, 0x8dc7, 0x8dfb, 0x0dec,
|
||||
0x0d20, 0x8d37, 0x8d0b, 0x0d1c, 0x8d73, 0x0d64, 0x0d58, 0x8d4f,
|
||||
0x0cc0, 0x8cd7, 0x8ceb, 0x0cfc, 0x8c93, 0x0c84, 0x0cb8, 0x8caf,
|
||||
0x8c63, 0x0c74, 0x0c48, 0x8c5f, 0x0c30, 0x8c27, 0x8c1b, 0x0c0c },
|
||||
|
||||
{ 0x0000, 0x9403, 0xa803, 0x3c00, 0xd003, 0x4400, 0x7800, 0xec03,
|
||||
0x2003, 0xb400, 0x8800, 0x1c03, 0xf000, 0x6403, 0x5803, 0xcc00,
|
||||
0x4006, 0xd405, 0xe805, 0x7c06, 0x9005, 0x0406, 0x3806, 0xac05,
|
||||
0x6005, 0xf406, 0xc806, 0x5c05, 0xb006, 0x2405, 0x1805, 0x8c06,
|
||||
0x800c, 0x140f, 0x280f, 0xbc0c, 0x500f, 0xc40c, 0xf80c, 0x6c0f,
|
||||
0xa00f, 0x340c, 0x080c, 0x9c0f, 0x700c, 0xe40f, 0xd80f, 0x4c0c,
|
||||
0xc00a, 0x5409, 0x6809, 0xfc0a, 0x1009, 0x840a, 0xb80a, 0x2c09,
|
||||
0xe009, 0x740a, 0x480a, 0xdc09, 0x300a, 0xa409, 0x9809, 0x0c0a,
|
||||
0x801d, 0x141e, 0x281e, 0xbc1d, 0x501e, 0xc41d, 0xf81d, 0x6c1e,
|
||||
0xa01e, 0x341d, 0x081d, 0x9c1e, 0x701d, 0xe41e, 0xd81e, 0x4c1d,
|
||||
0xc01b, 0x5418, 0x6818, 0xfc1b, 0x1018, 0x841b, 0xb81b, 0x2c18,
|
||||
0xe018, 0x741b, 0x481b, 0xdc18, 0x301b, 0xa418, 0x9818, 0x0c1b,
|
||||
0x0011, 0x9412, 0xa812, 0x3c11, 0xd012, 0x4411, 0x7811, 0xec12,
|
||||
0x2012, 0xb411, 0x8811, 0x1c12, 0xf011, 0x6412, 0x5812, 0xcc11,
|
||||
0x4017, 0xd414, 0xe814, 0x7c17, 0x9014, 0x0417, 0x3817, 0xac14,
|
||||
0x6014, 0xf417, 0xc817, 0x5c14, 0xb017, 0x2414, 0x1814, 0x8c17,
|
||||
0x803f, 0x143c, 0x283c, 0xbc3f, 0x503c, 0xc43f, 0xf83f, 0x6c3c,
|
||||
0xa03c, 0x343f, 0x083f, 0x9c3c, 0x703f, 0xe43c, 0xd83c, 0x4c3f,
|
||||
0xc039, 0x543a, 0x683a, 0xfc39, 0x103a, 0x8439, 0xb839, 0x2c3a,
|
||||
0xe03a, 0x7439, 0x4839, 0xdc3a, 0x3039, 0xa43a, 0x983a, 0x0c39,
|
||||
0x0033, 0x9430, 0xa830, 0x3c33, 0xd030, 0x4433, 0x7833, 0xec30,
|
||||
0x2030, 0xb433, 0x8833, 0x1c30, 0xf033, 0x6430, 0x5830, 0xcc33,
|
||||
0x4035, 0xd436, 0xe836, 0x7c35, 0x9036, 0x0435, 0x3835, 0xac36,
|
||||
0x6036, 0xf435, 0xc835, 0x5c36, 0xb035, 0x2436, 0x1836, 0x8c35,
|
||||
0x0022, 0x9421, 0xa821, 0x3c22, 0xd021, 0x4422, 0x7822, 0xec21,
|
||||
0x2021, 0xb422, 0x8822, 0x1c21, 0xf022, 0x6421, 0x5821, 0xcc22,
|
||||
0x4024, 0xd427, 0xe827, 0x7c24, 0x9027, 0x0424, 0x3824, 0xac27,
|
||||
0x6027, 0xf424, 0xc824, 0x5c27, 0xb024, 0x2427, 0x1827, 0x8c24,
|
||||
0x802e, 0x142d, 0x282d, 0xbc2e, 0x502d, 0xc42e, 0xf82e, 0x6c2d,
|
||||
0xa02d, 0x342e, 0x082e, 0x9c2d, 0x702e, 0xe42d, 0xd82d, 0x4c2e,
|
||||
0xc028, 0x542b, 0x682b, 0xfc28, 0x102b, 0x8428, 0xb828, 0x2c2b,
|
||||
0xe02b, 0x7428, 0x4828, 0xdc2b, 0x3028, 0xa42b, 0x982b, 0x0c28 },
|
||||
|
||||
{ 0x0000, 0x807b, 0x80f3, 0x0088, 0x81e3, 0x0198, 0x0110, 0x816b,
|
||||
0x83c3, 0x03b8, 0x0330, 0x834b, 0x0220, 0x825b, 0x82d3, 0x02a8,
|
||||
0x8783, 0x07f8, 0x0770, 0x870b, 0x0660, 0x861b, 0x8693, 0x06e8,
|
||||
0x0440, 0x843b, 0x84b3, 0x04c8, 0x85a3, 0x05d8, 0x0550, 0x852b,
|
||||
0x8f03, 0x0f78, 0x0ff0, 0x8f8b, 0x0ee0, 0x8e9b, 0x8e13, 0x0e68,
|
||||
0x0cc0, 0x8cbb, 0x8c33, 0x0c48, 0x8d23, 0x0d58, 0x0dd0, 0x8dab,
|
||||
0x0880, 0x88fb, 0x8873, 0x0808, 0x8963, 0x0918, 0x0990, 0x89eb,
|
||||
0x8b43, 0x0b38, 0x0bb0, 0x8bcb, 0x0aa0, 0x8adb, 0x8a53, 0x0a28,
|
||||
0x9e03, 0x1e78, 0x1ef0, 0x9e8b, 0x1fe0, 0x9f9b, 0x9f13, 0x1f68,
|
||||
0x1dc0, 0x9dbb, 0x9d33, 0x1d48, 0x9c23, 0x1c58, 0x1cd0, 0x9cab,
|
||||
0x1980, 0x99fb, 0x9973, 0x1908, 0x9863, 0x1818, 0x1890, 0x98eb,
|
||||
0x9a43, 0x1a38, 0x1ab0, 0x9acb, 0x1ba0, 0x9bdb, 0x9b53, 0x1b28,
|
||||
0x1100, 0x917b, 0x91f3, 0x1188, 0x90e3, 0x1098, 0x1010, 0x906b,
|
||||
0x92c3, 0x12b8, 0x1230, 0x924b, 0x1320, 0x935b, 0x93d3, 0x13a8,
|
||||
0x9683, 0x16f8, 0x1670, 0x960b, 0x1760, 0x971b, 0x9793, 0x17e8,
|
||||
0x1540, 0x953b, 0x95b3, 0x15c8, 0x94a3, 0x14d8, 0x1450, 0x942b,
|
||||
0xbc03, 0x3c78, 0x3cf0, 0xbc8b, 0x3de0, 0xbd9b, 0xbd13, 0x3d68,
|
||||
0x3fc0, 0xbfbb, 0xbf33, 0x3f48, 0xbe23, 0x3e58, 0x3ed0, 0xbeab,
|
||||
0x3b80, 0xbbfb, 0xbb73, 0x3b08, 0xba63, 0x3a18, 0x3a90, 0xbaeb,
|
||||
0xb843, 0x3838, 0x38b0, 0xb8cb, 0x39a0, 0xb9db, 0xb953, 0x3928,
|
||||
0x3300, 0xb37b, 0xb3f3, 0x3388, 0xb2e3, 0x3298, 0x3210, 0xb26b,
|
||||
0xb0c3, 0x30b8, 0x3030, 0xb04b, 0x3120, 0xb15b, 0xb1d3, 0x31a8,
|
||||
0xb483, 0x34f8, 0x3470, 0xb40b, 0x3560, 0xb51b, 0xb593, 0x35e8,
|
||||
0x3740, 0xb73b, 0xb7b3, 0x37c8, 0xb6a3, 0x36d8, 0x3650, 0xb62b,
|
||||
0x2200, 0xa27b, 0xa2f3, 0x2288, 0xa3e3, 0x2398, 0x2310, 0xa36b,
|
||||
0xa1c3, 0x21b8, 0x2130, 0xa14b, 0x2020, 0xa05b, 0xa0d3, 0x20a8,
|
||||
0xa583, 0x25f8, 0x2570, 0xa50b, 0x2460, 0xa41b, 0xa493, 0x24e8,
|
||||
0x2640, 0xa63b, 0xa6b3, 0x26c8, 0xa7a3, 0x27d8, 0x2750, 0xa72b,
|
||||
0xad03, 0x2d78, 0x2df0, 0xad8b, 0x2ce0, 0xac9b, 0xac13, 0x2c68,
|
||||
0x2ec0, 0xaebb, 0xae33, 0x2e48, 0xaf23, 0x2f58, 0x2fd0, 0xafab,
|
||||
0x2a80, 0xaafb, 0xaa73, 0x2a08, 0xab63, 0x2b18, 0x2b90, 0xabeb,
|
||||
0xa943, 0x2938, 0x29b0, 0xa9cb, 0x28a0, 0xa8db, 0xa853, 0x2828 },
|
||||
|
||||
{ 0x0000, 0xf803, 0x7003, 0x8800, 0xe006, 0x1805, 0x9005, 0x6806,
|
||||
0x4009, 0xb80a, 0x300a, 0xc809, 0xa00f, 0x580c, 0xd00c, 0x280f,
|
||||
0x8012, 0x7811, 0xf011, 0x0812, 0x6014, 0x9817, 0x1017, 0xe814,
|
||||
0xc01b, 0x3818, 0xb018, 0x481b, 0x201d, 0xd81e, 0x501e, 0xa81d,
|
||||
0x8021, 0x7822, 0xf022, 0x0821, 0x6027, 0x9824, 0x1024, 0xe827,
|
||||
0xc028, 0x382b, 0xb02b, 0x4828, 0x202e, 0xd82d, 0x502d, 0xa82e,
|
||||
0x0033, 0xf830, 0x7030, 0x8833, 0xe035, 0x1836, 0x9036, 0x6835,
|
||||
0x403a, 0xb839, 0x3039, 0xc83a, 0xa03c, 0x583f, 0xd03f, 0x283c,
|
||||
0x8047, 0x7844, 0xf044, 0x0847, 0x6041, 0x9842, 0x1042, 0xe841,
|
||||
0xc04e, 0x384d, 0xb04d, 0x484e, 0x2048, 0xd84b, 0x504b, 0xa848,
|
||||
0x0055, 0xf856, 0x7056, 0x8855, 0xe053, 0x1850, 0x9050, 0x6853,
|
||||
0x405c, 0xb85f, 0x305f, 0xc85c, 0xa05a, 0x5859, 0xd059, 0x285a,
|
||||
0x0066, 0xf865, 0x7065, 0x8866, 0xe060, 0x1863, 0x9063, 0x6860,
|
||||
0x406f, 0xb86c, 0x306c, 0xc86f, 0xa069, 0x586a, 0xd06a, 0x2869,
|
||||
0x8074, 0x7877, 0xf077, 0x0874, 0x6072, 0x9871, 0x1071, 0xe872,
|
||||
0xc07d, 0x387e, 0xb07e, 0x487d, 0x207b, 0xd878, 0x5078, 0xa87b,
|
||||
0x808b, 0x7888, 0xf088, 0x088b, 0x608d, 0x988e, 0x108e, 0xe88d,
|
||||
0xc082, 0x3881, 0xb081, 0x4882, 0x2084, 0xd887, 0x5087, 0xa884,
|
||||
0x0099, 0xf89a, 0x709a, 0x8899, 0xe09f, 0x189c, 0x909c, 0x689f,
|
||||
0x4090, 0xb893, 0x3093, 0xc890, 0xa096, 0x5895, 0xd095, 0x2896,
|
||||
0x00aa, 0xf8a9, 0x70a9, 0x88aa, 0xe0ac, 0x18af, 0x90af, 0x68ac,
|
||||
0x40a3, 0xb8a0, 0x30a0, 0xc8a3, 0xa0a5, 0x58a6, 0xd0a6, 0x28a5,
|
||||
0x80b8, 0x78bb, 0xf0bb, 0x08b8, 0x60be, 0x98bd, 0x10bd, 0xe8be,
|
||||
0xc0b1, 0x38b2, 0xb0b2, 0x48b1, 0x20b7, 0xd8b4, 0x50b4, 0xa8b7,
|
||||
0x00cc, 0xf8cf, 0x70cf, 0x88cc, 0xe0ca, 0x18c9, 0x90c9, 0x68ca,
|
||||
0x40c5, 0xb8c6, 0x30c6, 0xc8c5, 0xa0c3, 0x58c0, 0xd0c0, 0x28c3,
|
||||
0x80de, 0x78dd, 0xf0dd, 0x08de, 0x60d8, 0x98db, 0x10db, 0xe8d8,
|
||||
0xc0d7, 0x38d4, 0xb0d4, 0x48d7, 0x20d1, 0xd8d2, 0x50d2, 0xa8d1,
|
||||
0x80ed, 0x78ee, 0xf0ee, 0x08ed, 0x60eb, 0x98e8, 0x10e8, 0xe8eb,
|
||||
0xc0e4, 0x38e7, 0xb0e7, 0x48e4, 0x20e2, 0xd8e1, 0x50e1, 0xa8e2,
|
||||
0x00ff, 0xf8fc, 0x70fc, 0x88ff, 0xe0f9, 0x18fa, 0x90fa, 0x68f9,
|
||||
0x40f6, 0xb8f5, 0x30f5, 0xc8f6, 0xa0f0, 0x58f3, 0xd0f3, 0x28f0 },
|
||||
|
||||
{ 0x0000, 0x8113, 0x8223, 0x0330, 0x8443, 0x0550, 0x0660, 0x8773,
|
||||
0x8883, 0x0990, 0x0aa0, 0x8bb3, 0x0cc0, 0x8dd3, 0x8ee3, 0x0ff0,
|
||||
0x9103, 0x1010, 0x1320, 0x9233, 0x1540, 0x9453, 0x9763, 0x1670,
|
||||
0x1980, 0x9893, 0x9ba3, 0x1ab0, 0x9dc3, 0x1cd0, 0x1fe0, 0x9ef3,
|
||||
0xa203, 0x2310, 0x2020, 0xa133, 0x2640, 0xa753, 0xa463, 0x2570,
|
||||
0x2a80, 0xab93, 0xa8a3, 0x29b0, 0xaec3, 0x2fd0, 0x2ce0, 0xadf3,
|
||||
0x3300, 0xb213, 0xb123, 0x3030, 0xb743, 0x3650, 0x3560, 0xb473,
|
||||
0xbb83, 0x3a90, 0x39a0, 0xb8b3, 0x3fc0, 0xbed3, 0xbde3, 0x3cf0,
|
||||
0xc403, 0x4510, 0x4620, 0xc733, 0x4040, 0xc153, 0xc263, 0x4370,
|
||||
0x4c80, 0xcd93, 0xcea3, 0x4fb0, 0xc8c3, 0x49d0, 0x4ae0, 0xcbf3,
|
||||
0x5500, 0xd413, 0xd723, 0x5630, 0xd143, 0x5050, 0x5360, 0xd273,
|
||||
0xdd83, 0x5c90, 0x5fa0, 0xdeb3, 0x59c0, 0xd8d3, 0xdbe3, 0x5af0,
|
||||
0x6600, 0xe713, 0xe423, 0x6530, 0xe243, 0x6350, 0x6060, 0xe173,
|
||||
0xee83, 0x6f90, 0x6ca0, 0xedb3, 0x6ac0, 0xebd3, 0xe8e3, 0x69f0,
|
||||
0xf703, 0x7610, 0x7520, 0xf433, 0x7340, 0xf253, 0xf163, 0x7070,
|
||||
0x7f80, 0xfe93, 0xfda3, 0x7cb0, 0xfbc3, 0x7ad0, 0x79e0, 0xf8f3,
|
||||
0x0803, 0x8910, 0x8a20, 0x0b33, 0x8c40, 0x0d53, 0x0e63, 0x8f70,
|
||||
0x8080, 0x0193, 0x02a3, 0x83b0, 0x04c3, 0x85d0, 0x86e0, 0x07f3,
|
||||
0x9900, 0x1813, 0x1b23, 0x9a30, 0x1d43, 0x9c50, 0x9f60, 0x1e73,
|
||||
0x1183, 0x9090, 0x93a0, 0x12b3, 0x95c0, 0x14d3, 0x17e3, 0x96f0,
|
||||
0xaa00, 0x2b13, 0x2823, 0xa930, 0x2e43, 0xaf50, 0xac60, 0x2d73,
|
||||
0x2283, 0xa390, 0xa0a0, 0x21b3, 0xa6c0, 0x27d3, 0x24e3, 0xa5f0,
|
||||
0x3b03, 0xba10, 0xb920, 0x3833, 0xbf40, 0x3e53, 0x3d63, 0xbc70,
|
||||
0xb380, 0x3293, 0x31a3, 0xb0b0, 0x37c3, 0xb6d0, 0xb5e0, 0x34f3,
|
||||
0xcc00, 0x4d13, 0x4e23, 0xcf30, 0x4843, 0xc950, 0xca60, 0x4b73,
|
||||
0x4483, 0xc590, 0xc6a0, 0x47b3, 0xc0c0, 0x41d3, 0x42e3, 0xc3f0,
|
||||
0x5d03, 0xdc10, 0xdf20, 0x5e33, 0xd940, 0x5853, 0x5b63, 0xda70,
|
||||
0xd580, 0x5493, 0x57a3, 0xd6b0, 0x51c3, 0xd0d0, 0xd3e0, 0x52f3,
|
||||
0x6e03, 0xef10, 0xec20, 0x6d33, 0xea40, 0x6b53, 0x6863, 0xe970,
|
||||
0xe680, 0x6793, 0x64a3, 0xe5b0, 0x62c3, 0xe3d0, 0xe0e0, 0x61f3,
|
||||
0xff00, 0x7e13, 0x7d23, 0xfc30, 0x7b43, 0xfa50, 0xf960, 0x7873,
|
||||
0x7783, 0xf690, 0xf5a0, 0x74b3, 0xf3c0, 0x72d3, 0x71e3, 0xf0f0 },
|
||||
|
||||
{ 0x0000, 0x1006, 0x200c, 0x300a, 0x4018, 0x501e, 0x6014, 0x7012,
|
||||
0x8030, 0x9036, 0xa03c, 0xb03a, 0xc028, 0xd02e, 0xe024, 0xf022,
|
||||
0x8065, 0x9063, 0xa069, 0xb06f, 0xc07d, 0xd07b, 0xe071, 0xf077,
|
||||
0x0055, 0x1053, 0x2059, 0x305f, 0x404d, 0x504b, 0x6041, 0x7047,
|
||||
0x80cf, 0x90c9, 0xa0c3, 0xb0c5, 0xc0d7, 0xd0d1, 0xe0db, 0xf0dd,
|
||||
0x00ff, 0x10f9, 0x20f3, 0x30f5, 0x40e7, 0x50e1, 0x60eb, 0x70ed,
|
||||
0x00aa, 0x10ac, 0x20a6, 0x30a0, 0x40b2, 0x50b4, 0x60be, 0x70b8,
|
||||
0x809a, 0x909c, 0xa096, 0xb090, 0xc082, 0xd084, 0xe08e, 0xf088,
|
||||
0x819b, 0x919d, 0xa197, 0xb191, 0xc183, 0xd185, 0xe18f, 0xf189,
|
||||
0x01ab, 0x11ad, 0x21a7, 0x31a1, 0x41b3, 0x51b5, 0x61bf, 0x71b9,
|
||||
0x01fe, 0x11f8, 0x21f2, 0x31f4, 0x41e6, 0x51e0, 0x61ea, 0x71ec,
|
||||
0x81ce, 0x91c8, 0xa1c2, 0xb1c4, 0xc1d6, 0xd1d0, 0xe1da, 0xf1dc,
|
||||
0x0154, 0x1152, 0x2158, 0x315e, 0x414c, 0x514a, 0x6140, 0x7146,
|
||||
0x8164, 0x9162, 0xa168, 0xb16e, 0xc17c, 0xd17a, 0xe170, 0xf176,
|
||||
0x8131, 0x9137, 0xa13d, 0xb13b, 0xc129, 0xd12f, 0xe125, 0xf123,
|
||||
0x0101, 0x1107, 0x210d, 0x310b, 0x4119, 0x511f, 0x6115, 0x7113,
|
||||
0x8333, 0x9335, 0xa33f, 0xb339, 0xc32b, 0xd32d, 0xe327, 0xf321,
|
||||
0x0303, 0x1305, 0x230f, 0x3309, 0x431b, 0x531d, 0x6317, 0x7311,
|
||||
0x0356, 0x1350, 0x235a, 0x335c, 0x434e, 0x5348, 0x6342, 0x7344,
|
||||
0x8366, 0x9360, 0xa36a, 0xb36c, 0xc37e, 0xd378, 0xe372, 0xf374,
|
||||
0x03fc, 0x13fa, 0x23f0, 0x33f6, 0x43e4, 0x53e2, 0x63e8, 0x73ee,
|
||||
0x83cc, 0x93ca, 0xa3c0, 0xb3c6, 0xc3d4, 0xd3d2, 0xe3d8, 0xf3de,
|
||||
0x8399, 0x939f, 0xa395, 0xb393, 0xc381, 0xd387, 0xe38d, 0xf38b,
|
||||
0x03a9, 0x13af, 0x23a5, 0x33a3, 0x43b1, 0x53b7, 0x63bd, 0x73bb,
|
||||
0x02a8, 0x12ae, 0x22a4, 0x32a2, 0x42b0, 0x52b6, 0x62bc, 0x72ba,
|
||||
0x8298, 0x929e, 0xa294, 0xb292, 0xc280, 0xd286, 0xe28c, 0xf28a,
|
||||
0x82cd, 0x92cb, 0xa2c1, 0xb2c7, 0xc2d5, 0xd2d3, 0xe2d9, 0xf2df,
|
||||
0x02fd, 0x12fb, 0x22f1, 0x32f7, 0x42e5, 0x52e3, 0x62e9, 0x72ef,
|
||||
0x8267, 0x9261, 0xa26b, 0xb26d, 0xc27f, 0xd279, 0xe273, 0xf275,
|
||||
0x0257, 0x1251, 0x225b, 0x325d, 0x424f, 0x5249, 0x6243, 0x7245,
|
||||
0x0202, 0x1204, 0x220e, 0x3208, 0x421a, 0x521c, 0x6216, 0x7210,
|
||||
0x8232, 0x9234, 0xa23e, 0xb238, 0xc22a, 0xd22c, 0xe226, 0xf220 }
|
||||
};
|
||||
|
||||
#if 0
|
||||
void FLAC__crc16_init_table(void)
|
||||
{
|
||||
int i, j;
|
||||
FLAC__uint16 polynomial, crc;
|
||||
polynomial = 0x8005;
|
||||
|
||||
for(i = 0; i <= 0xFF; i++){
|
||||
crc = i << 8;
|
||||
|
||||
for(j = 0; j < 8; j++)
|
||||
crc = (crc << 1) ^ (crc & (1 << 15) ? polynomial : 0);
|
||||
|
||||
FLAC__crc16_table[0][i] = crc;
|
||||
}
|
||||
|
||||
for(i = 0; i <= 0xFF; i++)
|
||||
for(j = 1; j < 8; j++)
|
||||
FLAC__crc16_table[j][i] = FLAC__crc16_table[0][FLAC__crc16_table[j - 1][i] >> 8] ^ (FLAC__crc16_table[j - 1][i] << 8);
|
||||
}
|
||||
#endif
|
||||
|
||||
FLAC__uint8 FLAC__crc8(const FLAC__byte *data, uint32_t len)
|
||||
{
|
||||
FLAC__uint8 crc = 0;
|
||||
|
||||
while(len--)
|
||||
crc = FLAC__crc8_table[crc ^ *data++];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
FLAC__uint16 FLAC__crc16(const FLAC__byte *data, uint32_t len)
|
||||
{
|
||||
FLAC__uint16 crc = 0;
|
||||
|
||||
while(len >= 8){
|
||||
crc ^= data[0] << 8 | data[1];
|
||||
|
||||
crc = FLAC__crc16_table[7][crc >> 8] ^ FLAC__crc16_table[6][crc & 0xFF] ^
|
||||
FLAC__crc16_table[5][data[2] ] ^ FLAC__crc16_table[4][data[3] ] ^
|
||||
FLAC__crc16_table[3][data[4] ] ^ FLAC__crc16_table[2][data[5] ] ^
|
||||
FLAC__crc16_table[1][data[6] ] ^ FLAC__crc16_table[0][data[7] ];
|
||||
|
||||
data += 8;
|
||||
len -= 8;
|
||||
}
|
||||
|
||||
while(len--)
|
||||
crc = (crc<<8) ^ FLAC__crc16_table[0][(crc>>8) ^ *data++];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
FLAC__uint16 FLAC__crc16_update_words32(const FLAC__uint32 *words, uint32_t len, FLAC__uint16 crc)
|
||||
{
|
||||
while (len >= 2) {
|
||||
crc ^= words[0] >> 16;
|
||||
|
||||
crc = FLAC__crc16_table[7][crc >> 8 ] ^ FLAC__crc16_table[6][crc & 0xFF ] ^
|
||||
FLAC__crc16_table[5][(words[0] >> 8) & 0xFF] ^ FLAC__crc16_table[4][ words[0] & 0xFF] ^
|
||||
FLAC__crc16_table[3][ words[1] >> 24 ] ^ FLAC__crc16_table[2][(words[1] >> 16) & 0xFF] ^
|
||||
FLAC__crc16_table[1][(words[1] >> 8) & 0xFF] ^ FLAC__crc16_table[0][ words[1] & 0xFF];
|
||||
|
||||
words += 2;
|
||||
len -= 2;
|
||||
}
|
||||
|
||||
if (len) {
|
||||
crc ^= words[0] >> 16;
|
||||
|
||||
crc = FLAC__crc16_table[3][crc >> 8 ] ^ FLAC__crc16_table[2][crc & 0xFF ] ^
|
||||
FLAC__crc16_table[1][(words[0] >> 8) & 0xFF] ^ FLAC__crc16_table[0][words[0] & 0xFF];
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
FLAC__uint16 FLAC__crc16_update_words64(const FLAC__uint64 *words, uint32_t len, FLAC__uint16 crc)
|
||||
{
|
||||
while (len--) {
|
||||
crc ^= words[0] >> 48;
|
||||
|
||||
crc = FLAC__crc16_table[7][crc >> 8 ] ^ FLAC__crc16_table[6][crc & 0xFF ] ^
|
||||
FLAC__crc16_table[5][(words[0] >> 40) & 0xFF] ^ FLAC__crc16_table[4][(words[0] >> 32) & 0xFF] ^
|
||||
FLAC__crc16_table[3][(words[0] >> 24) & 0xFF] ^ FLAC__crc16_table[2][(words[0] >> 16) & 0xFF] ^
|
||||
FLAC__crc16_table[1][(words[0] >> 8) & 0xFF] ^ FLAC__crc16_table[0][ words[0] & 0xFF];
|
||||
|
||||
words++;
|
||||
}
|
||||
|
||||
return crc;
|
||||
}
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
{
|
||||
/* try and get br->consumed_words and br->consumed_bits into register;
|
||||
* must remember to flush them back to *br before calling other
|
||||
* bitreader functions that use them, and before returning */
|
||||
uint32_t cwords, words, lsbs, msbs, x, y, limit;
|
||||
uint32_t ucbits; /* keep track of the number of unconsumed bits in word */
|
||||
brword b;
|
||||
int *val, *end;
|
||||
|
||||
FLAC__ASSERT(0 != br);
|
||||
FLAC__ASSERT(0 != br->buffer);
|
||||
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
|
||||
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
|
||||
FLAC__ASSERT(parameter < 32);
|
||||
/* the above two asserts also guarantee that the binary part never straddles more than 2 words, so we don't have to loop to read it */
|
||||
|
||||
limit = UINT32_MAX >> parameter; /* Maximal msbs that can occur with residual bounded to int32_t */
|
||||
|
||||
val = vals;
|
||||
end = vals + nvals;
|
||||
|
||||
if(parameter == 0) {
|
||||
while(val < end) {
|
||||
/* read the unary MSBs and end bit */
|
||||
if(!FLAC__bitreader_read_unary_unsigned(br, &msbs))
|
||||
return false;
|
||||
/* Checking limit here would be overzealous: coding UINT32_MAX
|
||||
* with parameter == 0 would take 4GiB */
|
||||
*val++ = (int)(msbs >> 1) ^ -(int)(msbs & 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
cwords = br->consumed_words;
|
||||
words = br->words;
|
||||
|
||||
/* if we've not consumed up to a partial tail word... */
|
||||
if(cwords >= words) {
|
||||
x = 0;
|
||||
goto process_tail;
|
||||
}
|
||||
|
||||
ucbits = FLAC__BITS_PER_WORD - br->consumed_bits;
|
||||
b = br->buffer[cwords] << br->consumed_bits; /* keep unconsumed bits aligned to left */
|
||||
|
||||
while(val < end) {
|
||||
/* read the unary MSBs and end bit */
|
||||
x = y = COUNT_ZERO_MSBS2(b);
|
||||
if(x == FLAC__BITS_PER_WORD) {
|
||||
x = ucbits;
|
||||
do {
|
||||
/* didn't find stop bit yet, have to keep going... */
|
||||
cwords++;
|
||||
if (cwords >= words)
|
||||
goto incomplete_msbs;
|
||||
b = br->buffer[cwords];
|
||||
y = COUNT_ZERO_MSBS2(b);
|
||||
x += y;
|
||||
} while(y == FLAC__BITS_PER_WORD);
|
||||
}
|
||||
b <<= y;
|
||||
b <<= 1; /* account for stop bit */
|
||||
ucbits = (ucbits - x - 1) % FLAC__BITS_PER_WORD;
|
||||
msbs = x;
|
||||
|
||||
if(x > limit)
|
||||
return false;
|
||||
|
||||
/* read the binary LSBs */
|
||||
x = (FLAC__uint32)(b >> (FLAC__BITS_PER_WORD - parameter)); /* parameter < 32, so we can cast to 32-bit uint32_t */
|
||||
if(parameter <= ucbits) {
|
||||
ucbits -= parameter;
|
||||
b <<= parameter;
|
||||
} else {
|
||||
/* there are still bits left to read, they will all be in the next word */
|
||||
cwords++;
|
||||
if (cwords >= words)
|
||||
goto incomplete_lsbs;
|
||||
b = br->buffer[cwords];
|
||||
ucbits += FLAC__BITS_PER_WORD - parameter;
|
||||
x |= (FLAC__uint32)(b >> ucbits);
|
||||
b <<= FLAC__BITS_PER_WORD - ucbits;
|
||||
}
|
||||
lsbs = x;
|
||||
|
||||
/* compose the value */
|
||||
x = (msbs << parameter) | lsbs;
|
||||
*val++ = (int)(x >> 1) ^ -(int)(x & 1);
|
||||
|
||||
continue;
|
||||
|
||||
/* at this point we've eaten up all the whole words */
|
||||
process_tail:
|
||||
do {
|
||||
if(0) {
|
||||
incomplete_msbs:
|
||||
br->consumed_bits = 0;
|
||||
br->consumed_words = cwords;
|
||||
}
|
||||
|
||||
/* read the unary MSBs and end bit */
|
||||
if(!FLAC__bitreader_read_unary_unsigned(br, &msbs))
|
||||
return false;
|
||||
msbs += x;
|
||||
x = ucbits = 0;
|
||||
|
||||
if(0) {
|
||||
incomplete_lsbs:
|
||||
br->consumed_bits = 0;
|
||||
br->consumed_words = cwords;
|
||||
}
|
||||
|
||||
/* read the binary LSBs */
|
||||
if(!FLAC__bitreader_read_raw_uint32(br, &lsbs, parameter - ucbits))
|
||||
return false;
|
||||
lsbs = x | lsbs;
|
||||
|
||||
/* compose the value */
|
||||
x = (msbs << parameter) | lsbs;
|
||||
*val++ = (int)(x >> 1) ^ -(int)(x & 1);
|
||||
x = 0;
|
||||
|
||||
cwords = br->consumed_words;
|
||||
words = br->words;
|
||||
ucbits = FLAC__BITS_PER_WORD - br->consumed_bits;
|
||||
b = cwords < br->capacity ? br->buffer[cwords] << br->consumed_bits : 0;
|
||||
} while(cwords >= words && val < end);
|
||||
}
|
||||
|
||||
if(ucbits == 0 && cwords < words) {
|
||||
/* don't leave the head word with no unconsumed bits */
|
||||
cwords++;
|
||||
ucbits = FLAC__BITS_PER_WORD;
|
||||
}
|
||||
|
||||
br->consumed_bits = FLAC__BITS_PER_WORD - ucbits;
|
||||
br->consumed_words = cwords;
|
||||
|
||||
return true;
|
||||
}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
int i, j;
|
||||
(void) lag;
|
||||
FLAC__ASSERT(lag <= MAX_LAG);
|
||||
|
||||
for(i = 0; i < MAX_LAG; i++)
|
||||
autoc[i] = 0.0;
|
||||
|
||||
for(i = 0; i < MAX_LAG; i++)
|
||||
for(j = 0; j <= i; j++)
|
||||
autoc[j] += (double)data[i] * (double)data[i-j];
|
||||
|
||||
for(i = MAX_LAG; i < (int)data_len; i++)
|
||||
for(j = 0; j < MAX_LAG; j++)
|
||||
autoc[j] += (double)data[i] * (double)data[i-j];
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
int i;
|
||||
float64x2_t sum0 = vdupq_n_f64(0.0f);
|
||||
float64x2_t sum1 = vdupq_n_f64(0.0f);
|
||||
float64x2_t sum2 = vdupq_n_f64(0.0f);
|
||||
float64x2_t sum3 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d0 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d1 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d2 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d3 = vdupq_n_f64(0.0f);
|
||||
#if MAX_LAG > 8
|
||||
float64x2_t sum4 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d4 = vdupq_n_f64(0.0f);
|
||||
#endif
|
||||
#if MAX_LAG > 10
|
||||
float64x2_t sum5 = vdupq_n_f64(0.0f);
|
||||
float64x2_t sum6 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d5 = vdupq_n_f64(0.0f);
|
||||
float64x2_t d6 = vdupq_n_f64(0.0f);
|
||||
#endif
|
||||
float64x2_t d;
|
||||
|
||||
(void)lag;
|
||||
FLAC__ASSERT(lag <= MAX_LAG);
|
||||
|
||||
// Loop backwards through samples from data_len to 0
|
||||
for (i = data_len - 1; i >= 0; i--)
|
||||
{
|
||||
d = vdupq_n_f64(data[i]); // Create vector with 2 entries data[i]
|
||||
|
||||
// The next 6 lines of code right-shift the elements through the 7 vectors d0..d6.
|
||||
// The 7th line adds the newly loaded element to d0. This works like a stack, where
|
||||
// data[i] is pushed onto the stack every time and the 9th element falls off
|
||||
#if MAX_LAG > 10
|
||||
d6 = vextq_f64(d5,d6,1);
|
||||
d5 = vextq_f64(d4,d5,1);
|
||||
#endif
|
||||
#if MAX_LAG > 8
|
||||
d4 = vextq_f64(d3,d4,1);
|
||||
#endif
|
||||
d3 = vextq_f64(d2,d3,1);
|
||||
d2 = vextq_f64(d1,d2,1);
|
||||
d1 = vextq_f64(d0,d1,1);
|
||||
d0 = vextq_f64(d,d0,1);
|
||||
|
||||
// Fused multiply-add sum += d * d0..d6
|
||||
sum0 = vfmaq_f64(sum0, d, d0);
|
||||
sum1 = vfmaq_f64(sum1, d, d1);
|
||||
sum2 = vfmaq_f64(sum2, d, d2);
|
||||
sum3 = vfmaq_f64(sum3, d, d3);
|
||||
#if MAX_LAG > 8
|
||||
sum4 = vfmaq_f64(sum4, d, d4);
|
||||
#endif
|
||||
#if MAX_LAG > 10
|
||||
sum5 = vfmaq_f64(sum5, d, d5);
|
||||
sum6 = vfmaq_f64(sum6, d, d6);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Store sum0..sum6 in autoc[0..14]
|
||||
vst1q_f64(autoc, sum0);
|
||||
vst1q_f64(autoc + 2, sum1);
|
||||
vst1q_f64(autoc + 4, sum2);
|
||||
vst1q_f64(autoc + 6, sum3);
|
||||
#if MAX_LAG > 8
|
||||
vst1q_f64(autoc + 8, sum4);
|
||||
#endif
|
||||
#if MAX_LAG > 10
|
||||
vst1q_f64(autoc + 10, sum5);
|
||||
vst1q_f64(autoc + 12, sum6);
|
||||
#endif
|
||||
@@ -0,0 +1,667 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "../compat.h"
|
||||
#include "include/private/bitmath.h"
|
||||
#include "include/private/fixed.h"
|
||||
|
||||
#include "../assert.h"
|
||||
|
||||
#ifdef local_abs
|
||||
#undef local_abs
|
||||
#endif
|
||||
#define local_abs(x) ((uint32_t)((x)<0? -(x) : (x)))
|
||||
|
||||
#ifdef local_abs64
|
||||
#undef local_abs64
|
||||
#endif
|
||||
#define local_abs64(x) ((uint64_t)((x)<0? -(x) : (x)))
|
||||
|
||||
#ifdef FLAC__INTEGER_ONLY_LIBRARY
|
||||
/* rbps stands for residual bits per sample
|
||||
*
|
||||
* (ln(2) * err)
|
||||
* rbps = log (-----------)
|
||||
* 2 ( n )
|
||||
*/
|
||||
static FLAC__fixedpoint local__compute_rbps_integerized(FLAC__uint32 err, FLAC__uint32 n)
|
||||
{
|
||||
FLAC__uint32 rbps;
|
||||
uint32_t bits; /* the number of bits required to represent a number */
|
||||
int fracbits; /* the number of bits of rbps that comprise the fractional part */
|
||||
|
||||
FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint));
|
||||
FLAC__ASSERT(err > 0);
|
||||
FLAC__ASSERT(n > 0);
|
||||
|
||||
FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE);
|
||||
if(err <= n)
|
||||
return 0;
|
||||
/*
|
||||
* The above two things tell us 1) n fits in 16 bits; 2) err/n > 1.
|
||||
* These allow us later to know we won't lose too much precision in the
|
||||
* fixed-point division (err<<fracbits)/n.
|
||||
*/
|
||||
|
||||
fracbits = (8*sizeof(err)) - (FLAC__bitmath_ilog2(err)+1);
|
||||
|
||||
err <<= fracbits;
|
||||
err /= n;
|
||||
/* err now holds err/n with fracbits fractional bits */
|
||||
|
||||
/*
|
||||
* Whittle err down to 16 bits max. 16 significant bits is enough for
|
||||
* our purposes.
|
||||
*/
|
||||
FLAC__ASSERT(err > 0);
|
||||
bits = FLAC__bitmath_ilog2(err)+1;
|
||||
if(bits > 16) {
|
||||
err >>= (bits-16);
|
||||
fracbits -= (bits-16);
|
||||
}
|
||||
rbps = (FLAC__uint32)err;
|
||||
|
||||
/* Multiply by fixed-point version of ln(2), with 16 fractional bits */
|
||||
rbps *= FLAC__FP_LN2;
|
||||
fracbits += 16;
|
||||
FLAC__ASSERT(fracbits >= 0);
|
||||
|
||||
/* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */
|
||||
{
|
||||
const int f = fracbits & 3;
|
||||
if(f) {
|
||||
rbps >>= f;
|
||||
fracbits -= f;
|
||||
}
|
||||
}
|
||||
|
||||
rbps = FLAC__fixedpoint_log2(rbps, fracbits, (uint32_t)(-1));
|
||||
|
||||
if(rbps == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The return value must have 16 fractional bits. Since the whole part
|
||||
* of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits
|
||||
* must be >= -3, these assertion allows us to be able to shift rbps
|
||||
* left if necessary to get 16 fracbits without losing any bits of the
|
||||
* whole part of rbps.
|
||||
*
|
||||
* There is a slight chance due to accumulated error that the whole part
|
||||
* will require 6 bits, so we use 6 in the assertion. Really though as
|
||||
* long as it fits in 13 bits (32 - (16 - (-3))) we are fine.
|
||||
*/
|
||||
FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6);
|
||||
FLAC__ASSERT(fracbits >= -3);
|
||||
|
||||
/* now shift the decimal point into place */
|
||||
if(fracbits < 16)
|
||||
return rbps << (16-fracbits);
|
||||
else if(fracbits > 16)
|
||||
return rbps >> (fracbits-16);
|
||||
else
|
||||
return rbps;
|
||||
}
|
||||
|
||||
static FLAC__fixedpoint local__compute_rbps_wide_integerized(FLAC__uint64 err, FLAC__uint32 n)
|
||||
{
|
||||
FLAC__uint32 rbps;
|
||||
uint32_t bits; /* the number of bits required to represent a number */
|
||||
int fracbits; /* the number of bits of rbps that comprise the fractional part */
|
||||
|
||||
FLAC__ASSERT(sizeof(rbps) == sizeof(FLAC__fixedpoint));
|
||||
FLAC__ASSERT(err > 0);
|
||||
FLAC__ASSERT(n > 0);
|
||||
|
||||
FLAC__ASSERT(n <= FLAC__MAX_BLOCK_SIZE);
|
||||
if(err <= n)
|
||||
return 0;
|
||||
/*
|
||||
* The above two things tell us 1) n fits in 16 bits; 2) err/n > 1.
|
||||
* These allow us later to know we won't lose too much precision in the
|
||||
* fixed-point division (err<<fracbits)/n.
|
||||
*/
|
||||
|
||||
fracbits = (8*sizeof(err)) - (FLAC__bitmath_ilog2_wide(err)+1);
|
||||
|
||||
err <<= fracbits;
|
||||
err /= n;
|
||||
/* err now holds err/n with fracbits fractional bits */
|
||||
|
||||
/*
|
||||
* Whittle err down to 16 bits max. 16 significant bits is enough for
|
||||
* our purposes.
|
||||
*/
|
||||
FLAC__ASSERT(err > 0);
|
||||
bits = FLAC__bitmath_ilog2_wide(err)+1;
|
||||
if(bits > 16) {
|
||||
err >>= (bits-16);
|
||||
fracbits -= (bits-16);
|
||||
}
|
||||
rbps = (FLAC__uint32)err;
|
||||
|
||||
/* Multiply by fixed-point version of ln(2), with 16 fractional bits */
|
||||
rbps *= FLAC__FP_LN2;
|
||||
fracbits += 16;
|
||||
FLAC__ASSERT(fracbits >= 0);
|
||||
|
||||
/* FLAC__fixedpoint_log2 requires fracbits%4 to be 0 */
|
||||
{
|
||||
const int f = fracbits & 3;
|
||||
if(f) {
|
||||
rbps >>= f;
|
||||
fracbits -= f;
|
||||
}
|
||||
}
|
||||
|
||||
rbps = FLAC__fixedpoint_log2(rbps, fracbits, (uint32_t)(-1));
|
||||
|
||||
if(rbps == 0)
|
||||
return 0;
|
||||
|
||||
/*
|
||||
* The return value must have 16 fractional bits. Since the whole part
|
||||
* of the base-2 log of a 32 bit number must fit in 5 bits, and fracbits
|
||||
* must be >= -3, these assertion allows us to be able to shift rbps
|
||||
* left if necessary to get 16 fracbits without losing any bits of the
|
||||
* whole part of rbps.
|
||||
*
|
||||
* There is a slight chance due to accumulated error that the whole part
|
||||
* will require 6 bits, so we use 6 in the assertion. Really though as
|
||||
* long as it fits in 13 bits (32 - (16 - (-3))) we are fine.
|
||||
*/
|
||||
FLAC__ASSERT((int)FLAC__bitmath_ilog2(rbps)+1 <= fracbits + 6);
|
||||
FLAC__ASSERT(fracbits >= -3);
|
||||
|
||||
/* now shift the decimal point into place */
|
||||
if(fracbits < 16)
|
||||
return rbps << (16-fracbits);
|
||||
else if(fracbits > 16)
|
||||
return rbps >> (fracbits-16);
|
||||
else
|
||||
return rbps;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#else
|
||||
uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#endif
|
||||
{
|
||||
FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
|
||||
uint32_t order;
|
||||
#if 0
|
||||
/* This code has been around a long time, and was written when compilers weren't able
|
||||
* to vectorize code. These days, compilers are better in optimizing the next block
|
||||
* which is also much more readable
|
||||
*/
|
||||
FLAC__int32 last_error_0 = data[-1];
|
||||
FLAC__int32 last_error_1 = data[-1] - data[-2];
|
||||
FLAC__int32 last_error_2 = last_error_1 - (data[-2] - data[-3]);
|
||||
FLAC__int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]);
|
||||
FLAC__int32 error, save;
|
||||
uint32_t i;
|
||||
/* total_error_* are 64-bits to avoid overflow when encoding
|
||||
* erratic signals when the bits-per-sample and blocksize are
|
||||
* large.
|
||||
*/
|
||||
for(i = 0; i < data_len; i++) {
|
||||
error = data[i] ; total_error_0 += local_abs(error); save = error;
|
||||
error -= last_error_0; total_error_1 += local_abs(error); last_error_0 = save; save = error;
|
||||
error -= last_error_1; total_error_2 += local_abs(error); last_error_1 = save; save = error;
|
||||
error -= last_error_2; total_error_3 += local_abs(error); last_error_2 = save; save = error;
|
||||
error -= last_error_3; total_error_4 += local_abs(error); last_error_3 = save;
|
||||
}
|
||||
#else
|
||||
int i;
|
||||
for(i = 0; i < (int)data_len; i++) {
|
||||
total_error_0 += local_abs(data[i]);
|
||||
total_error_1 += local_abs(data[i] - data[i-1]);
|
||||
total_error_2 += local_abs(data[i] - 2 * data[i-1] + data[i-2]);
|
||||
total_error_3 += local_abs(data[i] - 3 * data[i-1] + 3 * data[i-2] - data[i-3]);
|
||||
total_error_4 += local_abs(data[i] - 4 * data[i-1] + 6 * data[i-2] - 4 * data[i-3] + data[i-4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* prefer lower order */
|
||||
if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
|
||||
order = 0;
|
||||
else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4))
|
||||
order = 1;
|
||||
else if(total_error_2 <= flac_min(total_error_3, total_error_4))
|
||||
order = 2;
|
||||
else if(total_error_3 <= total_error_4)
|
||||
order = 3;
|
||||
else
|
||||
order = 4;
|
||||
|
||||
/* Estimate the expected number of bits per residual signal sample. */
|
||||
/* 'total_error*' is linearly related to the variance of the residual */
|
||||
/* signal, so we use it directly to compute E(|x|) */
|
||||
FLAC__ASSERT(data_len > 0 || total_error_0 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_1 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_2 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_3 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_4 == 0);
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
residual_bits_per_sample[0] = (float)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[1] = (float)((total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[2] = (float)((total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[3] = (float)((total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[4] = (float)((total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0);
|
||||
#else
|
||||
residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_integerized(total_error_0, data_len) : 0;
|
||||
residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_integerized(total_error_1, data_len) : 0;
|
||||
residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_integerized(total_error_2, data_len) : 0;
|
||||
residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_integerized(total_error_3, data_len) : 0;
|
||||
residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_integerized(total_error_4, data_len) : 0;
|
||||
#endif
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#else
|
||||
uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#endif
|
||||
{
|
||||
FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
|
||||
uint32_t order;
|
||||
int i;
|
||||
|
||||
for(i = 0; i < (int)data_len; i++) {
|
||||
total_error_0 += local_abs(data[i]);
|
||||
total_error_1 += local_abs(data[i] - data[i-1]);
|
||||
total_error_2 += local_abs(data[i] - 2 * data[i-1] + data[i-2]);
|
||||
total_error_3 += local_abs(data[i] - 3 * data[i-1] + 3 * data[i-2] - data[i-3]);
|
||||
total_error_4 += local_abs(data[i] - 4 * data[i-1] + 6 * data[i-2] - 4 * data[i-3] + data[i-4]);
|
||||
}
|
||||
|
||||
/* prefer lower order */
|
||||
if(total_error_0 <= flac_min(flac_min(flac_min(total_error_1, total_error_2), total_error_3), total_error_4))
|
||||
order = 0;
|
||||
else if(total_error_1 <= flac_min(flac_min(total_error_2, total_error_3), total_error_4))
|
||||
order = 1;
|
||||
else if(total_error_2 <= flac_min(total_error_3, total_error_4))
|
||||
order = 2;
|
||||
else if(total_error_3 <= total_error_4)
|
||||
order = 3;
|
||||
else
|
||||
order = 4;
|
||||
|
||||
/* Estimate the expected number of bits per residual signal sample. */
|
||||
/* 'total_error*' is linearly related to the variance of the residual */
|
||||
/* signal, so we use it directly to compute E(|x|) */
|
||||
FLAC__ASSERT(data_len > 0 || total_error_0 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_1 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_2 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_3 == 0);
|
||||
FLAC__ASSERT(data_len > 0 || total_error_4 == 0);
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
residual_bits_per_sample[0] = (float)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[1] = (float)((total_error_1 > 0) ? log(M_LN2 * (double)total_error_1 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[2] = (float)((total_error_2 > 0) ? log(M_LN2 * (double)total_error_2 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[3] = (float)((total_error_3 > 0) ? log(M_LN2 * (double)total_error_3 / (double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[4] = (float)((total_error_4 > 0) ? log(M_LN2 * (double)total_error_4 / (double)data_len) / M_LN2 : 0.0);
|
||||
#else
|
||||
residual_bits_per_sample[0] = (total_error_0 > 0) ? local__compute_rbps_wide_integerized(total_error_0, data_len) : 0;
|
||||
residual_bits_per_sample[1] = (total_error_1 > 0) ? local__compute_rbps_wide_integerized(total_error_1, data_len) : 0;
|
||||
residual_bits_per_sample[2] = (total_error_2 > 0) ? local__compute_rbps_wide_integerized(total_error_2, data_len) : 0;
|
||||
residual_bits_per_sample[3] = (total_error_3 > 0) ? local__compute_rbps_wide_integerized(total_error_3, data_len) : 0;
|
||||
residual_bits_per_sample[4] = (total_error_4 > 0) ? local__compute_rbps_wide_integerized(total_error_4, data_len) : 0;
|
||||
#endif
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
#define CHECK_ORDER_IS_VALID(macro_order) \
|
||||
if(order_##macro_order##_is_valid && total_error_##macro_order < smallest_error) { \
|
||||
order = macro_order; \
|
||||
smallest_error = total_error_##macro_order ; \
|
||||
residual_bits_per_sample[ macro_order ] = (float)((total_error_0 > 0) ? log(M_LN2 * (double)total_error_0 / (double)data_len) / M_LN2 : 0.0); \
|
||||
} \
|
||||
else \
|
||||
residual_bits_per_sample[ macro_order ] = 34.0f;
|
||||
#else
|
||||
#define CHECK_ORDER_IS_VALID(macro_order) \
|
||||
if(order_##macro_order##_is_valid && total_error_##macro_order < smallest_error) { \
|
||||
order = macro_order; \
|
||||
smallest_error = total_error_##macro_order ; \
|
||||
residual_bits_per_sample[ macro_order ] = (total_error_##macro_order > 0) ? local__compute_rbps_wide_integerized(total_error_##macro_order, data_len) : 0; \
|
||||
} \
|
||||
else \
|
||||
residual_bits_per_sample[ macro_order ] = 34 * FLAC__FP_ONE;
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#else
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#endif
|
||||
{
|
||||
FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0, smallest_error = UINT64_MAX;
|
||||
FLAC__uint64 error_0, error_1, error_2, error_3, error_4;
|
||||
FLAC__bool order_0_is_valid = true, order_1_is_valid = true, order_2_is_valid = true, order_3_is_valid = true, order_4_is_valid = true;
|
||||
uint32_t order = 0;
|
||||
int i;
|
||||
|
||||
for(i = -4; i < (int)data_len; i++) {
|
||||
error_0 = local_abs64((FLAC__int64)data[i]);
|
||||
error_1 = (i > -4) ? local_abs64((FLAC__int64)data[i] - data[i-1]) : 0 ;
|
||||
error_2 = (i > -3) ? local_abs64((FLAC__int64)data[i] - 2 * (FLAC__int64)data[i-1] + data[i-2]) : 0;
|
||||
error_3 = (i > -2) ? local_abs64((FLAC__int64)data[i] - 3 * (FLAC__int64)data[i-1] + 3 * (FLAC__int64)data[i-2] - data[i-3]) : 0;
|
||||
error_4 = (i > -1) ? local_abs64((FLAC__int64)data[i] - 4 * (FLAC__int64)data[i-1] + 6 * (FLAC__int64)data[i-2] - 4 * (FLAC__int64)data[i-3] + data[i-4]) : 0;
|
||||
|
||||
total_error_0 += error_0;
|
||||
total_error_1 += error_1;
|
||||
total_error_2 += error_2;
|
||||
total_error_3 += error_3;
|
||||
total_error_4 += error_4;
|
||||
|
||||
/* residual must not be INT32_MIN because abs(INT32_MIN) is undefined */
|
||||
if(error_0 > INT32_MAX)
|
||||
order_0_is_valid = false;
|
||||
if(error_1 > INT32_MAX)
|
||||
order_1_is_valid = false;
|
||||
if(error_2 > INT32_MAX)
|
||||
order_2_is_valid = false;
|
||||
if(error_3 > INT32_MAX)
|
||||
order_3_is_valid = false;
|
||||
if(error_4 > INT32_MAX)
|
||||
order_4_is_valid = false;
|
||||
}
|
||||
|
||||
CHECK_ORDER_IS_VALID(0);
|
||||
CHECK_ORDER_IS_VALID(1);
|
||||
CHECK_ORDER_IS_VALID(2);
|
||||
CHECK_ORDER_IS_VALID(3);
|
||||
CHECK_ORDER_IS_VALID(4);
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#else
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#endif
|
||||
{
|
||||
FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0, smallest_error = UINT64_MAX;
|
||||
FLAC__uint64 error_0, error_1, error_2, error_3, error_4;
|
||||
FLAC__bool order_0_is_valid = true, order_1_is_valid = true, order_2_is_valid = true, order_3_is_valid = true, order_4_is_valid = true;
|
||||
uint32_t order = 0;
|
||||
int i;
|
||||
|
||||
for(i = -4; i < (int)data_len; i++) {
|
||||
error_0 = local_abs64(data[i]);
|
||||
error_1 = (i > -4) ? local_abs64(data[i] - data[i-1]) : 0 ;
|
||||
error_2 = (i > -3) ? local_abs64(data[i] - 2 * data[i-1] + data[i-2]) : 0;
|
||||
error_3 = (i > -2) ? local_abs64(data[i] - 3 * data[i-1] + 3 * data[i-2] - data[i-3]) : 0;
|
||||
error_4 = (i > -1) ? local_abs64(data[i] - 4 * data[i-1] + 6 * data[i-2] - 4 * data[i-3] + data[i-4]) : 0;
|
||||
|
||||
total_error_0 += error_0;
|
||||
total_error_1 += error_1;
|
||||
total_error_2 += error_2;
|
||||
total_error_3 += error_3;
|
||||
total_error_4 += error_4;
|
||||
|
||||
/* residual must not be INT32_MIN because abs(INT32_MIN) is undefined */
|
||||
if(error_0 > INT32_MAX)
|
||||
order_0_is_valid = false;
|
||||
if(error_1 > INT32_MAX)
|
||||
order_1_is_valid = false;
|
||||
if(error_2 > INT32_MAX)
|
||||
order_2_is_valid = false;
|
||||
if(error_3 > INT32_MAX)
|
||||
order_3_is_valid = false;
|
||||
if(error_4 > INT32_MAX)
|
||||
order_4_is_valid = false;
|
||||
}
|
||||
|
||||
CHECK_ORDER_IS_VALID(0);
|
||||
CHECK_ORDER_IS_VALID(1);
|
||||
CHECK_ORDER_IS_VALID(2);
|
||||
CHECK_ORDER_IS_VALID(3);
|
||||
CHECK_ORDER_IS_VALID(4);
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
void FLAC__fixed_compute_residual(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[])
|
||||
{
|
||||
const int idata_len = (int)data_len;
|
||||
int i;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
|
||||
memcpy(residual, data, sizeof(residual[0])*data_len);
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - data[i-1];
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - 2*data[i-1] + data[i-2];
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3];
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4];
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__fixed_compute_residual_wide(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[])
|
||||
{
|
||||
const int idata_len = (int)data_len;
|
||||
int i;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
|
||||
memcpy(residual, data, sizeof(residual[0])*data_len);
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = (FLAC__int64)data[i] - data[i-1];
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = (FLAC__int64)data[i] - 2*(FLAC__int64)data[i-1] + data[i-2];
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = (FLAC__int64)data[i] - 3*(FLAC__int64)data[i-1] + 3*(FLAC__int64)data[i-2] - data[i-3];
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = (FLAC__int64)data[i] - 4*(FLAC__int64)data[i-1] + 6*(FLAC__int64)data[i-2] - 4*(FLAC__int64)data[i-3] + data[i-4];
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__fixed_compute_residual_wide_33bit(const FLAC__int64 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[])
|
||||
{
|
||||
const int idata_len = (int)data_len;
|
||||
int i;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i];
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - data[i-1];
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - 2*data[i-1] + data[i-2];
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3];
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4];
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(FUZZING_BUILD_MODE_FLAC_SANITIZE_SIGNED_INTEGER_OVERFLOW)
|
||||
/* The attribute below is to silence the undefined sanitizer of oss-fuzz.
|
||||
* Because fuzzing feeds bogus predictors and residual samples to the
|
||||
* decoder, having overflows in this section is unavoidable. Also,
|
||||
* because the calculated values are audio path only, there is no
|
||||
* potential for security problems */
|
||||
__attribute__((no_sanitize("signed-integer-overflow")))
|
||||
#endif
|
||||
void FLAC__fixed_restore_signal(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[])
|
||||
{
|
||||
int i, idata_len = (int)data_len;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
|
||||
memcpy(data, residual, sizeof(residual[0])*data_len);
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = residual[i] + data[i-1];
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = residual[i] + 2*data[i-1] - data[i-2];
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = residual[i] + 3*data[i-1] - 3*data[i-2] + data[i-3];
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4];
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__fixed_restore_signal_wide(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[])
|
||||
{
|
||||
int i, idata_len = (int)data_len;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
FLAC__ASSERT(sizeof(residual[0]) == sizeof(data[0]));
|
||||
memcpy(data, residual, sizeof(residual[0])*data_len);
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + (FLAC__int64)data[i-1];
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + 2*(FLAC__int64)data[i-1] - (FLAC__int64)data[i-2];
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + 3*(FLAC__int64)data[i-1] - 3*(FLAC__int64)data[i-2] + (FLAC__int64)data[i-3];
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + 4*(FLAC__int64)data[i-1] - 6*(FLAC__int64)data[i-2] + 4*(FLAC__int64)data[i-3] - (FLAC__int64)data[i-4];
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION) && !defined(FUZZING_BUILD_MODE_FLAC_SANITIZE_SIGNED_INTEGER_OVERFLOW)
|
||||
/* The attribute below is to silence the undefined sanitizer of oss-fuzz.
|
||||
* Because fuzzing feeds bogus predictors and residual samples to the
|
||||
* decoder, having overflows in this section is unavoidable. Also,
|
||||
* because the calculated values are audio path only, there is no
|
||||
* potential for security problems */
|
||||
__attribute__((no_sanitize("signed-integer-overflow")))
|
||||
#endif
|
||||
void FLAC__fixed_restore_signal_wide_33bit(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int64 data[])
|
||||
{
|
||||
int i, idata_len = (int)data_len;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = residual[i];
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + data[i-1];
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + 2*data[i-1] - data[i-2];
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + 3*data[i-1] - 3*data[i-2] + data[i-3];
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
data[i] = (FLAC__int64)residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4];
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "../assert.h"
|
||||
#include "../compat.h"
|
||||
#include "include/private/float.h"
|
||||
|
||||
#ifdef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
const FLAC__fixedpoint FLAC__FP_ZERO = 0;
|
||||
const FLAC__fixedpoint FLAC__FP_ONE_HALF = 0x00008000;
|
||||
const FLAC__fixedpoint FLAC__FP_ONE = 0x00010000;
|
||||
const FLAC__fixedpoint FLAC__FP_LN2 = 45426;
|
||||
const FLAC__fixedpoint FLAC__FP_E = 178145;
|
||||
|
||||
/* Lookup tables for Knuth's logarithm algorithm */
|
||||
#define LOG2_LOOKUP_PRECISION 16
|
||||
static const FLAC__uint32 log2_lookup[][LOG2_LOOKUP_PRECISION] = {
|
||||
{
|
||||
/*
|
||||
* 0 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x00000001,
|
||||
/* lg(4/3) = */ 0x00000000,
|
||||
/* lg(8/7) = */ 0x00000000,
|
||||
/* lg(16/15) = */ 0x00000000,
|
||||
/* lg(32/31) = */ 0x00000000,
|
||||
/* lg(64/63) = */ 0x00000000,
|
||||
/* lg(128/127) = */ 0x00000000,
|
||||
/* lg(256/255) = */ 0x00000000,
|
||||
/* lg(512/511) = */ 0x00000000,
|
||||
/* lg(1024/1023) = */ 0x00000000,
|
||||
/* lg(2048/2047) = */ 0x00000000,
|
||||
/* lg(4096/4095) = */ 0x00000000,
|
||||
/* lg(8192/8191) = */ 0x00000000,
|
||||
/* lg(16384/16383) = */ 0x00000000,
|
||||
/* lg(32768/32767) = */ 0x00000000
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 4 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x00000010,
|
||||
/* lg(4/3) = */ 0x00000007,
|
||||
/* lg(8/7) = */ 0x00000003,
|
||||
/* lg(16/15) = */ 0x00000001,
|
||||
/* lg(32/31) = */ 0x00000001,
|
||||
/* lg(64/63) = */ 0x00000000,
|
||||
/* lg(128/127) = */ 0x00000000,
|
||||
/* lg(256/255) = */ 0x00000000,
|
||||
/* lg(512/511) = */ 0x00000000,
|
||||
/* lg(1024/1023) = */ 0x00000000,
|
||||
/* lg(2048/2047) = */ 0x00000000,
|
||||
/* lg(4096/4095) = */ 0x00000000,
|
||||
/* lg(8192/8191) = */ 0x00000000,
|
||||
/* lg(16384/16383) = */ 0x00000000,
|
||||
/* lg(32768/32767) = */ 0x00000000
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 8 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x00000100,
|
||||
/* lg(4/3) = */ 0x0000006a,
|
||||
/* lg(8/7) = */ 0x00000031,
|
||||
/* lg(16/15) = */ 0x00000018,
|
||||
/* lg(32/31) = */ 0x0000000c,
|
||||
/* lg(64/63) = */ 0x00000006,
|
||||
/* lg(128/127) = */ 0x00000003,
|
||||
/* lg(256/255) = */ 0x00000001,
|
||||
/* lg(512/511) = */ 0x00000001,
|
||||
/* lg(1024/1023) = */ 0x00000000,
|
||||
/* lg(2048/2047) = */ 0x00000000,
|
||||
/* lg(4096/4095) = */ 0x00000000,
|
||||
/* lg(8192/8191) = */ 0x00000000,
|
||||
/* lg(16384/16383) = */ 0x00000000,
|
||||
/* lg(32768/32767) = */ 0x00000000
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 12 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x00001000,
|
||||
/* lg(4/3) = */ 0x000006a4,
|
||||
/* lg(8/7) = */ 0x00000315,
|
||||
/* lg(16/15) = */ 0x0000017d,
|
||||
/* lg(32/31) = */ 0x000000bc,
|
||||
/* lg(64/63) = */ 0x0000005d,
|
||||
/* lg(128/127) = */ 0x0000002e,
|
||||
/* lg(256/255) = */ 0x00000017,
|
||||
/* lg(512/511) = */ 0x0000000c,
|
||||
/* lg(1024/1023) = */ 0x00000006,
|
||||
/* lg(2048/2047) = */ 0x00000003,
|
||||
/* lg(4096/4095) = */ 0x00000001,
|
||||
/* lg(8192/8191) = */ 0x00000001,
|
||||
/* lg(16384/16383) = */ 0x00000000,
|
||||
/* lg(32768/32767) = */ 0x00000000
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 16 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x00010000,
|
||||
/* lg(4/3) = */ 0x00006a40,
|
||||
/* lg(8/7) = */ 0x00003151,
|
||||
/* lg(16/15) = */ 0x000017d6,
|
||||
/* lg(32/31) = */ 0x00000bba,
|
||||
/* lg(64/63) = */ 0x000005d1,
|
||||
/* lg(128/127) = */ 0x000002e6,
|
||||
/* lg(256/255) = */ 0x00000172,
|
||||
/* lg(512/511) = */ 0x000000b9,
|
||||
/* lg(1024/1023) = */ 0x0000005c,
|
||||
/* lg(2048/2047) = */ 0x0000002e,
|
||||
/* lg(4096/4095) = */ 0x00000017,
|
||||
/* lg(8192/8191) = */ 0x0000000c,
|
||||
/* lg(16384/16383) = */ 0x00000006,
|
||||
/* lg(32768/32767) = */ 0x00000003
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 20 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x00100000,
|
||||
/* lg(4/3) = */ 0x0006a3fe,
|
||||
/* lg(8/7) = */ 0x00031513,
|
||||
/* lg(16/15) = */ 0x00017d60,
|
||||
/* lg(32/31) = */ 0x0000bb9d,
|
||||
/* lg(64/63) = */ 0x00005d10,
|
||||
/* lg(128/127) = */ 0x00002e59,
|
||||
/* lg(256/255) = */ 0x00001721,
|
||||
/* lg(512/511) = */ 0x00000b8e,
|
||||
/* lg(1024/1023) = */ 0x000005c6,
|
||||
/* lg(2048/2047) = */ 0x000002e3,
|
||||
/* lg(4096/4095) = */ 0x00000171,
|
||||
/* lg(8192/8191) = */ 0x000000b9,
|
||||
/* lg(16384/16383) = */ 0x0000005c,
|
||||
/* lg(32768/32767) = */ 0x0000002e
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 24 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x01000000,
|
||||
/* lg(4/3) = */ 0x006a3fe6,
|
||||
/* lg(8/7) = */ 0x00315130,
|
||||
/* lg(16/15) = */ 0x0017d605,
|
||||
/* lg(32/31) = */ 0x000bb9ca,
|
||||
/* lg(64/63) = */ 0x0005d0fc,
|
||||
/* lg(128/127) = */ 0x0002e58f,
|
||||
/* lg(256/255) = */ 0x0001720e,
|
||||
/* lg(512/511) = */ 0x0000b8d8,
|
||||
/* lg(1024/1023) = */ 0x00005c61,
|
||||
/* lg(2048/2047) = */ 0x00002e2d,
|
||||
/* lg(4096/4095) = */ 0x00001716,
|
||||
/* lg(8192/8191) = */ 0x00000b8b,
|
||||
/* lg(16384/16383) = */ 0x000005c5,
|
||||
/* lg(32768/32767) = */ 0x000002e3
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 28 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ 0x10000000,
|
||||
/* lg(4/3) = */ 0x06a3fe5c,
|
||||
/* lg(8/7) = */ 0x03151301,
|
||||
/* lg(16/15) = */ 0x017d6049,
|
||||
/* lg(32/31) = */ 0x00bb9ca6,
|
||||
/* lg(64/63) = */ 0x005d0fba,
|
||||
/* lg(128/127) = */ 0x002e58f7,
|
||||
/* lg(256/255) = */ 0x001720da,
|
||||
/* lg(512/511) = */ 0x000b8d87,
|
||||
/* lg(1024/1023) = */ 0x0005c60b,
|
||||
/* lg(2048/2047) = */ 0x0002e2d7,
|
||||
/* lg(4096/4095) = */ 0x00017160,
|
||||
/* lg(8192/8191) = */ 0x0000b8ad,
|
||||
/* lg(16384/16383) = */ 0x00005c56,
|
||||
/* lg(32768/32767) = */ 0x00002e2b
|
||||
}
|
||||
};
|
||||
|
||||
#if 0
|
||||
static const FLAC__uint64 log2_lookup_wide[] = {
|
||||
{
|
||||
/*
|
||||
* 32 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ FLAC__U64L(0x100000000),
|
||||
/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c6),
|
||||
/* lg(8/7) = */ FLAC__U64L(0x31513015),
|
||||
/* lg(16/15) = */ FLAC__U64L(0x17d60497),
|
||||
/* lg(32/31) = */ FLAC__U64L(0x0bb9ca65),
|
||||
/* lg(64/63) = */ FLAC__U64L(0x05d0fba2),
|
||||
/* lg(128/127) = */ FLAC__U64L(0x02e58f74),
|
||||
/* lg(256/255) = */ FLAC__U64L(0x01720d9c),
|
||||
/* lg(512/511) = */ FLAC__U64L(0x00b8d875),
|
||||
/* lg(1024/1023) = */ FLAC__U64L(0x005c60aa),
|
||||
/* lg(2048/2047) = */ FLAC__U64L(0x002e2d72),
|
||||
/* lg(4096/4095) = */ FLAC__U64L(0x00171600),
|
||||
/* lg(8192/8191) = */ FLAC__U64L(0x000b8ad2),
|
||||
/* lg(16384/16383) = */ FLAC__U64L(0x0005c55d),
|
||||
/* lg(32768/32767) = */ FLAC__U64L(0x0002e2ac)
|
||||
},
|
||||
{
|
||||
/*
|
||||
* 48 fraction bits
|
||||
*/
|
||||
/* undefined */ 0x00000000,
|
||||
/* lg(2/1) = */ FLAC__U64L(0x1000000000000),
|
||||
/* lg(4/3) = */ FLAC__U64L(0x6a3fe5c60429),
|
||||
/* lg(8/7) = */ FLAC__U64L(0x315130157f7a),
|
||||
/* lg(16/15) = */ FLAC__U64L(0x17d60496cfbb),
|
||||
/* lg(32/31) = */ FLAC__U64L(0xbb9ca64ecac),
|
||||
/* lg(64/63) = */ FLAC__U64L(0x5d0fba187cd),
|
||||
/* lg(128/127) = */ FLAC__U64L(0x2e58f7441ee),
|
||||
/* lg(256/255) = */ FLAC__U64L(0x1720d9c06a8),
|
||||
/* lg(512/511) = */ FLAC__U64L(0xb8d8752173),
|
||||
/* lg(1024/1023) = */ FLAC__U64L(0x5c60aa252e),
|
||||
/* lg(2048/2047) = */ FLAC__U64L(0x2e2d71b0d8),
|
||||
/* lg(4096/4095) = */ FLAC__U64L(0x1716001719),
|
||||
/* lg(8192/8191) = */ FLAC__U64L(0xb8ad1de1b),
|
||||
/* lg(16384/16383) = */ FLAC__U64L(0x5c55d640d),
|
||||
/* lg(32768/32767) = */ FLAC__U64L(0x2e2abcf52)
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, uint32_t fracbits, uint32_t precision)
|
||||
{
|
||||
const FLAC__uint32 ONE = (1u << fracbits);
|
||||
const FLAC__uint32 *table = log2_lookup[fracbits >> 2];
|
||||
|
||||
FLAC__ASSERT(fracbits < 32);
|
||||
FLAC__ASSERT((fracbits & 0x3) == 0);
|
||||
|
||||
if(x < ONE)
|
||||
return 0;
|
||||
|
||||
if(precision > LOG2_LOOKUP_PRECISION)
|
||||
precision = LOG2_LOOKUP_PRECISION;
|
||||
|
||||
/* Knuth's algorithm for computing logarithms, optimized for base-2 with lookup tables */
|
||||
{
|
||||
FLAC__uint32 y = 0;
|
||||
FLAC__uint32 z = x >> 1, k = 1;
|
||||
while (x > ONE && k < precision) {
|
||||
if (x - z >= ONE) {
|
||||
x -= z;
|
||||
z = x >> k;
|
||||
y += table[k];
|
||||
}
|
||||
else {
|
||||
z >>= 1;
|
||||
k++;
|
||||
}
|
||||
}
|
||||
return y;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
@@ -0,0 +1,608 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for qsort() */
|
||||
#include <string.h> /* for memset() */
|
||||
#include "../assert.h"
|
||||
#include "../format.h"
|
||||
#include "../alloc.h"
|
||||
#include "../compat.h"
|
||||
#include "include/private/format.h"
|
||||
|
||||
|
||||
#if (defined GIT_COMMIT_HASH && defined GIT_COMMIT_DATE)
|
||||
# ifdef GIT_COMMIT_TAG
|
||||
FLAC_API const char *FLAC__VERSION_STRING = GIT_COMMIT_TAG;
|
||||
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " GIT_COMMIT_TAG " " GIT_COMMIT_DATE;
|
||||
# else
|
||||
FLAC_API const char *FLAC__VERSION_STRING = "git-" GIT_COMMIT_HASH " " GIT_COMMIT_DATE;
|
||||
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC git-" GIT_COMMIT_HASH " " GIT_COMMIT_DATE;
|
||||
# endif
|
||||
#else
|
||||
/* PACKAGE_VERSION should come from configure */
|
||||
FLAC_API const char *FLAC__VERSION_STRING = PACKAGE_VERSION;
|
||||
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " PACKAGE_VERSION " 20230623";
|
||||
#endif
|
||||
|
||||
FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
|
||||
FLAC_API const uint32_t FLAC__STREAM_SYNC = 0x664C6143;
|
||||
FLAC_API const uint32_t FLAC__STREAM_SYNC_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN = 16; /* bits */
|
||||
|
||||
FLAC_API const FLAC__uint64 FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER = FLAC__U64L(0xffffffffffffffff);
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
|
||||
FLAC_API const uint32_t FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_SYNC = 0x3ffe;
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
|
||||
FLAC_API const uint32_t FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
|
||||
FLAC_API const uint32_t FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER = 31; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN)-1 */
|
||||
|
||||
FLAC_API const char * const FLAC__EntropyCodingMethodTypeString[] = {
|
||||
"PARTITIONED_RICE",
|
||||
"PARTITIONED_RICE2"
|
||||
};
|
||||
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
|
||||
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
|
||||
FLAC_API const uint32_t FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK = 0x40;
|
||||
|
||||
FLAC_API const char * const FLAC__SubframeTypeString[] = {
|
||||
"CONSTANT",
|
||||
"VERBATIM",
|
||||
"FIXED",
|
||||
"LPC"
|
||||
};
|
||||
|
||||
FLAC_API const char * const FLAC__ChannelAssignmentString[] = {
|
||||
"INDEPENDENT",
|
||||
"LEFT_SIDE",
|
||||
"RIGHT_SIDE",
|
||||
"MID_SIDE"
|
||||
};
|
||||
|
||||
FLAC_API const char * const FLAC__FrameNumberTypeString[] = {
|
||||
"FRAME_NUMBER_TYPE_FRAME_NUMBER",
|
||||
"FRAME_NUMBER_TYPE_SAMPLE_NUMBER"
|
||||
};
|
||||
|
||||
FLAC_API const char * const FLAC__MetadataTypeString[] = {
|
||||
"STREAMINFO",
|
||||
"PADDING",
|
||||
"APPLICATION",
|
||||
"SEEKTABLE",
|
||||
"VORBIS_COMMENT",
|
||||
"CUESHEET",
|
||||
"PICTURE"
|
||||
};
|
||||
|
||||
FLAC_API const char * const FLAC__StreamMetadata_Picture_TypeString[] = {
|
||||
"Other",
|
||||
"32x32 pixels 'file icon' (PNG only)",
|
||||
"Other file icon",
|
||||
"Cover (front)",
|
||||
"Cover (back)",
|
||||
"Leaflet page",
|
||||
"Media (e.g. label side of CD)",
|
||||
"Lead artist/lead performer/soloist",
|
||||
"Artist/performer",
|
||||
"Conductor",
|
||||
"Band/Orchestra",
|
||||
"Composer",
|
||||
"Lyricist/text writer",
|
||||
"Recording Location",
|
||||
"During recording",
|
||||
"During performance",
|
||||
"Movie/video screen capture",
|
||||
"A bright coloured fish",
|
||||
"Illustration",
|
||||
"Band/artist logotype",
|
||||
"Publisher/Studio logotype"
|
||||
};
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_sample_rate_is_valid(uint32_t sample_rate)
|
||||
{
|
||||
if(sample_rate > FLAC__MAX_SAMPLE_RATE) {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(uint32_t blocksize, uint32_t sample_rate)
|
||||
{
|
||||
if(blocksize > 16384)
|
||||
return false;
|
||||
else if(sample_rate <= 48000 && blocksize > 4608)
|
||||
return false;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_sample_rate_is_subset(uint32_t sample_rate)
|
||||
{
|
||||
if( // sample rate is not subset if
|
||||
!FLAC__format_sample_rate_is_valid(sample_rate) || // sample rate is invalid or
|
||||
sample_rate >= ((1u << 16) * 10) || // sample rate is larger then or equal to 655360 or
|
||||
(sample_rate >= (1u << 16) && sample_rate % 10 != 0) //sample rate is >= 65536 and not divisible by 10
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
|
||||
FLAC_API FLAC__bool FLAC__format_seektable_is_legal(const FLAC__StreamMetadata_SeekTable *seek_table)
|
||||
{
|
||||
uint32_t i;
|
||||
FLAC__uint64 prev_sample_number = 0;
|
||||
FLAC__bool got_prev = false;
|
||||
|
||||
FLAC__ASSERT(0 != seek_table);
|
||||
|
||||
if((FLAC__uint64)(seek_table->num_points) * FLAC__STREAM_METADATA_SEEKPOINT_LENGTH >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < seek_table->num_points; i++) {
|
||||
if(got_prev) {
|
||||
if(
|
||||
seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER &&
|
||||
seek_table->points[i].sample_number <= prev_sample_number
|
||||
)
|
||||
return false;
|
||||
}
|
||||
prev_sample_number = seek_table->points[i].sample_number;
|
||||
got_prev = true;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* used as the sort predicate for qsort() */
|
||||
static int seekpoint_compare_(const FLAC__StreamMetadata_SeekPoint *l, const FLAC__StreamMetadata_SeekPoint *r)
|
||||
{
|
||||
/* we don't just 'return l->sample_number - r->sample_number' since the result (FLAC__int64) might overflow an 'int' */
|
||||
if(l->sample_number == r->sample_number)
|
||||
return 0;
|
||||
else if(l->sample_number < r->sample_number)
|
||||
return -1;
|
||||
else
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
|
||||
FLAC_API uint32_t FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table)
|
||||
{
|
||||
uint32_t i, j;
|
||||
FLAC__bool first;
|
||||
|
||||
FLAC__ASSERT(0 != seek_table);
|
||||
|
||||
if (seek_table->num_points == 0)
|
||||
return 0;
|
||||
|
||||
/* sort the seekpoints */
|
||||
qsort(seek_table->points, seek_table->num_points, sizeof(FLAC__StreamMetadata_SeekPoint), (int (*)(const void *, const void *))seekpoint_compare_);
|
||||
|
||||
/* uniquify the seekpoints */
|
||||
first = true;
|
||||
for(i = j = 0; i < seek_table->num_points; i++) {
|
||||
if(seek_table->points[i].sample_number != FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER) {
|
||||
if(!first) {
|
||||
if(seek_table->points[i].sample_number == seek_table->points[j-1].sample_number)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
first = false;
|
||||
seek_table->points[j++] = seek_table->points[i];
|
||||
}
|
||||
|
||||
for(i = j; i < seek_table->num_points; i++) {
|
||||
seek_table->points[i].sample_number = FLAC__STREAM_METADATA_SEEKPOINT_PLACEHOLDER;
|
||||
seek_table->points[i].stream_offset = 0;
|
||||
seek_table->points[i].frame_samples = 0;
|
||||
}
|
||||
|
||||
return j;
|
||||
}
|
||||
|
||||
/*
|
||||
* also disallows non-shortest-form encodings, c.f.
|
||||
* http://www.unicode.org/versions/corrigendum1.html
|
||||
* and a more clear explanation at the end of this section:
|
||||
* http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
*/
|
||||
static uint32_t utf8len_(const FLAC__byte *utf8)
|
||||
{
|
||||
FLAC__ASSERT(0 != utf8);
|
||||
if ((utf8[0] & 0x80) == 0) {
|
||||
return 1;
|
||||
}
|
||||
else if ((utf8[0] & 0xE0) == 0xC0 && (utf8[1] & 0xC0) == 0x80) {
|
||||
if ((utf8[0] & 0xFE) == 0xC0) /* overlong sequence check */
|
||||
return 0;
|
||||
return 2;
|
||||
}
|
||||
else if ((utf8[0] & 0xF0) == 0xE0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80) {
|
||||
if (utf8[0] == 0xE0 && (utf8[1] & 0xE0) == 0x80) /* overlong sequence check */
|
||||
return 0;
|
||||
/* illegal surrogates check (U+D800...U+DFFF and U+FFFE...U+FFFF) */
|
||||
if (utf8[0] == 0xED && (utf8[1] & 0xE0) == 0xA0) /* D800-DFFF */
|
||||
return 0;
|
||||
if (utf8[0] == 0xEF && utf8[1] == 0xBF && (utf8[2] & 0xFE) == 0xBE) /* FFFE-FFFF */
|
||||
return 0;
|
||||
return 3;
|
||||
}
|
||||
else if ((utf8[0] & 0xF8) == 0xF0 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80) {
|
||||
if (utf8[0] == 0xF0 && (utf8[1] & 0xF0) == 0x80) /* overlong sequence check */
|
||||
return 0;
|
||||
return 4;
|
||||
}
|
||||
else if ((utf8[0] & 0xFC) == 0xF8 && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80) {
|
||||
if (utf8[0] == 0xF8 && (utf8[1] & 0xF8) == 0x80) /* overlong sequence check */
|
||||
return 0;
|
||||
return 5;
|
||||
}
|
||||
else if ((utf8[0] & 0xFE) == 0xFC && (utf8[1] & 0xC0) == 0x80 && (utf8[2] & 0xC0) == 0x80 && (utf8[3] & 0xC0) == 0x80 && (utf8[4] & 0xC0) == 0x80 && (utf8[5] & 0xC0) == 0x80) {
|
||||
if (utf8[0] == 0xFC && (utf8[1] & 0xFC) == 0x80) /* overlong sequence check */
|
||||
return 0;
|
||||
return 6;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_name_is_legal(const char *name)
|
||||
{
|
||||
char c;
|
||||
for(c = *name; c; c = *(++name))
|
||||
if(c < 0x20 || c == 0x3d || c > 0x7d)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_value_is_legal(const FLAC__byte *value, uint32_t length)
|
||||
{
|
||||
if(length == (uint32_t)(-1)) {
|
||||
while(*value) {
|
||||
uint32_t n = utf8len_(value);
|
||||
if(n == 0)
|
||||
return false;
|
||||
value += n;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const FLAC__byte *end = value + length;
|
||||
while(value < end) {
|
||||
uint32_t n = utf8len_(value);
|
||||
if(n == 0)
|
||||
return false;
|
||||
value += n;
|
||||
}
|
||||
if(value != end)
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_vorbiscomment_entry_is_legal(const FLAC__byte *entry, uint32_t length)
|
||||
{
|
||||
const FLAC__byte *s, *end;
|
||||
|
||||
for(s = entry, end = s + length; s < end && *s != '='; s++) {
|
||||
if(*s < 0x20 || *s > 0x7D)
|
||||
return false;
|
||||
}
|
||||
if(s == end)
|
||||
return false;
|
||||
|
||||
s++; /* skip '=' */
|
||||
|
||||
while(s < end) {
|
||||
uint32_t n = utf8len_(s);
|
||||
if(n == 0)
|
||||
return false;
|
||||
s += n;
|
||||
}
|
||||
if(s != end)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
|
||||
FLAC_API FLAC__bool FLAC__format_cuesheet_is_legal(const FLAC__StreamMetadata_CueSheet *cue_sheet, FLAC__bool check_cd_da_subset, const char **violation)
|
||||
{
|
||||
uint32_t i, j;
|
||||
|
||||
if(check_cd_da_subset) {
|
||||
if(cue_sheet->lead_in < 2 * 44100) {
|
||||
if(violation) *violation = "CD-DA cue sheet must have a lead-in length of at least 2 seconds";
|
||||
return false;
|
||||
}
|
||||
if(cue_sheet->lead_in % 588 != 0) {
|
||||
if(violation) *violation = "CD-DA cue sheet lead-in length must be evenly divisible by 588 samples";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(cue_sheet->num_tracks == 0) {
|
||||
if(violation) *violation = "cue sheet must have at least one track (the lead-out)";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(check_cd_da_subset && cue_sheet->tracks[cue_sheet->num_tracks-1].number != 170) {
|
||||
if(violation) *violation = "CD-DA cue sheet must have a lead-out track number 170 (0xAA)";
|
||||
return false;
|
||||
}
|
||||
|
||||
for(i = 0; i < cue_sheet->num_tracks; i++) {
|
||||
if(cue_sheet->tracks[i].number == 0) {
|
||||
if(violation) *violation = "cue sheet may not have a track number 0";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(check_cd_da_subset) {
|
||||
if(!((cue_sheet->tracks[i].number >= 1 && cue_sheet->tracks[i].number <= 99) || cue_sheet->tracks[i].number == 170)) {
|
||||
if(violation) *violation = "CD-DA cue sheet track number must be 1-99 or 170";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(check_cd_da_subset && cue_sheet->tracks[i].offset % 588 != 0) {
|
||||
if(violation) {
|
||||
if(i == cue_sheet->num_tracks-1) /* the lead-out track... */
|
||||
*violation = "CD-DA cue sheet lead-out offset must be evenly divisible by 588 samples";
|
||||
else
|
||||
*violation = "CD-DA cue sheet track offset must be evenly divisible by 588 samples";
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if(i < cue_sheet->num_tracks - 1) {
|
||||
if(cue_sheet->tracks[i].num_indices == 0) {
|
||||
if(violation) *violation = "cue sheet track must have at least one index point";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(cue_sheet->tracks[i].indices[0].number > 1) {
|
||||
if(violation) *violation = "cue sheet track's first index number must be 0 or 1";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(j = 0; j < cue_sheet->tracks[i].num_indices; j++) {
|
||||
if(check_cd_da_subset && cue_sheet->tracks[i].indices[j].offset % 588 != 0) {
|
||||
if(violation) *violation = "CD-DA cue sheet track index offset must be evenly divisible by 588 samples";
|
||||
return false;
|
||||
}
|
||||
|
||||
if(j > 0) {
|
||||
if(cue_sheet->tracks[i].indices[j].number != cue_sheet->tracks[i].indices[j-1].number + 1) {
|
||||
if(violation) *violation = "cue sheet track index numbers must increase by 1";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* @@@@ add to unit tests; it is already indirectly tested by the metadata_object tests */
|
||||
FLAC_API FLAC__bool FLAC__format_picture_is_legal(const FLAC__StreamMetadata_Picture *picture, const char **violation)
|
||||
{
|
||||
char *p;
|
||||
FLAC__byte *b;
|
||||
|
||||
for(p = picture->mime_type; *p; p++) {
|
||||
if(*p < 0x20 || *p > 0x7e) {
|
||||
if(violation) *violation = "MIME type string must contain only printable ASCII characters (0x20-0x7e)";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
for(b = picture->description; *b; ) {
|
||||
uint32_t n = utf8len_(b);
|
||||
if(n == 0) {
|
||||
if(violation) *violation = "description string must be valid UTF-8";
|
||||
return false;
|
||||
}
|
||||
b += n;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* These routines are private to libFLAC
|
||||
*/
|
||||
#if 0 /* UNUSED */
|
||||
uint32_t FLAC__format_get_max_rice_partition_order(uint32_t blocksize, uint32_t predictor_order)
|
||||
{
|
||||
return
|
||||
FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(
|
||||
FLAC__format_get_max_rice_partition_order_from_blocksize(blocksize),
|
||||
blocksize,
|
||||
predictor_order
|
||||
);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t FLAC__format_get_max_rice_partition_order_from_blocksize(uint32_t blocksize)
|
||||
{
|
||||
uint32_t max_rice_partition_order = 0;
|
||||
while(!(blocksize & 1)) {
|
||||
max_rice_partition_order++;
|
||||
blocksize >>= 1;
|
||||
}
|
||||
return flac_min(FLAC__MAX_RICE_PARTITION_ORDER, max_rice_partition_order);
|
||||
}
|
||||
|
||||
uint32_t FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(uint32_t limit, uint32_t blocksize, uint32_t predictor_order)
|
||||
{
|
||||
uint32_t max_rice_partition_order = limit;
|
||||
|
||||
while(max_rice_partition_order > 0 && (blocksize >> max_rice_partition_order) <= predictor_order)
|
||||
max_rice_partition_order--;
|
||||
|
||||
FLAC__ASSERT(
|
||||
(max_rice_partition_order == 0 && blocksize >= predictor_order) ||
|
||||
(max_rice_partition_order > 0 && blocksize >> max_rice_partition_order > predictor_order)
|
||||
);
|
||||
|
||||
return max_rice_partition_order;
|
||||
}
|
||||
|
||||
void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
|
||||
{
|
||||
FLAC__ASSERT(0 != object);
|
||||
|
||||
object->parameters = 0;
|
||||
object->raw_bits = 0;
|
||||
object->capacity_by_order = 0;
|
||||
}
|
||||
|
||||
void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object)
|
||||
{
|
||||
FLAC__ASSERT(0 != object);
|
||||
|
||||
if(0 != object->parameters)
|
||||
free(object->parameters);
|
||||
if(0 != object->raw_bits)
|
||||
free(object->raw_bits);
|
||||
FLAC__format_entropy_coding_method_partitioned_rice_contents_init(object);
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// silence three MSVC warnings 'result of 32-bit shift implicitly converted to 64 bits (was 64-bit shift intended?)'
|
||||
#pragma warning ( disable : 4334 )
|
||||
#endif
|
||||
|
||||
FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, uint32_t max_partition_order)
|
||||
{
|
||||
FLAC__ASSERT(0 != object);
|
||||
|
||||
if(object->capacity_by_order < max_partition_order || object->parameters == NULL || object->raw_bits == NULL) {
|
||||
if(0 == (object->parameters = (uint32_t*) safe_realloc_(object->parameters, sizeof(uint32_t)*(1 << max_partition_order))))
|
||||
return false;
|
||||
if(0 == (object->raw_bits = (uint32_t*) safe_realloc_(object->raw_bits, sizeof(uint32_t)*(1 << max_partition_order))))
|
||||
return false;
|
||||
memset(object->raw_bits, 0, sizeof(uint32_t)*(1 << max_partition_order));
|
||||
object->capacity_by_order = max_partition_order;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning ( default : 4334 )
|
||||
#endif
|
||||
+210
@@ -0,0 +1,210 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__BITMATH_H
|
||||
#define FLAC__PRIVATE__BITMATH_H
|
||||
|
||||
#include "../../../ordinals.h"
|
||||
#include "../../../assert.h"
|
||||
|
||||
#include "../../../compat.h"
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#include <intrin.h> /* for _BitScanReverse* */
|
||||
#endif
|
||||
|
||||
/* Will never be emitted for MSVC, GCC, Intel compilers */
|
||||
static inline uint32_t FLAC__clz_soft_uint32(FLAC__uint32 word)
|
||||
{
|
||||
static const uint8_t byte_to_unary_table[] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
};
|
||||
|
||||
return word > 0xffffff ? byte_to_unary_table[word >> 24] :
|
||||
word > 0xffff ? byte_to_unary_table[word >> 16] + 8 :
|
||||
word > 0xff ? byte_to_unary_table[word >> 8] + 16 :
|
||||
byte_to_unary_table[word] + 24;
|
||||
}
|
||||
|
||||
static inline uint32_t FLAC__clz_uint32(FLAC__uint32 v)
|
||||
{
|
||||
/* Never used with input 0 */
|
||||
FLAC__ASSERT(v > 0);
|
||||
#if defined(__INTEL_COMPILER)
|
||||
return _bit_scan_reverse(v) ^ 31U;
|
||||
#elif defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||
/* This will translate either to (bsr ^ 31U), clz , ctlz, cntlz, lzcnt depending on
|
||||
* -march= setting or to a software routine in exotic machines. */
|
||||
return __builtin_clz(v);
|
||||
#elif defined(_MSC_VER)
|
||||
{
|
||||
uint32_t idx;
|
||||
_BitScanReverse((unsigned long*) &idx, v);
|
||||
return idx ^ 31U;
|
||||
}
|
||||
#else
|
||||
return FLAC__clz_soft_uint32(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Used when 64-bit bsr/clz is unavailable; can use 32-bit bsr/clz when possible */
|
||||
static inline uint32_t FLAC__clz_soft_uint64(FLAC__uint64 word)
|
||||
{
|
||||
return (FLAC__uint32)(word>>32) ? FLAC__clz_uint32((FLAC__uint32)(word>>32)) :
|
||||
FLAC__clz_uint32((FLAC__uint32)word) + 32;
|
||||
}
|
||||
|
||||
static inline uint32_t FLAC__clz_uint64(FLAC__uint64 v)
|
||||
{
|
||||
/* Never used with input 0 */
|
||||
FLAC__ASSERT(v > 0);
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||
return __builtin_clzll(v);
|
||||
#elif (defined(__INTEL_COMPILER) || defined(_MSC_VER)) && (defined(_M_IA64) || defined(_M_X64))
|
||||
{
|
||||
uint32_t idx;
|
||||
_BitScanReverse64((unsigned long*) &idx, v);
|
||||
return idx ^ 63U;
|
||||
}
|
||||
#else
|
||||
return FLAC__clz_soft_uint64(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* These two functions work with input 0 */
|
||||
static inline uint32_t FLAC__clz2_uint32(FLAC__uint32 v)
|
||||
{
|
||||
if (!v)
|
||||
return 32;
|
||||
return FLAC__clz_uint32(v);
|
||||
}
|
||||
|
||||
static inline uint32_t FLAC__clz2_uint64(FLAC__uint64 v)
|
||||
{
|
||||
if (!v)
|
||||
return 64;
|
||||
return FLAC__clz_uint64(v);
|
||||
}
|
||||
|
||||
/* An example of what FLAC__bitmath_ilog2() computes:
|
||||
*
|
||||
* ilog2( 0) = assertion failure
|
||||
* ilog2( 1) = 0
|
||||
* ilog2( 2) = 1
|
||||
* ilog2( 3) = 1
|
||||
* ilog2( 4) = 2
|
||||
* ilog2( 5) = 2
|
||||
* ilog2( 6) = 2
|
||||
* ilog2( 7) = 2
|
||||
* ilog2( 8) = 3
|
||||
* ilog2( 9) = 3
|
||||
* ilog2(10) = 3
|
||||
* ilog2(11) = 3
|
||||
* ilog2(12) = 3
|
||||
* ilog2(13) = 3
|
||||
* ilog2(14) = 3
|
||||
* ilog2(15) = 3
|
||||
* ilog2(16) = 4
|
||||
* ilog2(17) = 4
|
||||
* ilog2(18) = 4
|
||||
*/
|
||||
|
||||
static inline uint32_t FLAC__bitmath_ilog2(FLAC__uint32 v)
|
||||
{
|
||||
FLAC__ASSERT(v > 0);
|
||||
#if defined(__INTEL_COMPILER)
|
||||
return _bit_scan_reverse(v);
|
||||
#elif defined(_MSC_VER)
|
||||
{
|
||||
uint32_t idx;
|
||||
_BitScanReverse((unsigned long*) &idx, v);
|
||||
return idx;
|
||||
}
|
||||
#else
|
||||
return FLAC__clz_uint32(v) ^ 31U;
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline uint32_t FLAC__bitmath_ilog2_wide(FLAC__uint64 v)
|
||||
{
|
||||
FLAC__ASSERT(v > 0);
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||
return __builtin_clzll(v) ^ 63U;
|
||||
/* Sorry, only supported in x64/Itanium.. and both have fast FPU which makes integer-only encoder pointless */
|
||||
#elif (defined(__INTEL_COMPILER) || defined(_MSC_VER)) && (defined(_M_IA64) || defined(_M_X64))
|
||||
{
|
||||
uint32_t idx;
|
||||
_BitScanReverse64((unsigned long*) &idx, v);
|
||||
return idx;
|
||||
}
|
||||
#else
|
||||
/* Brain-damaged compilers will use the fastest possible way that is,
|
||||
de Bruijn sequences (http://supertech.csail.mit.edu/papers/debruijn.pdf)
|
||||
(C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 CC0 (Public domain).
|
||||
*/
|
||||
{
|
||||
static const uint8_t DEBRUIJN_IDX64[64]={
|
||||
0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40,
|
||||
5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57,
|
||||
63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56,
|
||||
62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58
|
||||
};
|
||||
v|= v>>1;
|
||||
v|= v>>2;
|
||||
v|= v>>4;
|
||||
v|= v>>8;
|
||||
v|= v>>16;
|
||||
v|= v>>32;
|
||||
v= (v>>1)+1;
|
||||
return DEBRUIJN_IDX64[v*FLAC__U64L(0x218A392CD3D5DBF)>>58&0x3F];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint32_t FLAC__bitmath_silog2(FLAC__int64 v);
|
||||
|
||||
#endif
|
||||
+101
@@ -0,0 +1,101 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__BITREADER_H
|
||||
#define FLAC__PRIVATE__BITREADER_H
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include "../../../ordinals.h"
|
||||
#include "cpu.h"
|
||||
|
||||
/*
|
||||
* opaque structure definition
|
||||
*/
|
||||
struct FLAC__BitReader;
|
||||
typedef struct FLAC__BitReader FLAC__BitReader;
|
||||
|
||||
typedef FLAC__bool (*FLAC__BitReaderReadCallback)(FLAC__byte buffer[], size_t *bytes, void *client_data);
|
||||
|
||||
/*
|
||||
* construction, deletion, initialization, etc functions
|
||||
*/
|
||||
FLAC__BitReader *FLAC__bitreader_new(void);
|
||||
void FLAC__bitreader_delete(FLAC__BitReader *br);
|
||||
FLAC__bool FLAC__bitreader_init(FLAC__BitReader *br, FLAC__BitReaderReadCallback rcb, void *cd);
|
||||
void FLAC__bitreader_free(FLAC__BitReader *br); /* does not 'free(br)' */
|
||||
FLAC__bool FLAC__bitreader_clear(FLAC__BitReader *br);
|
||||
void FLAC__bitreader_set_framesync_location(FLAC__BitReader *br);
|
||||
FLAC__bool FLAC__bitreader_rewind_to_after_last_seen_framesync(FLAC__BitReader *br);
|
||||
|
||||
/*
|
||||
* CRC functions
|
||||
*/
|
||||
void FLAC__bitreader_reset_read_crc16(FLAC__BitReader *br, FLAC__uint16 seed);
|
||||
FLAC__uint16 FLAC__bitreader_get_read_crc16(FLAC__BitReader *br);
|
||||
|
||||
/*
|
||||
* info functions
|
||||
*/
|
||||
FLAC__bool FLAC__bitreader_is_consumed_byte_aligned(const FLAC__BitReader *br);
|
||||
uint32_t FLAC__bitreader_bits_left_for_byte_alignment(const FLAC__BitReader *br);
|
||||
uint32_t FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br);
|
||||
void FLAC__bitreader_set_limit(FLAC__BitReader *br, uint32_t limit);
|
||||
void FLAC__bitreader_remove_limit(FLAC__BitReader *br);
|
||||
uint32_t FLAC__bitreader_limit_remaining(FLAC__BitReader *br);
|
||||
void FLAC__bitreader_limit_invalidate(FLAC__BitReader *br);
|
||||
|
||||
/*
|
||||
* read functions
|
||||
*/
|
||||
|
||||
FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitreader_read_raw_int64(FLAC__BitReader *br, FLAC__int64 *val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitreader_read_uint32_little_endian(FLAC__BitReader *br, FLAC__uint32 *val); /*only for bits=32*/
|
||||
FLAC__bool FLAC__bitreader_skip_bits_no_crc(FLAC__BitReader *br, uint32_t bits); /* WATCHOUT: does not CRC the skipped data! */ /*@@@@ add to unit tests */
|
||||
FLAC__bool FLAC__bitreader_skip_byte_block_aligned_no_crc(FLAC__BitReader *br, uint32_t nvals); /* WATCHOUT: does not CRC the read data! */
|
||||
FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, FLAC__byte *val, uint32_t nvals); /* WATCHOUT: does not CRC the read data! */
|
||||
FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, uint32_t *val);
|
||||
FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, uint32_t parameter);
|
||||
FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], uint32_t nvals, uint32_t parameter);
|
||||
#ifdef FLAC__BMI2_SUPPORTED
|
||||
FLAC__bool FLAC__bitreader_read_rice_signed_block_bmi2(FLAC__BitReader *br, int vals[], uint32_t nvals, uint32_t parameter);
|
||||
#endif
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitreader_read_golomb_signed(FLAC__BitReader *br, int *val, uint32_t parameter);
|
||||
FLAC__bool FLAC__bitreader_read_golomb_unsigned(FLAC__BitReader *br, uint32_t *val, uint32_t parameter);
|
||||
#endif
|
||||
FLAC__bool FLAC__bitreader_read_utf8_uint32(FLAC__BitReader *br, FLAC__uint32 *val, FLAC__byte *raw, uint32_t *rawlen);
|
||||
FLAC__bool FLAC__bitreader_read_utf8_uint64(FLAC__BitReader *br, FLAC__uint64 *val, FLAC__byte *raw, uint32_t *rawlen);
|
||||
#endif
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__BITWRITER_H
|
||||
#define FLAC__PRIVATE__BITWRITER_H
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include "../../../ordinals.h"
|
||||
|
||||
/*
|
||||
* opaque structure definition
|
||||
*/
|
||||
struct FLAC__BitWriter;
|
||||
typedef struct FLAC__BitWriter FLAC__BitWriter;
|
||||
|
||||
/*
|
||||
* construction, deletion, initialization, etc functions
|
||||
*/
|
||||
FLAC__BitWriter *FLAC__bitwriter_new(void);
|
||||
void FLAC__bitwriter_delete(FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw);
|
||||
void FLAC__bitwriter_free(FLAC__BitWriter *bw); /* does not 'free(buffer)' */
|
||||
void FLAC__bitwriter_clear(FLAC__BitWriter *bw);
|
||||
|
||||
/*
|
||||
* CRC functions
|
||||
*
|
||||
* non-const *bw because they have to cal FLAC__bitwriter_get_buffer()
|
||||
*/
|
||||
FLAC__bool FLAC__bitwriter_get_write_crc16(FLAC__BitWriter *bw, FLAC__uint16 *crc);
|
||||
FLAC__bool FLAC__bitwriter_get_write_crc8(FLAC__BitWriter *bw, FLAC__byte *crc);
|
||||
|
||||
/*
|
||||
* info functions
|
||||
*/
|
||||
FLAC__bool FLAC__bitwriter_is_byte_aligned(const FLAC__BitWriter *bw);
|
||||
uint32_t FLAC__bitwriter_get_input_bits_unconsumed(const FLAC__BitWriter *bw); /* can be called anytime, returns total # of bits unconsumed */
|
||||
|
||||
/*
|
||||
* direct buffer access
|
||||
*
|
||||
* there may be no calls on the bitwriter between get and release.
|
||||
* the bitwriter continues to own the returned buffer.
|
||||
* before get, bitwriter MUST be byte aligned: check with FLAC__bitwriter_is_byte_aligned()
|
||||
*/
|
||||
FLAC__bool FLAC__bitwriter_get_buffer(FLAC__BitWriter *bw, const FLAC__byte **buffer, size_t *bytes);
|
||||
void FLAC__bitwriter_release_buffer(FLAC__BitWriter *bw);
|
||||
|
||||
/*
|
||||
* write functions
|
||||
*/
|
||||
FLAC__bool FLAC__bitwriter_write_zeroes(FLAC__BitWriter *bw, uint32_t bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_int64(FLAC__BitWriter *bw, FLAC__int64 val, uint32_t bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint32_little_endian(FLAC__BitWriter *bw, FLAC__uint32 val); /*only for bits=32*/
|
||||
FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], uint32_t nvals);
|
||||
FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, uint32_t val);
|
||||
#if 0 /* UNUSED */
|
||||
uint32_t FLAC__bitwriter_rice_bits(FLAC__int32 val, uint32_t parameter);
|
||||
uint32_t FLAC__bitwriter_golomb_bits_signed(int val, uint32_t parameter);
|
||||
uint32_t FLAC__bitwriter_golomb_bits_unsigned(uint32_t val, uint32_t parameter);
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, uint32_t parameter);
|
||||
#endif
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, uint32_t nvals, uint32_t parameter);
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, uint32_t parameter);
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, uint32_t val, uint32_t parameter);
|
||||
#endif
|
||||
FLAC__bool FLAC__bitwriter_write_utf8_uint32(FLAC__BitWriter *bw, FLAC__uint32 val);
|
||||
FLAC__bool FLAC__bitwriter_write_utf8_uint64(FLAC__BitWriter *bw, FLAC__uint64 val);
|
||||
FLAC__bool FLAC__bitwriter_zero_pad_to_byte_boundary(FLAC__BitWriter *bw);
|
||||
|
||||
#endif
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__CPU_H
|
||||
#define FLAC__PRIVATE__CPU_H
|
||||
|
||||
#include "../../../ordinals.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__CPU_X86_64
|
||||
|
||||
#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
|
||||
#define FLAC__CPU_X86_64
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__CPU_IA32
|
||||
|
||||
#if defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) ||defined( __i386) || defined(_M_IX86)
|
||||
#define FLAC__CPU_IA32
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef __has_attribute
|
||||
#define __has_attribute(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__AVX_SUPPORTED
|
||||
#define FLAC__AVX_SUPPORTED 0
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FLAC__CPUINFO_TYPE_IA32,
|
||||
FLAC__CPUINFO_TYPE_X86_64,
|
||||
FLAC__CPUINFO_TYPE_UNKNOWN
|
||||
} FLAC__CPUInfo_Type;
|
||||
|
||||
typedef struct {
|
||||
FLAC__bool intel;
|
||||
|
||||
FLAC__bool cmov;
|
||||
FLAC__bool mmx;
|
||||
FLAC__bool sse;
|
||||
FLAC__bool sse2;
|
||||
|
||||
FLAC__bool sse3;
|
||||
FLAC__bool ssse3;
|
||||
FLAC__bool sse41;
|
||||
FLAC__bool sse42;
|
||||
FLAC__bool avx;
|
||||
FLAC__bool avx2;
|
||||
FLAC__bool fma;
|
||||
FLAC__bool bmi2;
|
||||
} FLAC__CPUInfo_x86;
|
||||
|
||||
typedef struct {
|
||||
FLAC__bool use_asm;
|
||||
FLAC__CPUInfo_Type type;
|
||||
FLAC__CPUInfo_x86 x86;
|
||||
} FLAC__CPUInfo;
|
||||
|
||||
void FLAC__cpu_info(FLAC__CPUInfo *info);
|
||||
|
||||
FLAC__uint32 FLAC__cpu_have_cpuid_asm_ia32(void);
|
||||
|
||||
void FLAC__cpu_info_asm_ia32(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx);
|
||||
|
||||
#endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__CRC_H
|
||||
#define FLAC__PRIVATE__CRC_H
|
||||
|
||||
#include "../../../ordinals.h"
|
||||
|
||||
/* 8 bit CRC generator, MSB shifted first
|
||||
** polynomial = x^8 + x^2 + x^1 + x^0
|
||||
** init = 0
|
||||
*/
|
||||
FLAC__uint8 FLAC__crc8(const FLAC__byte *data, uint32_t len);
|
||||
|
||||
/* 16 bit CRC generator, MSB shifted first
|
||||
** polynomial = x^16 + x^15 + x^2 + x^0
|
||||
** init = 0
|
||||
*/
|
||||
extern FLAC__uint16 const FLAC__crc16_table[8][256];
|
||||
|
||||
#define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) & 0xffff) ^ FLAC__crc16_table[0][((crc)>>8) ^ (data)])
|
||||
/* this alternate may be faster on some systems/compilers */
|
||||
#if 0
|
||||
#define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) ^ FLAC__crc16_table[0][((crc)>>8) ^ (data)]) & 0xffff)
|
||||
#endif
|
||||
|
||||
FLAC__uint16 FLAC__crc16(const FLAC__byte *data, uint32_t len);
|
||||
FLAC__uint16 FLAC__crc16_update_words32(const FLAC__uint32 *words, uint32_t len, FLAC__uint16 crc);
|
||||
FLAC__uint16 FLAC__crc16_update_words64(const FLAC__uint64 *words, uint32_t len, FLAC__uint16 crc);
|
||||
|
||||
#endif
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__FIXED_H
|
||||
#define FLAC__PRIVATE__FIXED_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "cpu.h"
|
||||
#include "float.h"
|
||||
#include "../../../format.h"
|
||||
|
||||
/*
|
||||
* FLAC__fixed_compute_best_predictor()
|
||||
* --------------------------------------------------------------------
|
||||
* Compute the best fixed predictor and the expected bits-per-sample
|
||||
* of the residual signal for each order. The _wide() version uses
|
||||
* 64-bit integers which is statistically necessary when bits-per-
|
||||
* sample + log2(blocksize) > 30
|
||||
*
|
||||
* IN data[0,data_len-1]
|
||||
* IN data_len
|
||||
* OUT residual_bits_per_sample[0,FLAC__MAX_FIXED_ORDER]
|
||||
*/
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
# ifndef FLAC__NO_ASM
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE2_SUPPORTED
|
||||
uint32_t FLAC__fixed_compute_best_predictor_intrin_sse2(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]);
|
||||
# endif
|
||||
# ifdef FLAC__SSSE3_SUPPORTED
|
||||
uint32_t FLAC__fixed_compute_best_predictor_intrin_ssse3(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
# endif
|
||||
# ifdef FLAC__SSE4_2_SUPPORTED
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual_intrin_sse42(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
# endif
|
||||
# ifdef FLAC__AVX2_SUPPORTED
|
||||
uint32_t FLAC__fixed_compute_best_predictor_wide_intrin_avx2(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual_intrin_avx2(const FLAC__int32 data[], uint32_t data_len, float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
# endif
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
uint32_t FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual(const FLAC__int32 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
uint32_t FLAC__fixed_compute_best_predictor_limit_residual_33bit(const FLAC__int64 data[], uint32_t data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* FLAC__fixed_compute_residual()
|
||||
* --------------------------------------------------------------------
|
||||
* Compute the residual signal obtained from sutracting the predicted
|
||||
* signal from the original.
|
||||
*
|
||||
* IN data[-order,data_len-1] original signal (NOTE THE INDICES!)
|
||||
* IN data_len length of original signal
|
||||
* IN order <= FLAC__MAX_FIXED_ORDER fixed-predictor order
|
||||
* OUT residual[0,data_len-1] residual signal
|
||||
*/
|
||||
void FLAC__fixed_compute_residual(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]);
|
||||
void FLAC__fixed_compute_residual_wide(const FLAC__int32 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]);
|
||||
void FLAC__fixed_compute_residual_wide_33bit(const FLAC__int64 data[], uint32_t data_len, uint32_t order, FLAC__int32 residual[]);
|
||||
|
||||
/*
|
||||
* FLAC__fixed_restore_signal()
|
||||
* --------------------------------------------------------------------
|
||||
* Restore the original signal by summing the residual and the
|
||||
* predictor.
|
||||
*
|
||||
* IN residual[0,data_len-1] residual signal
|
||||
* IN data_len length of original signal
|
||||
* IN order <= FLAC__MAX_FIXED_ORDER fixed-predictor order
|
||||
* *** IMPORTANT: the caller must pass in the historical samples:
|
||||
* IN data[-order,-1] previously-reconstructed historical samples
|
||||
* OUT data[0,data_len-1] original signal
|
||||
*/
|
||||
void FLAC__fixed_restore_signal(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[]);
|
||||
void FLAC__fixed_restore_signal_wide(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int32 data[]);
|
||||
void FLAC__fixed_restore_signal_wide_33bit(const FLAC__int32 residual[], uint32_t data_len, uint32_t order, FLAC__int64 data[]);
|
||||
|
||||
#endif
|
||||
+95
@@ -0,0 +1,95 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__FLOAT_H
|
||||
#define FLAC__PRIVATE__FLOAT_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "../../../ordinals.h"
|
||||
|
||||
/*
|
||||
* All the code in libFLAC that uses float and double
|
||||
* should be protected by checks of the macro
|
||||
* FLAC__INTEGER_ONLY_LIBRARY.
|
||||
*
|
||||
*/
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
/*
|
||||
* FLAC__real is the basic floating point type used in LPC analysis.
|
||||
*
|
||||
* WATCHOUT: changing FLAC__real will change the signatures of many
|
||||
* functions that have assembly language equivalents and break them.
|
||||
*/
|
||||
typedef float FLAC__real;
|
||||
#else
|
||||
/*
|
||||
* The convention for FLAC__fixedpoint is to use the upper 16 bits
|
||||
* for the integer part and lower 16 bits for the fractional part.
|
||||
*/
|
||||
typedef FLAC__int32 FLAC__fixedpoint;
|
||||
extern const FLAC__fixedpoint FLAC__FP_ZERO;
|
||||
extern const FLAC__fixedpoint FLAC__FP_ONE_HALF;
|
||||
extern const FLAC__fixedpoint FLAC__FP_ONE;
|
||||
extern const FLAC__fixedpoint FLAC__FP_LN2;
|
||||
extern const FLAC__fixedpoint FLAC__FP_E;
|
||||
|
||||
#define FLAC__fixedpoint_trunc(x) ((x)>>16)
|
||||
|
||||
#define FLAC__fixedpoint_mul(x, y) ( (FLAC__fixedpoint) ( ((FLAC__int64)(x)*(FLAC__int64)(y)) >> 16 ) )
|
||||
|
||||
#define FLAC__fixedpoint_div(x, y) ( (FLAC__fixedpoint) ( ( ((FLAC__int64)(x)<<32) / (FLAC__int64)(y) ) >> 16 ) )
|
||||
|
||||
/*
|
||||
* FLAC__fixedpoint_log2()
|
||||
* --------------------------------------------------------------------
|
||||
* Returns the base-2 logarithm of the fixed-point number 'x' using an
|
||||
* algorithm by Knuth for x >= 1.0
|
||||
*
|
||||
* 'fracbits' is the number of fractional bits of 'x'. 'fracbits' must
|
||||
* be < 32 and evenly divisible by 4 (0 is OK but not very precise).
|
||||
*
|
||||
* 'precision' roughly limits the number of iterations that are done;
|
||||
* use (uint32_t)(-1) for maximum precision.
|
||||
*
|
||||
* If 'x' is less than one -- that is, x < (1<<fracbits) -- then this
|
||||
* function will punt and return 0.
|
||||
*
|
||||
* The return value will also have 'fracbits' fractional bits.
|
||||
*/
|
||||
FLAC__uint32 FLAC__fixedpoint_log2(FLAC__uint32 x, uint32_t fracbits, uint32_t precision);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+47
@@ -0,0 +1,47 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__FORMAT_H
|
||||
#define FLAC__PRIVATE__FORMAT_H
|
||||
|
||||
#include "../../../format.h"
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
uint32_t FLAC__format_get_max_rice_partition_order(uint32_t blocksize, uint32_t predictor_order);
|
||||
#endif
|
||||
uint32_t FLAC__format_get_max_rice_partition_order_from_blocksize(uint32_t blocksize);
|
||||
uint32_t FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(uint32_t limit, uint32_t blocksize, uint32_t predictor_order);
|
||||
void FLAC__format_entropy_coding_method_partitioned_rice_contents_init(FLAC__EntropyCodingMethod_PartitionedRiceContents *object);
|
||||
void FLAC__format_entropy_coding_method_partitioned_rice_contents_clear(FLAC__EntropyCodingMethod_PartitionedRiceContents *object);
|
||||
FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, uint32_t max_partition_order);
|
||||
|
||||
#endif
|
||||
+238
@@ -0,0 +1,238 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__LPC_H
|
||||
#define FLAC__PRIVATE__LPC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "cpu.h"
|
||||
#include "float.h"
|
||||
#include "../../../format.h"
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
/*
|
||||
* FLAC__lpc_window_data()
|
||||
* --------------------------------------------------------------------
|
||||
* Applies the given window to the data.
|
||||
* OPT: asm implementation
|
||||
*
|
||||
* IN in[0,data_len-1]
|
||||
* IN window[0,data_len-1]
|
||||
* OUT out[0,lag-1]
|
||||
* IN data_len
|
||||
*/
|
||||
void FLAC__lpc_window_data(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len);
|
||||
void FLAC__lpc_window_data_wide(const FLAC__int64 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len);
|
||||
void FLAC__lpc_window_data_partial(const FLAC__int32 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len, uint32_t part_size, uint32_t data_shift);
|
||||
void FLAC__lpc_window_data_partial_wide(const FLAC__int64 in[], const FLAC__real window[], FLAC__real out[], uint32_t data_len, uint32_t part_size, uint32_t data_shift);
|
||||
|
||||
/*
|
||||
* FLAC__lpc_compute_autocorrelation()
|
||||
* --------------------------------------------------------------------
|
||||
* Compute the autocorrelation for lags between 0 and lag-1.
|
||||
* Assumes data[] outside of [0,data_len-1] == 0.
|
||||
* Asserts that lag > 0.
|
||||
*
|
||||
* IN data[0,data_len-1]
|
||||
* IN data_len
|
||||
* IN 0 < lag <= data_len
|
||||
* OUT autoc[0,lag-1]
|
||||
*/
|
||||
void FLAC__lpc_compute_autocorrelation(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
#ifndef FLAC__NO_ASM
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE2_SUPPORTED
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_10(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse2_lag_14(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
# endif
|
||||
# endif
|
||||
# if defined FLAC__CPU_X86_64 && FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__FMA_SUPPORTED
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_fma_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_fma_lag_12(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_fma_lag_16(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
# endif
|
||||
# endif
|
||||
#if defined FLAC__CPU_ARM64 && FLAC__HAS_NEONINTRIN && FLAC__HAS_A64NEONINTRIN
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_neon_lag_8(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_neon_lag_10(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_neon_lag_14(const FLAC__real data[], uint32_t data_len, uint32_t lag, double autoc[]);
|
||||
#endif
|
||||
#endif /* FLAC__NO_ASM */
|
||||
|
||||
/*
|
||||
* FLAC__lpc_compute_lp_coefficients()
|
||||
* --------------------------------------------------------------------
|
||||
* Computes LP coefficients for orders 1..max_order.
|
||||
* Do not call if autoc[0] == 0.0. This means the signal is zero
|
||||
* and there is no point in calculating a predictor.
|
||||
*
|
||||
* IN autoc[0,max_order] autocorrelation values
|
||||
* IN 0 < max_order <= FLAC__MAX_LPC_ORDER max LP order to compute
|
||||
* OUT lp_coeff[0,max_order-1][0,max_order-1] LP coefficients for each order
|
||||
* *** IMPORTANT:
|
||||
* *** lp_coeff[0,max_order-1][max_order,FLAC__MAX_LPC_ORDER-1] are untouched
|
||||
* OUT error[0,max_order-1] error for each order (more
|
||||
* specifically, the variance of
|
||||
* the error signal times # of
|
||||
* samples in the signal)
|
||||
*
|
||||
* Example: if max_order is 9, the LP coefficients for order 9 will be
|
||||
* in lp_coeff[8][0,8], the LP coefficients for order 8 will be
|
||||
* in lp_coeff[7][0,7], etc.
|
||||
*/
|
||||
void FLAC__lpc_compute_lp_coefficients(const double autoc[], uint32_t *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], double error[]);
|
||||
|
||||
/*
|
||||
* FLAC__lpc_quantize_coefficients()
|
||||
* --------------------------------------------------------------------
|
||||
* Quantizes the LP coefficients. NOTE: precision + bits_per_sample
|
||||
* must be less than 32 (sizeof(FLAC__int32)*8).
|
||||
*
|
||||
* IN lp_coeff[0,order-1] LP coefficients
|
||||
* IN order LP order
|
||||
* IN FLAC__MIN_QLP_COEFF_PRECISION < precision
|
||||
* desired precision (in bits, including sign
|
||||
* bit) of largest coefficient
|
||||
* OUT qlp_coeff[0,order-1] quantized coefficients
|
||||
* OUT shift # of bits to shift right to get approximated
|
||||
* LP coefficients. NOTE: could be negative.
|
||||
* RETURN 0 => quantization OK
|
||||
* 1 => coefficients require too much shifting for *shift to
|
||||
* fit in the LPC subframe header. 'shift' is unset.
|
||||
* 2 => coefficients are all zero, which is bad. 'shift' is
|
||||
* unset.
|
||||
*/
|
||||
int FLAC__lpc_quantize_coefficients(const FLAC__real lp_coeff[], uint32_t order, uint32_t precision, FLAC__int32 qlp_coeff[], int *shift);
|
||||
|
||||
/*
|
||||
* FLAC__lpc_compute_residual_from_qlp_coefficients()
|
||||
* --------------------------------------------------------------------
|
||||
* Compute the residual signal obtained from sutracting the predicted
|
||||
* signal from the original.
|
||||
*
|
||||
* IN data[-order,data_len-1] original signal (NOTE THE INDICES!)
|
||||
* IN data_len length of original signal
|
||||
* IN qlp_coeff[0,order-1] quantized LP coefficients
|
||||
* IN order > 0 LP order
|
||||
* IN lp_quantization quantization of LP coefficients in bits
|
||||
* OUT residual[0,data_len-1] residual signal
|
||||
*/
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
FLAC__bool FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
FLAC__bool FLAC__lpc_compute_residual_from_qlp_coefficients_limit_residual_33bit(const FLAC__int64 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
#ifndef FLAC__NO_ASM
|
||||
# ifdef FLAC__CPU_ARM64
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_neon(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_neon(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
# endif
|
||||
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE2_SUPPORTED
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
# endif
|
||||
# ifdef FLAC__SSE4_1_SUPPORTED
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse41(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_sse41(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
# endif
|
||||
# ifdef FLAC__AVX2_SUPPORTED
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_avx2(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_avx2(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2(const FLAC__int32 *data, uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 residual[]);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
|
||||
uint32_t FLAC__lpc_max_prediction_before_shift_bps(uint32_t subframe_bps, const FLAC__int32 qlp_coeff[], uint32_t order);
|
||||
uint32_t FLAC__lpc_max_residual_bps(uint32_t subframe_bps, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization);
|
||||
|
||||
/*
|
||||
* FLAC__lpc_restore_signal()
|
||||
* --------------------------------------------------------------------
|
||||
* Restore the original signal by summing the residual and the
|
||||
* predictor.
|
||||
*
|
||||
* IN residual[0,data_len-1] residual signal
|
||||
* IN data_len length of original signal
|
||||
* IN qlp_coeff[0,order-1] quantized LP coefficients
|
||||
* IN order > 0 LP order
|
||||
* IN lp_quantization quantization of LP coefficients in bits
|
||||
* *** IMPORTANT: the caller must pass in the historical samples:
|
||||
* IN data[-order,-1] previously-reconstructed historical samples
|
||||
* OUT data[0,data_len-1] original signal
|
||||
*/
|
||||
void FLAC__lpc_restore_signal(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]);
|
||||
void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int32 data[]);
|
||||
void FLAC__lpc_restore_signal_wide_33bit(const FLAC__int32 residual[], uint32_t data_len, const FLAC__int32 qlp_coeff[], uint32_t order, int lp_quantization, FLAC__int64 data[]);
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
/*
|
||||
* FLAC__lpc_compute_expected_bits_per_residual_sample()
|
||||
* --------------------------------------------------------------------
|
||||
* Compute the expected number of bits per residual signal sample
|
||||
* based on the LP error (which is related to the residual variance).
|
||||
*
|
||||
* IN lpc_error >= 0.0 error returned from calculating LP coefficients
|
||||
* IN total_samples > 0 # of samples in residual signal
|
||||
* RETURN expected bits per sample
|
||||
*/
|
||||
double FLAC__lpc_compute_expected_bits_per_residual_sample(double lpc_error, uint32_t total_samples);
|
||||
double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(double lpc_error, double error_scale);
|
||||
|
||||
/*
|
||||
* FLAC__lpc_compute_best_order()
|
||||
* --------------------------------------------------------------------
|
||||
* Compute the best order from the array of signal errors returned
|
||||
* during coefficient computation.
|
||||
*
|
||||
* IN lpc_error[0,max_order-1] >= 0.0 error returned from calculating LP coefficients
|
||||
* IN max_order > 0 max LP order
|
||||
* IN total_samples > 0 # of samples in residual signal
|
||||
* IN overhead_bits_per_order # of bits overhead for each increased LP order
|
||||
* (includes warmup sample size and quantized LP coefficient)
|
||||
* RETURN [1,max_order] best order
|
||||
*/
|
||||
uint32_t FLAC__lpc_compute_best_order(const double lpc_error[], uint32_t max_order, uint32_t total_samples, uint32_t overhead_bits_per_order);
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
|
||||
#endif
|
||||
+50
@@ -0,0 +1,50 @@
|
||||
#ifndef FLAC__PRIVATE__MD5_H
|
||||
#define FLAC__PRIVATE__MD5_H
|
||||
|
||||
/*
|
||||
* This is the header file for the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*
|
||||
* Changed so as no longer to depend on Colin Plumb's `usual.h'
|
||||
* header definitions; now uses stuff from dpkg's config.h
|
||||
* - Ian Jackson <ijackson@nyx.cs.du.edu>.
|
||||
* Still in the public domain.
|
||||
*
|
||||
* Josh Coalson: made some changes to integrate with libFLAC.
|
||||
* Still in the public domain, with no warranty.
|
||||
*/
|
||||
|
||||
#include "../../../ordinals.h"
|
||||
|
||||
typedef union {
|
||||
FLAC__byte *p8;
|
||||
FLAC__int16 *p16;
|
||||
FLAC__int32 *p32;
|
||||
} FLAC__multibyte;
|
||||
|
||||
typedef struct {
|
||||
FLAC__uint32 in[16];
|
||||
FLAC__uint32 buf[4];
|
||||
FLAC__uint32 bytes[2];
|
||||
FLAC__multibyte internal_buf;
|
||||
size_t capacity;
|
||||
} FLAC__MD5Context;
|
||||
|
||||
void FLAC__MD5Init(FLAC__MD5Context *context);
|
||||
void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *context);
|
||||
|
||||
FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const signal[], uint32_t channels, uint32_t samples, uint32_t bytes_per_sample);
|
||||
|
||||
#endif
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__MEMORY_H
|
||||
#define FLAC__PRIVATE__MEMORY_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for size_t */
|
||||
|
||||
#include "float.h"
|
||||
#include "../../../ordinals.h" /* for FLAC__bool */
|
||||
|
||||
/* Returns the unaligned address returned by malloc.
|
||||
* Use free() on this address to deallocate.
|
||||
*/
|
||||
void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_int32_array(size_t elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_uint32_array(size_t elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_int64_array(size_t elements, FLAC__int64 **unaligned_pointer, FLAC__int64 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_uint64_array(size_t elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer);
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
FLAC__bool FLAC__memory_alloc_aligned_real_array(size_t elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer);
|
||||
#endif
|
||||
void *safe_malloc_mul_2op_p(size_t size1, size_t size2);
|
||||
|
||||
#endif
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__STREAM_ENCODER_H
|
||||
#define FLAC__PRIVATE__STREAM_ENCODER_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This is used to avoid overflow with unusual signals in 32-bit
|
||||
* accumulator in the *precompute_partition_info_sums_* functions.
|
||||
*/
|
||||
#define FLAC__MAX_EXTRA_RESIDUAL_BPS 4
|
||||
|
||||
#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
#include "cpu.h"
|
||||
#include "../../../format.h"
|
||||
|
||||
#ifdef FLAC__SSE2_SUPPORTED
|
||||
extern void FLAC__precompute_partition_info_sums_intrin_sse2(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[],
|
||||
uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps);
|
||||
#endif
|
||||
|
||||
#ifdef FLAC__SSSE3_SUPPORTED
|
||||
extern void FLAC__precompute_partition_info_sums_intrin_ssse3(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[],
|
||||
uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps);
|
||||
#endif
|
||||
|
||||
#ifdef FLAC__AVX2_SUPPORTED
|
||||
extern void FLAC__precompute_partition_info_sums_intrin_avx2(const FLAC__int32 residual[], FLAC__uint64 abs_residual_partition_sums[],
|
||||
uint32_t residual_samples, uint32_t predictor_order, uint32_t min_partition_order, uint32_t max_partition_order, uint32_t bps);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__STREAM_ENCODER_FRAMING_H
|
||||
#define FLAC__PRIVATE__STREAM_ENCODER_FRAMING_H
|
||||
|
||||
#include "../../../format.h"
|
||||
#include "bitwriter.h"
|
||||
|
||||
FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw, FLAC__bool update_vendor_string);
|
||||
FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, uint32_t residual_samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, uint32_t residual_samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, uint32_t samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw);
|
||||
|
||||
#endif
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2006-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__WINDOW_H
|
||||
#define FLAC__PRIVATE__WINDOW_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include "float.h"
|
||||
#include "../../../format.h"
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
/*
|
||||
* FLAC__window_*()
|
||||
* --------------------------------------------------------------------
|
||||
* Calculates window coefficients according to different apodization
|
||||
* functions.
|
||||
*
|
||||
* OUT window[0,L-1]
|
||||
* IN L (number of points in window)
|
||||
*/
|
||||
void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_bartlett_hann(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_blackman_harris_4term_92db_sidelobe(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_connes(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_flattop(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_gauss(FLAC__real *window, const FLAC__int32 L, const FLAC__real stddev); /* 0.0 < stddev <= 0.5 */
|
||||
void FLAC__window_hamming(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_hann(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_kaiser_bessel(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_nuttall(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_rectangle(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_triangle(FLAC__real *window, const FLAC__int32 L);
|
||||
void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p);
|
||||
void FLAC__window_partial_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end);
|
||||
void FLAC__window_punchout_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end);
|
||||
void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L);
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
|
||||
#endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PROTECTED__STREAM_DECODER_H
|
||||
#define FLAC__PROTECTED__STREAM_DECODER_H
|
||||
|
||||
#include "../../../stream_decoder.h"
|
||||
#if FLAC__HAS_OGG
|
||||
#include "../private/ogg_decoder_aspect.h"
|
||||
#endif
|
||||
|
||||
typedef struct FLAC__StreamDecoderProtected {
|
||||
FLAC__StreamDecoderState state;
|
||||
FLAC__StreamDecoderInitStatus initstate;
|
||||
uint32_t channels;
|
||||
FLAC__ChannelAssignment channel_assignment;
|
||||
uint32_t bits_per_sample;
|
||||
uint32_t sample_rate; /* in Hz */
|
||||
uint32_t blocksize; /* in samples (per channel) */
|
||||
FLAC__bool md5_checking; /* if true, generate MD5 signature of decoded data and compare against signature in the STREAMINFO metadata block */
|
||||
#if FLAC__HAS_OGG
|
||||
FLAC__OggDecoderAspect ogg_decoder_aspect;
|
||||
#endif
|
||||
} FLAC__StreamDecoderProtected;
|
||||
|
||||
/*
|
||||
* Return the number of input bytes consumed
|
||||
*/
|
||||
uint32_t FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
#endif
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PROTECTED__STREAM_ENCODER_H
|
||||
#define FLAC__PROTECTED__STREAM_ENCODER_H
|
||||
|
||||
#include "../../../stream_encoder.h"
|
||||
#if FLAC__HAS_OGG
|
||||
#include "../private/ogg_encoder_aspect.h"
|
||||
#endif
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
#include "../private/float.h"
|
||||
|
||||
#define FLAC__MAX_APODIZATION_FUNCTIONS 32
|
||||
|
||||
typedef enum {
|
||||
FLAC__APODIZATION_BARTLETT,
|
||||
FLAC__APODIZATION_BARTLETT_HANN,
|
||||
FLAC__APODIZATION_BLACKMAN,
|
||||
FLAC__APODIZATION_BLACKMAN_HARRIS_4TERM_92DB_SIDELOBE,
|
||||
FLAC__APODIZATION_CONNES,
|
||||
FLAC__APODIZATION_FLATTOP,
|
||||
FLAC__APODIZATION_GAUSS,
|
||||
FLAC__APODIZATION_HAMMING,
|
||||
FLAC__APODIZATION_HANN,
|
||||
FLAC__APODIZATION_KAISER_BESSEL,
|
||||
FLAC__APODIZATION_NUTTALL,
|
||||
FLAC__APODIZATION_RECTANGLE,
|
||||
FLAC__APODIZATION_TRIANGLE,
|
||||
FLAC__APODIZATION_TUKEY,
|
||||
FLAC__APODIZATION_PARTIAL_TUKEY,
|
||||
FLAC__APODIZATION_PUNCHOUT_TUKEY,
|
||||
FLAC__APODIZATION_SUBDIVIDE_TUKEY,
|
||||
FLAC__APODIZATION_WELCH
|
||||
} FLAC__ApodizationFunction;
|
||||
|
||||
typedef struct {
|
||||
FLAC__ApodizationFunction type;
|
||||
union {
|
||||
struct {
|
||||
FLAC__real stddev;
|
||||
} gauss;
|
||||
struct {
|
||||
FLAC__real p;
|
||||
} tukey;
|
||||
struct {
|
||||
FLAC__real p;
|
||||
FLAC__real start;
|
||||
FLAC__real end;
|
||||
} multiple_tukey;
|
||||
struct {
|
||||
FLAC__real p;
|
||||
FLAC__int32 parts;
|
||||
} subdivide_tukey;
|
||||
} parameters;
|
||||
} FLAC__ApodizationSpecification;
|
||||
|
||||
#endif // #ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
typedef struct FLAC__StreamEncoderProtected {
|
||||
FLAC__StreamEncoderState state;
|
||||
FLAC__bool verify;
|
||||
FLAC__bool streamable_subset;
|
||||
FLAC__bool do_md5;
|
||||
FLAC__bool do_mid_side_stereo;
|
||||
FLAC__bool loose_mid_side_stereo;
|
||||
uint32_t channels;
|
||||
uint32_t bits_per_sample;
|
||||
uint32_t sample_rate;
|
||||
uint32_t blocksize;
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
uint32_t num_apodizations;
|
||||
FLAC__ApodizationSpecification apodizations[FLAC__MAX_APODIZATION_FUNCTIONS];
|
||||
#endif
|
||||
uint32_t max_lpc_order;
|
||||
uint32_t qlp_coeff_precision;
|
||||
FLAC__bool do_qlp_coeff_prec_search;
|
||||
FLAC__bool do_exhaustive_model_search;
|
||||
FLAC__bool do_escape_coding;
|
||||
uint32_t min_residual_partition_order;
|
||||
uint32_t max_residual_partition_order;
|
||||
uint32_t rice_parameter_search_dist;
|
||||
FLAC__uint64 total_samples_estimate;
|
||||
FLAC__bool limit_min_bitrate;
|
||||
FLAC__StreamMetadata **metadata;
|
||||
uint32_t num_metadata_blocks;
|
||||
FLAC__uint64 streaminfo_offset, seektable_offset, audio_offset;
|
||||
#if FLAC__HAS_OGG
|
||||
FLAC__OggEncoderAspect ogg_encoder_aspect;
|
||||
#endif
|
||||
} FLAC__StreamEncoderProtected;
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,517 @@
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcpy() */
|
||||
|
||||
#include "include/private/md5.h"
|
||||
#include "../alloc.h"
|
||||
#include "../compat.h"
|
||||
#include "../endswap.h"
|
||||
|
||||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* MD5Context structure, pass it to MD5Init, call MD5Update as
|
||||
* needed on buffers full of bytes, and then call MD5Final, which
|
||||
* will fill a supplied 16-byte array with the digest.
|
||||
*
|
||||
* Changed so as no longer to depend on Colin Plumb's `usual.h' header
|
||||
* definitions; now uses stuff from dpkg's config.h.
|
||||
* - Ian Jackson <ijackson@nyx.cs.du.edu>.
|
||||
* Still in the public domain.
|
||||
*
|
||||
* Josh Coalson: made some changes to integrate with libFLAC.
|
||||
* Still in the public domain.
|
||||
*/
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
/* #define F1(x, y, z) (x & y | ~x & z) */
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1(z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define MD5STEP(f,w,x,y,z,in,s) \
|
||||
(w += f(x,y,z) + in, w = (w<<s | w>>(32-s)) + x)
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. MD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void FLAC__MD5Transform(FLAC__uint32 buf[4], FLAC__uint32 const in[16])
|
||||
{
|
||||
FLAC__uint32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
MD5STEP(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
MD5STEP(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
MD5STEP(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
MD5STEP(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
MD5STEP(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
MD5STEP(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
MD5STEP(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
MD5STEP(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
MD5STEP(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
MD5STEP(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
MD5STEP(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
MD5STEP(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
MD5STEP(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
MD5STEP(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
MD5STEP(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
MD5STEP(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
MD5STEP(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
MD5STEP(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
MD5STEP(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
MD5STEP(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
//@@@@@@ OPT: use bswap/intrinsics
|
||||
static void byteSwap(FLAC__uint32 *buf, uint32_t words)
|
||||
{
|
||||
register FLAC__uint32 x;
|
||||
do {
|
||||
x = *buf;
|
||||
x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff);
|
||||
*buf++ = (x >> 16) | (x << 16);
|
||||
} while (--words);
|
||||
}
|
||||
static void byteSwapX16(FLAC__uint32 *buf)
|
||||
{
|
||||
register FLAC__uint32 x;
|
||||
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf++ = (x >> 16) | (x << 16);
|
||||
x = *buf; x = ((x << 8) & 0xff00ff00) | ((x >> 8) & 0x00ff00ff); *buf = (x >> 16) | (x << 16);
|
||||
}
|
||||
#else
|
||||
#define byteSwap(buf, words)
|
||||
#define byteSwapX16(buf)
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
static void FLAC__MD5Update(FLAC__MD5Context *ctx, FLAC__byte const *buf, uint32_t len)
|
||||
{
|
||||
FLAC__uint32 t;
|
||||
|
||||
/* Update byte count */
|
||||
|
||||
t = ctx->bytes[0];
|
||||
if ((ctx->bytes[0] = t + len) < t)
|
||||
ctx->bytes[1]++; /* Carry from low to high */
|
||||
|
||||
t = 64 - (t & 0x3f); /* Space available in ctx->in (at least 1) */
|
||||
if (t > len) {
|
||||
memcpy((FLAC__byte *)ctx->in + 64 - t, buf, len);
|
||||
return;
|
||||
}
|
||||
/* First chunk is an odd size */
|
||||
memcpy((FLAC__byte *)ctx->in + 64 - t, buf, t);
|
||||
byteSwapX16(ctx->in);
|
||||
FLAC__MD5Transform(ctx->buf, ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
|
||||
/* Process data in 64-byte chunks */
|
||||
while (len >= 64) {
|
||||
memcpy(ctx->in, buf, 64);
|
||||
byteSwapX16(ctx->in);
|
||||
FLAC__MD5Transform(ctx->buf, ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void FLAC__MD5Init(FLAC__MD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bytes[0] = 0;
|
||||
ctx->bytes[1] = 0;
|
||||
|
||||
ctx->internal_buf.p8 = 0;
|
||||
ctx->capacity = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void FLAC__MD5Final(FLAC__byte digest[16], FLAC__MD5Context *ctx)
|
||||
{
|
||||
int count = ctx->bytes[0] & 0x3f; /* Number of bytes in ctx->in */
|
||||
FLAC__byte *p = (FLAC__byte *)ctx->in + count;
|
||||
|
||||
/* Set the first char of padding to 0x80. There is always room. */
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 56 bytes (-8..55) */
|
||||
count = 56 - 1 - count;
|
||||
|
||||
if (count < 0) { /* Padding forces an extra block */
|
||||
memset(p, 0, count + 8);
|
||||
byteSwapX16(ctx->in);
|
||||
FLAC__MD5Transform(ctx->buf, ctx->in);
|
||||
p = (FLAC__byte *)ctx->in;
|
||||
count = 56;
|
||||
}
|
||||
memset(p, 0, count);
|
||||
byteSwap(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
ctx->in[14] = ctx->bytes[0] << 3;
|
||||
ctx->in[15] = ctx->bytes[1] << 3 | ctx->bytes[0] >> 29;
|
||||
FLAC__MD5Transform(ctx->buf, ctx->in);
|
||||
|
||||
byteSwap(ctx->buf, 4);
|
||||
memcpy(digest, ctx->buf, 16);
|
||||
if (0 != ctx->internal_buf.p8) {
|
||||
free(ctx->internal_buf.p8);
|
||||
ctx->internal_buf.p8 = 0;
|
||||
ctx->capacity = 0;
|
||||
}
|
||||
memset(ctx, 0, sizeof(*ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the incoming audio signal to a byte stream
|
||||
*/
|
||||
static void format_input_(FLAC__multibyte *mbuf, const FLAC__int32 * const signal[], uint32_t channels, uint32_t samples, uint32_t bytes_per_sample)
|
||||
{
|
||||
FLAC__byte *buf_ = mbuf->p8;
|
||||
FLAC__int16 *buf16 = mbuf->p16;
|
||||
FLAC__int32 *buf32 = mbuf->p32;
|
||||
FLAC__int32 a_word;
|
||||
uint32_t channel, sample;
|
||||
|
||||
/* Storage in the output buffer, buf, is little endian. */
|
||||
|
||||
#define BYTES_CHANNEL_SELECTOR(bytes, channels) (bytes * 100 + channels)
|
||||
|
||||
/* First do the most commonly used combinations. */
|
||||
switch (BYTES_CHANNEL_SELECTOR (bytes_per_sample, channels)) {
|
||||
/* One byte per sample. */
|
||||
case (BYTES_CHANNEL_SELECTOR (1, 1)):
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
*buf_++ = signal[0][sample];
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (1, 2)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf_++ = signal[0][sample];
|
||||
*buf_++ = signal[1][sample];
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (1, 4)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf_++ = signal[0][sample];
|
||||
*buf_++ = signal[1][sample];
|
||||
*buf_++ = signal[2][sample];
|
||||
*buf_++ = signal[3][sample];
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (1, 6)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf_++ = signal[0][sample];
|
||||
*buf_++ = signal[1][sample];
|
||||
*buf_++ = signal[2][sample];
|
||||
*buf_++ = signal[3][sample];
|
||||
*buf_++ = signal[4][sample];
|
||||
*buf_++ = signal[5][sample];
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (1, 8)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf_++ = signal[0][sample];
|
||||
*buf_++ = signal[1][sample];
|
||||
*buf_++ = signal[2][sample];
|
||||
*buf_++ = signal[3][sample];
|
||||
*buf_++ = signal[4][sample];
|
||||
*buf_++ = signal[5][sample];
|
||||
*buf_++ = signal[6][sample];
|
||||
*buf_++ = signal[7][sample];
|
||||
}
|
||||
return;
|
||||
|
||||
/* Two bytes per sample. */
|
||||
case (BYTES_CHANNEL_SELECTOR (2, 1)):
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
*buf16++ = H2LE_16(signal[0][sample]);
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (2, 2)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf16++ = H2LE_16(signal[0][sample]);
|
||||
*buf16++ = H2LE_16(signal[1][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (2, 4)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf16++ = H2LE_16(signal[0][sample]);
|
||||
*buf16++ = H2LE_16(signal[1][sample]);
|
||||
*buf16++ = H2LE_16(signal[2][sample]);
|
||||
*buf16++ = H2LE_16(signal[3][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (2, 6)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf16++ = H2LE_16(signal[0][sample]);
|
||||
*buf16++ = H2LE_16(signal[1][sample]);
|
||||
*buf16++ = H2LE_16(signal[2][sample]);
|
||||
*buf16++ = H2LE_16(signal[3][sample]);
|
||||
*buf16++ = H2LE_16(signal[4][sample]);
|
||||
*buf16++ = H2LE_16(signal[5][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (2, 8)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf16++ = H2LE_16(signal[0][sample]);
|
||||
*buf16++ = H2LE_16(signal[1][sample]);
|
||||
*buf16++ = H2LE_16(signal[2][sample]);
|
||||
*buf16++ = H2LE_16(signal[3][sample]);
|
||||
*buf16++ = H2LE_16(signal[4][sample]);
|
||||
*buf16++ = H2LE_16(signal[5][sample]);
|
||||
*buf16++ = H2LE_16(signal[6][sample]);
|
||||
*buf16++ = H2LE_16(signal[7][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
/* Three bytes per sample. */
|
||||
case (BYTES_CHANNEL_SELECTOR (3, 1)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
a_word = signal[0][sample];
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (3, 2)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
a_word = signal[0][sample];
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
a_word = signal[1][sample];
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
return;
|
||||
|
||||
/* Four bytes per sample. */
|
||||
case (BYTES_CHANNEL_SELECTOR (4, 1)):
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
*buf32++ = H2LE_32(signal[0][sample]);
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (4, 2)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf32++ = H2LE_32(signal[0][sample]);
|
||||
*buf32++ = H2LE_32(signal[1][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (4, 4)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf32++ = H2LE_32(signal[0][sample]);
|
||||
*buf32++ = H2LE_32(signal[1][sample]);
|
||||
*buf32++ = H2LE_32(signal[2][sample]);
|
||||
*buf32++ = H2LE_32(signal[3][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (4, 6)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf32++ = H2LE_32(signal[0][sample]);
|
||||
*buf32++ = H2LE_32(signal[1][sample]);
|
||||
*buf32++ = H2LE_32(signal[2][sample]);
|
||||
*buf32++ = H2LE_32(signal[3][sample]);
|
||||
*buf32++ = H2LE_32(signal[4][sample]);
|
||||
*buf32++ = H2LE_32(signal[5][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
case (BYTES_CHANNEL_SELECTOR (4, 8)):
|
||||
for (sample = 0; sample < samples; sample++) {
|
||||
*buf32++ = H2LE_32(signal[0][sample]);
|
||||
*buf32++ = H2LE_32(signal[1][sample]);
|
||||
*buf32++ = H2LE_32(signal[2][sample]);
|
||||
*buf32++ = H2LE_32(signal[3][sample]);
|
||||
*buf32++ = H2LE_32(signal[4][sample]);
|
||||
*buf32++ = H2LE_32(signal[5][sample]);
|
||||
*buf32++ = H2LE_32(signal[6][sample]);
|
||||
*buf32++ = H2LE_32(signal[7][sample]);
|
||||
}
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* General version. */
|
||||
switch (bytes_per_sample) {
|
||||
case 1:
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
for (channel = 0; channel < channels; channel++)
|
||||
*buf_++ = signal[channel][sample];
|
||||
return;
|
||||
|
||||
case 2:
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
for (channel = 0; channel < channels; channel++)
|
||||
*buf16++ = H2LE_16(signal[channel][sample]);
|
||||
return;
|
||||
|
||||
case 3:
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
for (channel = 0; channel < channels; channel++) {
|
||||
a_word = signal[channel][sample];
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
return;
|
||||
|
||||
case 4:
|
||||
for (sample = 0; sample < samples; sample++)
|
||||
for (channel = 0; channel < channels; channel++)
|
||||
*buf32++ = H2LE_32(signal[channel][sample]);
|
||||
return;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the incoming audio signal to a byte stream and FLAC__MD5Update it.
|
||||
*/
|
||||
FLAC__bool FLAC__MD5Accumulate(FLAC__MD5Context *ctx, const FLAC__int32 * const signal[], uint32_t channels, uint32_t samples, uint32_t bytes_per_sample)
|
||||
{
|
||||
const size_t bytes_needed = (size_t)channels * (size_t)samples * (size_t)bytes_per_sample;
|
||||
|
||||
/* overflow check */
|
||||
if ((size_t)channels > SIZE_MAX / (size_t)bytes_per_sample)
|
||||
return false;
|
||||
if ((size_t)channels * (size_t)bytes_per_sample > SIZE_MAX / (size_t)samples)
|
||||
return false;
|
||||
|
||||
if (ctx->capacity < bytes_needed) {
|
||||
if (0 == (ctx->internal_buf.p8 = (FLAC__byte*) safe_realloc_(ctx->internal_buf.p8, bytes_needed))) {
|
||||
if (0 == (ctx->internal_buf.p8 = (FLAC__byte*) safe_malloc_(bytes_needed))) {
|
||||
ctx->capacity = 0;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
ctx->capacity = bytes_needed;
|
||||
}
|
||||
|
||||
format_input_(&ctx->internal_buf, signal, channels, samples, bytes_per_sample);
|
||||
|
||||
FLAC__MD5Update(ctx, ctx->internal_buf.p8, bytes_needed);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,219 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "include/private/memory.h"
|
||||
#include "../assert.h"
|
||||
#include "../compat.h"
|
||||
#include "../alloc.h"
|
||||
|
||||
void *FLAC__memory_alloc_aligned(size_t bytes, void **aligned_address)
|
||||
{
|
||||
void *x;
|
||||
|
||||
FLAC__ASSERT(0 != aligned_address);
|
||||
|
||||
#ifdef FLAC__ALIGN_MALLOC_DATA
|
||||
/* align on 32-byte (256-bit) boundary */
|
||||
x = safe_malloc_add_2op_(bytes, /*+*/31L);
|
||||
*aligned_address = (void*)(((uintptr_t)x + 31L) & -32L);
|
||||
#else
|
||||
x = safe_malloc_(bytes);
|
||||
*aligned_address = x;
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_int32_array(size_t elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer)
|
||||
{
|
||||
FLAC__int32 *pu; /* unaligned pointer */
|
||||
union { /* union needed to comply with C99 pointer aliasing rules */
|
||||
FLAC__int32 *pa; /* aligned pointer */
|
||||
void *pv; /* aligned pointer alias */
|
||||
} u;
|
||||
|
||||
FLAC__ASSERT(elements > 0);
|
||||
FLAC__ASSERT(0 != unaligned_pointer);
|
||||
FLAC__ASSERT(0 != aligned_pointer);
|
||||
FLAC__ASSERT(unaligned_pointer != aligned_pointer);
|
||||
|
||||
if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (FLAC__int32*) FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
|
||||
if(0 == pu) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(*unaligned_pointer != 0)
|
||||
free(*unaligned_pointer);
|
||||
*unaligned_pointer = pu;
|
||||
*aligned_pointer = u.pa;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_uint32_array(size_t elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer)
|
||||
{
|
||||
FLAC__uint32 *pu; /* unaligned pointer */
|
||||
union { /* union needed to comply with C99 pointer aliasing rules */
|
||||
FLAC__uint32 *pa; /* aligned pointer */
|
||||
void *pv; /* aligned pointer alias */
|
||||
} u;
|
||||
|
||||
FLAC__ASSERT(elements > 0);
|
||||
FLAC__ASSERT(0 != unaligned_pointer);
|
||||
FLAC__ASSERT(0 != aligned_pointer);
|
||||
FLAC__ASSERT(unaligned_pointer != aligned_pointer);
|
||||
|
||||
if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (FLAC__uint32*) FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
|
||||
if(0 == pu) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(*unaligned_pointer != 0)
|
||||
free(*unaligned_pointer);
|
||||
*unaligned_pointer = pu;
|
||||
*aligned_pointer = u.pa;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_int64_array(size_t elements, FLAC__int64 **unaligned_pointer, FLAC__int64 **aligned_pointer)
|
||||
{
|
||||
FLAC__int64 *pu; /* unaligned pointer */
|
||||
union { /* union needed to comply with C99 pointer aliasing rules */
|
||||
FLAC__int64 *pa; /* aligned pointer */
|
||||
void *pv; /* aligned pointer alias */
|
||||
} u;
|
||||
|
||||
FLAC__ASSERT(elements > 0);
|
||||
FLAC__ASSERT(0 != unaligned_pointer);
|
||||
FLAC__ASSERT(0 != aligned_pointer);
|
||||
FLAC__ASSERT(unaligned_pointer != aligned_pointer);
|
||||
|
||||
if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (FLAC__int64*) FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
|
||||
if(0 == pu) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(*unaligned_pointer != 0)
|
||||
free(*unaligned_pointer);
|
||||
*unaligned_pointer = pu;
|
||||
*aligned_pointer = u.pa;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_uint64_array(size_t elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer)
|
||||
{
|
||||
FLAC__uint64 *pu; /* unaligned pointer */
|
||||
union { /* union needed to comply with C99 pointer aliasing rules */
|
||||
FLAC__uint64 *pa; /* aligned pointer */
|
||||
void *pv; /* aligned pointer alias */
|
||||
} u;
|
||||
|
||||
FLAC__ASSERT(elements > 0);
|
||||
FLAC__ASSERT(0 != unaligned_pointer);
|
||||
FLAC__ASSERT(0 != aligned_pointer);
|
||||
FLAC__ASSERT(unaligned_pointer != aligned_pointer);
|
||||
|
||||
if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (FLAC__uint64*) FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
|
||||
if(0 == pu) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(*unaligned_pointer != 0)
|
||||
free(*unaligned_pointer);
|
||||
*unaligned_pointer = pu;
|
||||
*aligned_pointer = u.pa;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_real_array(size_t elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer)
|
||||
{
|
||||
FLAC__real *pu; /* unaligned pointer */
|
||||
union { /* union needed to comply with C99 pointer aliasing rules */
|
||||
FLAC__real *pa; /* aligned pointer */
|
||||
void *pv; /* aligned pointer alias */
|
||||
} u;
|
||||
|
||||
FLAC__ASSERT(elements > 0);
|
||||
FLAC__ASSERT(0 != unaligned_pointer);
|
||||
FLAC__ASSERT(0 != aligned_pointer);
|
||||
FLAC__ASSERT(unaligned_pointer != aligned_pointer);
|
||||
|
||||
if(elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (FLAC__real*) FLAC__memory_alloc_aligned(sizeof(*pu) * elements, &u.pv);
|
||||
if(0 == pu) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(*unaligned_pointer != 0)
|
||||
free(*unaligned_pointer);
|
||||
*unaligned_pointer = pu;
|
||||
*aligned_pointer = u.pa;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void *safe_malloc_mul_2op_p(size_t size1, size_t size2)
|
||||
{
|
||||
if(!size1 || !size2)
|
||||
return malloc(1); /* malloc(0) is undefined; FLAC src convention is to always allocate */
|
||||
if(size1 > SIZE_MAX / size2)
|
||||
return 0;
|
||||
return malloc(size1*size2);
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
+594
@@ -0,0 +1,594 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h> /* for strlen() */
|
||||
#include "include/private/stream_encoder_framing.h"
|
||||
#include "include/private/crc.h"
|
||||
#include "../assert.h"
|
||||
#include "../compat.h"
|
||||
|
||||
static FLAC__bool add_entropy_coding_method_(FLAC__BitWriter *bw, const FLAC__EntropyCodingMethod *method);
|
||||
static FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 residual[], const uint32_t residual_samples, const uint32_t predictor_order, const uint32_t rice_parameters[], const uint32_t raw_bits[], const uint32_t partition_order, const FLAC__bool is_extended);
|
||||
|
||||
FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw, FLAC__bool update_vendor_string)
|
||||
{
|
||||
uint32_t i, j, metadata_length;
|
||||
const uint32_t vendor_string_length = (uint32_t)strlen(FLAC__VENDOR_STRING);
|
||||
const uint32_t start_bits = FLAC__bitwriter_get_input_bits_unconsumed(bw);
|
||||
|
||||
FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN))
|
||||
return false;
|
||||
|
||||
/*
|
||||
* First, for VORBIS_COMMENTs, adjust the length to reflect our vendor string
|
||||
*/
|
||||
metadata_length = metadata->length;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT && update_vendor_string) {
|
||||
FLAC__ASSERT(metadata->data.vorbis_comment.vendor_string.length == 0 || 0 != metadata->data.vorbis_comment.vendor_string.entry);
|
||||
metadata_length -= metadata->data.vorbis_comment.vendor_string.length;
|
||||
metadata_length += vendor_string_length;
|
||||
}
|
||||
FLAC__ASSERT(metadata_length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
|
||||
/* double protection */
|
||||
if(metadata_length >= (1u << FLAC__STREAM_METADATA_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata_length, FLAC__STREAM_METADATA_LENGTH_LEN))
|
||||
return false;
|
||||
|
||||
switch(metadata->type) {
|
||||
case FLAC__METADATA_TYPE_STREAMINFO:
|
||||
FLAC__ASSERT(metadata->data.stream_info.min_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.max_blocksize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_blocksize, FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.min_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.min_framesize, FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.max_framesize < (1u << FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.max_framesize, FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(FLAC__format_sample_rate_is_valid(metadata->data.stream_info.sample_rate));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.sample_rate, FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.channels > 0);
|
||||
FLAC__ASSERT(metadata->data.stream_info.channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.channels-1, FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(metadata->data.stream_info.bits_per_sample > 0);
|
||||
FLAC__ASSERT(metadata->data.stream_info.bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.stream_info.bits_per_sample-1, FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN))
|
||||
return false;
|
||||
if(metadata->data.stream_info.total_samples >= (FLAC__U64L(1) << FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN)){
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, 0, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
|
||||
return false;
|
||||
}else{
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.stream_info.total_samples, FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN))
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.stream_info.md5sum, 16))
|
||||
return false;
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_PADDING:
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, metadata->length * 8))
|
||||
return false;
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_APPLICATION:
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.id, FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.application.data, metadata->length - (FLAC__STREAM_METADATA_APPLICATION_ID_LEN / 8)))
|
||||
return false;
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_SEEKTABLE:
|
||||
for(i = 0; i < metadata->data.seek_table.num_points; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].sample_number, FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.seek_table.points[i].stream_offset, FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.seek_table.points[i].frame_samples, FLAC__STREAM_METADATA_SEEKPOINT_FRAME_SAMPLES_LEN))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_VORBIS_COMMENT:
|
||||
if(update_vendor_string) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, vendor_string_length))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)FLAC__VENDOR_STRING, vendor_string_length))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.vendor_string.length))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.vorbis_comment.vendor_string.entry, metadata->data.vorbis_comment.vendor_string.length))
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.num_comments))
|
||||
return false;
|
||||
for(i = 0; i < metadata->data.vorbis_comment.num_comments; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32_little_endian(bw, metadata->data.vorbis_comment.comments[i].length))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.vorbis_comment.comments[i].entry, metadata->data.vorbis_comment.comments[i].length))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_CUESHEET:
|
||||
FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN % 8 == 0);
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.cue_sheet.media_catalog_number, FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN/8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, metadata->data.cue_sheet.lead_in, FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.is_cd? 1 : 0, FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.cue_sheet.num_tracks, FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN))
|
||||
return false;
|
||||
for(i = 0; i < metadata->data.cue_sheet.num_tracks; i++) {
|
||||
const FLAC__StreamMetadata_CueSheet_Track *track = metadata->data.cue_sheet.tracks + i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, track->offset, FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->number, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN))
|
||||
return false;
|
||||
FLAC__ASSERT(FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN % 8 == 0);
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)track->isrc, FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN/8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->type, FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->pre_emphasis, FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, track->num_indices, FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN))
|
||||
return false;
|
||||
for(j = 0; j < track->num_indices; j++) {
|
||||
const FLAC__StreamMetadata_CueSheet_Index *indx = track->indices + j;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, indx->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, indx->number, FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_zeroes(bw, FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case FLAC__METADATA_TYPE_PICTURE:
|
||||
{
|
||||
size_t len;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.type, FLAC__STREAM_METADATA_PICTURE_TYPE_LEN))
|
||||
return false;
|
||||
len = strlen(metadata->data.picture.mime_type);
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, (const FLAC__byte*)metadata->data.picture.mime_type, len))
|
||||
return false;
|
||||
len = strlen((const char *)metadata->data.picture.description);
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, len, FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.description, len))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.width, FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.height, FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.depth, FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.colors, FLAC__STREAM_METADATA_PICTURE_COLORS_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, metadata->data.picture.data_length, FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.picture.data, metadata->data.picture.data_length))
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if(!FLAC__bitwriter_write_byte_block(bw, metadata->data.unknown.data, metadata->length))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Now check whether metadata block length was correct */
|
||||
{
|
||||
uint32_t length_in_bits = FLAC__bitwriter_get_input_bits_unconsumed(bw);
|
||||
if(length_in_bits < start_bits)
|
||||
return false;
|
||||
length_in_bits -= start_bits;
|
||||
if(length_in_bits % 8 != 0 || length_in_bits != (metadata_length*8+32))
|
||||
return false;
|
||||
}
|
||||
|
||||
FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw)
|
||||
{
|
||||
uint32_t u, blocksize_hint, sample_rate_hint;
|
||||
FLAC__byte crc;
|
||||
|
||||
FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__FRAME_HEADER_SYNC, FLAC__FRAME_HEADER_SYNC_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 0, FLAC__FRAME_HEADER_RESERVED_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (header->number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER)? 0 : 1, FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(header->blocksize > 0 && header->blocksize <= FLAC__MAX_BLOCK_SIZE);
|
||||
/* when this assertion holds true, any legal blocksize can be expressed in the frame header */
|
||||
FLAC__ASSERT(FLAC__MAX_BLOCK_SIZE <= 65535u);
|
||||
blocksize_hint = 0;
|
||||
switch(header->blocksize) {
|
||||
case 192: u = 1; break;
|
||||
case 576: u = 2; break;
|
||||
case 1152: u = 3; break;
|
||||
case 2304: u = 4; break;
|
||||
case 4608: u = 5; break;
|
||||
case 256: u = 8; break;
|
||||
case 512: u = 9; break;
|
||||
case 1024: u = 10; break;
|
||||
case 2048: u = 11; break;
|
||||
case 4096: u = 12; break;
|
||||
case 8192: u = 13; break;
|
||||
case 16384: u = 14; break;
|
||||
case 32768: u = 15; break;
|
||||
default:
|
||||
if(header->blocksize <= 0x100)
|
||||
blocksize_hint = u = 6;
|
||||
else
|
||||
blocksize_hint = u = 7;
|
||||
break;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(FLAC__format_sample_rate_is_valid(header->sample_rate));
|
||||
sample_rate_hint = 0;
|
||||
switch(header->sample_rate) {
|
||||
case 88200: u = 1; break;
|
||||
case 176400: u = 2; break;
|
||||
case 192000: u = 3; break;
|
||||
case 8000: u = 4; break;
|
||||
case 16000: u = 5; break;
|
||||
case 22050: u = 6; break;
|
||||
case 24000: u = 7; break;
|
||||
case 32000: u = 8; break;
|
||||
case 44100: u = 9; break;
|
||||
case 48000: u = 10; break;
|
||||
case 96000: u = 11; break;
|
||||
default:
|
||||
if(header->sample_rate <= 255000 && header->sample_rate % 1000 == 0)
|
||||
sample_rate_hint = u = 12;
|
||||
else if(header->sample_rate <= 655350 && header->sample_rate % 10 == 0)
|
||||
sample_rate_hint = u = 14;
|
||||
else if(header->sample_rate <= 0xffff)
|
||||
sample_rate_hint = u = 13;
|
||||
else
|
||||
u = 0;
|
||||
break;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_SAMPLE_RATE_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(header->channels > 0 && header->channels <= (1u << FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN) && header->channels <= FLAC__MAX_CHANNELS);
|
||||
switch(header->channel_assignment) {
|
||||
case FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT:
|
||||
u = header->channels - 1;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE:
|
||||
FLAC__ASSERT(header->channels == 2);
|
||||
u = 8;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
|
||||
FLAC__ASSERT(header->channels == 2);
|
||||
u = 9;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
|
||||
FLAC__ASSERT(header->channels == 2);
|
||||
u = 10;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN))
|
||||
return false;
|
||||
|
||||
FLAC__ASSERT(header->bits_per_sample > 0 && header->bits_per_sample <= (1u << FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN));
|
||||
switch(header->bits_per_sample) {
|
||||
case 8 : u = 1; break;
|
||||
case 12: u = 2; break;
|
||||
case 16: u = 4; break;
|
||||
case 20: u = 5; break;
|
||||
case 24: u = 6; break;
|
||||
case 32: u = 7; break;
|
||||
default: u = 0; break;
|
||||
}
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, u, FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, 0, FLAC__FRAME_HEADER_ZERO_PAD_LEN))
|
||||
return false;
|
||||
|
||||
if(header->number_type == FLAC__FRAME_NUMBER_TYPE_FRAME_NUMBER) {
|
||||
if(!FLAC__bitwriter_write_utf8_uint32(bw, header->number.frame_number))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_utf8_uint64(bw, header->number.sample_number))
|
||||
return false;
|
||||
}
|
||||
|
||||
if(blocksize_hint)
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->blocksize-1, (blocksize_hint==6)? 8:16))
|
||||
return false;
|
||||
|
||||
switch(sample_rate_hint) {
|
||||
case 12:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate / 1000, 8))
|
||||
return false;
|
||||
break;
|
||||
case 13:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate, 16))
|
||||
return false;
|
||||
break;
|
||||
case 14:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, header->sample_rate / 10, 16))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* write the CRC */
|
||||
if(!FLAC__bitwriter_get_write_crc8(bw, &crc))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, crc, FLAC__FRAME_HEADER_CRC_LEN))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__bool ok;
|
||||
|
||||
ok =
|
||||
FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN) &&
|
||||
(wasted_bits? FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1) : true) &&
|
||||
FLAC__bitwriter_write_raw_int64(bw, subframe->value, subframe_bps)
|
||||
;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, uint32_t residual_samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK | (subframe->order<<1) | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN))
|
||||
return false;
|
||||
if(wasted_bits)
|
||||
if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < subframe->order; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int64(bw, subframe->warmup[i], subframe_bps))
|
||||
return false;
|
||||
|
||||
if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method))
|
||||
return false;
|
||||
switch(subframe->entropy_coding_method.type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
|
||||
if(!add_residual_partitioned_rice_(
|
||||
bw,
|
||||
subframe->residual,
|
||||
residual_samples,
|
||||
subframe->order,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->parameters,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.order,
|
||||
/*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2
|
||||
))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, uint32_t residual_samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_LPC_BYTE_ALIGNED_MASK | ((subframe->order-1)<<1) | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN))
|
||||
return false;
|
||||
if(wasted_bits)
|
||||
if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < subframe->order; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int64(bw, subframe->warmup[i], subframe_bps))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, subframe->qlp_coeff_precision-1, FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, subframe->quantization_level, FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN))
|
||||
return false;
|
||||
for(i = 0; i < subframe->order; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, subframe->qlp_coeff[i], subframe->qlp_coeff_precision))
|
||||
return false;
|
||||
|
||||
if(!add_entropy_coding_method_(bw, &subframe->entropy_coding_method))
|
||||
return false;
|
||||
switch(subframe->entropy_coding_method.type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
|
||||
if(!add_residual_partitioned_rice_(
|
||||
bw,
|
||||
subframe->residual,
|
||||
residual_samples,
|
||||
subframe->order,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->parameters,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.contents->raw_bits,
|
||||
subframe->entropy_coding_method.data.partitioned_rice.order,
|
||||
/*is_extended=*/subframe->entropy_coding_method.type == FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2
|
||||
))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, uint32_t samples, uint32_t subframe_bps, uint32_t wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK | (wasted_bits? 1:0), FLAC__SUBFRAME_ZERO_PAD_LEN + FLAC__SUBFRAME_TYPE_LEN + FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN))
|
||||
return false;
|
||||
if(wasted_bits)
|
||||
if(!FLAC__bitwriter_write_unary_unsigned(bw, wasted_bits-1))
|
||||
return false;
|
||||
|
||||
if(subframe->data_type == FLAC__VERBATIM_SUBFRAME_DATA_TYPE_INT32) {
|
||||
const FLAC__int32 *signal = subframe->data.int32;
|
||||
|
||||
FLAC__ASSERT(subframe_bps < 33);
|
||||
|
||||
for(i = 0; i < samples; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, signal[i], subframe_bps))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
const FLAC__int64 *signal = subframe->data.int64;
|
||||
|
||||
FLAC__ASSERT(subframe_bps == 33);
|
||||
|
||||
for(i = 0; i < samples; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int64(bw, (FLAC__int64)signal[i], subframe_bps))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool add_entropy_coding_method_(FLAC__BitWriter *bw, const FLAC__EntropyCodingMethod *method)
|
||||
{
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, method->type, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN))
|
||||
return false;
|
||||
switch(method->type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2:
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, method->data.partitioned_rice.order, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool add_residual_partitioned_rice_(FLAC__BitWriter *bw, const FLAC__int32 residual[], const uint32_t residual_samples, const uint32_t predictor_order, const uint32_t rice_parameters[], const uint32_t raw_bits[], const uint32_t partition_order, const FLAC__bool is_extended)
|
||||
{
|
||||
const uint32_t plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
|
||||
const uint32_t pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
|
||||
|
||||
if(partition_order == 0) {
|
||||
uint32_t i;
|
||||
|
||||
if(raw_bits[0] == 0) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, rice_parameters[0], plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_rice_signed_block(bw, residual, residual_samples, rice_parameters[0]))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
FLAC__ASSERT(rice_parameters[0] == 0);
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pesc, plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, raw_bits[0], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN))
|
||||
return false;
|
||||
for(i = 0; i < residual_samples; i++) {
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, residual[i], raw_bits[0]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
uint32_t i, j, k = 0, k_last = 0;
|
||||
uint32_t partition_samples;
|
||||
const uint32_t default_partition_samples = (residual_samples+predictor_order) >> partition_order;
|
||||
for(i = 0; i < (1u<<partition_order); i++) {
|
||||
partition_samples = default_partition_samples;
|
||||
if(i == 0)
|
||||
partition_samples -= predictor_order;
|
||||
k += partition_samples;
|
||||
if(raw_bits[i] == 0) {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, rice_parameters[i], plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_rice_signed_block(bw, residual+k_last, k-k_last, rice_parameters[i]))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, pesc, plen))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, raw_bits[i], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN))
|
||||
return false;
|
||||
for(j = k_last; j < k; j++) {
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, residual[j], raw_bits[i]))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
k_last = k;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,308 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2006-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include "../compat.h"
|
||||
#include "../assert.h"
|
||||
#include "../format.h"
|
||||
#include "include/private/window.h"
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
// silence 25 MSVC warnings 'conversion from 'double' to 'float', possible loss of data'
|
||||
#pragma warning ( disable : 4244 )
|
||||
#endif
|
||||
|
||||
void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
if (L & 1) {
|
||||
for (n = 0; n <= N/2; n++)
|
||||
window[n] = 2.0f * n / (float)N;
|
||||
for (; n <= N; n++)
|
||||
window[n] = 2.0f - 2.0f * n / (float)N;
|
||||
}
|
||||
else {
|
||||
for (n = 0; n <= L/2-1; n++)
|
||||
window[n] = 2.0f * n / (float)N;
|
||||
for (; n <= N; n++)
|
||||
window[n] = 2.0f - 2.0f * n / (float)N;
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_bartlett_hann(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.62f - 0.48f * fabsf((float)n/(float)N-0.5f) - 0.38f * cosf(2.0f * M_PI * ((float)n/(float)N)));
|
||||
}
|
||||
|
||||
void FLAC__window_blackman(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.42f - 0.5f * cosf(2.0f * M_PI * n / N) + 0.08f * cosf(4.0f * M_PI * n / N));
|
||||
}
|
||||
|
||||
/* 4-term -92dB side-lobe */
|
||||
void FLAC__window_blackman_harris_4term_92db_sidelobe(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n <= N; n++)
|
||||
window[n] = (FLAC__real)(0.35875f - 0.48829f * cosf(2.0f * M_PI * n / N) + 0.14128f * cosf(4.0f * M_PI * n / N) - 0.01168f * cosf(6.0f * M_PI * n / N));
|
||||
}
|
||||
|
||||
void FLAC__window_connes(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
const double N2 = (double)N / 2.;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n <= N; n++) {
|
||||
double k = ((double)n - N2) / N2;
|
||||
k = 1.0f - k * k;
|
||||
window[n] = (FLAC__real)(k * k);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_flattop(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.21557895f - 0.41663158f * cosf(2.0f * M_PI * n / N) + 0.277263158f * cosf(4.0f * M_PI * n / N) - 0.083578947f * cosf(6.0f * M_PI * n / N) + 0.006947368f * cosf(8.0f * M_PI * n / N));
|
||||
}
|
||||
|
||||
void FLAC__window_gauss(FLAC__real *window, const FLAC__int32 L, const FLAC__real stddev)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
const double N2 = (double)N / 2.;
|
||||
FLAC__int32 n;
|
||||
|
||||
if(!(stddev > 0.0f && stddev <= 0.5f))
|
||||
/* stddev is not between 0 and 0.5, might be NaN.
|
||||
* Default to 0.5 */
|
||||
FLAC__window_gauss(window, L, 0.25f);
|
||||
else {
|
||||
for (n = 0; n <= N; n++) {
|
||||
const double k = ((double)n - N2) / (stddev * N2);
|
||||
window[n] = (FLAC__real)exp(-0.5f * k * k);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_hamming(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.54f - 0.46f * cosf(2.0f * M_PI * n / N));
|
||||
}
|
||||
|
||||
void FLAC__window_hann(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(2.0f * M_PI * n / N));
|
||||
}
|
||||
|
||||
void FLAC__window_kaiser_bessel(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.402f - 0.498f * cosf(2.0f * M_PI * n / N) + 0.098f * cosf(4.0f * M_PI * n / N) - 0.001f * cosf(6.0f * M_PI * n / N));
|
||||
}
|
||||
|
||||
void FLAC__window_nuttall(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = (FLAC__real)(0.3635819f - 0.4891775f*cosf(2.0f*M_PI*n/N) + 0.1365995f*cosf(4.0f*M_PI*n/N) - 0.0106411f*cosf(6.0f*M_PI*n/N));
|
||||
}
|
||||
|
||||
void FLAC__window_rectangle(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n < L; n++)
|
||||
window[n] = 1.0f;
|
||||
}
|
||||
|
||||
void FLAC__window_triangle(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
FLAC__int32 n;
|
||||
|
||||
if (L & 1) {
|
||||
for (n = 1; n <= (L+1)/2; n++)
|
||||
window[n-1] = 2.0f * n / ((float)L + 1.0f);
|
||||
for (; n <= L; n++)
|
||||
window[n-1] = (float)(2 * (L - n + 1)) / ((float)L + 1.0f);
|
||||
}
|
||||
else {
|
||||
for (n = 1; n <= L/2; n++)
|
||||
window[n-1] = 2.0f * n / ((float)L + 1.0f);
|
||||
for (; n <= L; n++)
|
||||
window[n-1] = (float)(2 * (L - n + 1)) / ((float)L + 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p)
|
||||
{
|
||||
if (p <= 0.0)
|
||||
FLAC__window_rectangle(window, L);
|
||||
else if (p >= 1.0)
|
||||
FLAC__window_hann(window, L);
|
||||
else if (!(p > 0.0f && p < 1.0f))
|
||||
/* p is not between 0 and 1, probably NaN.
|
||||
* Default to 0.5 */
|
||||
FLAC__window_tukey(window, L, 0.5f);
|
||||
else {
|
||||
const FLAC__int32 Np = (FLAC__int32)(p / 2.0f * L) - 1;
|
||||
FLAC__int32 n;
|
||||
/* start with rectangle... */
|
||||
FLAC__window_rectangle(window, L);
|
||||
/* ...replace ends with hann */
|
||||
if (Np > 0) {
|
||||
for (n = 0; n <= Np; n++) {
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * n / Np));
|
||||
window[L-Np-1+n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * (n+Np) / Np));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_partial_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end)
|
||||
{
|
||||
const FLAC__int32 start_n = (FLAC__int32)(start * L);
|
||||
const FLAC__int32 end_n = (FLAC__int32)(end * L);
|
||||
const FLAC__int32 N = end_n - start_n;
|
||||
FLAC__int32 Np, n, i;
|
||||
|
||||
if (p <= 0.0f)
|
||||
FLAC__window_partial_tukey(window, L, 0.05f, start, end);
|
||||
else if (p >= 1.0f)
|
||||
FLAC__window_partial_tukey(window, L, 0.95f, start, end);
|
||||
else if (!(p > 0.0f && p < 1.0f))
|
||||
/* p is not between 0 and 1, probably NaN.
|
||||
* Default to 0.5 */
|
||||
FLAC__window_partial_tukey(window, L, 0.5f, start, end);
|
||||
else {
|
||||
|
||||
Np = (FLAC__int32)(p / 2.0f * N);
|
||||
|
||||
for (n = 0; n < start_n && n < L; n++)
|
||||
window[n] = 0.0f;
|
||||
for (i = 1; n < (start_n+Np) && n < L; n++, i++)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * i / Np));
|
||||
for (; n < (end_n-Np) && n < L; n++)
|
||||
window[n] = 1.0f;
|
||||
for (i = Np; n < end_n && n < L; n++, i--)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * i / Np));
|
||||
for (; n < L; n++)
|
||||
window[n] = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_punchout_tukey(FLAC__real *window, const FLAC__int32 L, const FLAC__real p, const FLAC__real start, const FLAC__real end)
|
||||
{
|
||||
const FLAC__int32 start_n = (FLAC__int32)(start * L);
|
||||
const FLAC__int32 end_n = (FLAC__int32)(end * L);
|
||||
FLAC__int32 Ns, Ne, n, i;
|
||||
|
||||
if (p <= 0.0f)
|
||||
FLAC__window_punchout_tukey(window, L, 0.05f, start, end);
|
||||
else if (p >= 1.0f)
|
||||
FLAC__window_punchout_tukey(window, L, 0.95f, start, end);
|
||||
else if (!(p > 0.0f && p < 1.0f))
|
||||
/* p is not between 0 and 1, probably NaN.
|
||||
* Default to 0.5 */
|
||||
FLAC__window_punchout_tukey(window, L, 0.5f, start, end);
|
||||
else {
|
||||
|
||||
Ns = (FLAC__int32)(p / 2.0f * start_n);
|
||||
Ne = (FLAC__int32)(p / 2.0f * (L - end_n));
|
||||
|
||||
for (n = 0, i = 1; n < Ns && n < L; n++, i++)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * i / Ns));
|
||||
for (; n < start_n-Ns && n < L; n++)
|
||||
window[n] = 1.0f;
|
||||
for (i = Ns; n < start_n && n < L; n++, i--)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * i / Ns));
|
||||
for (; n < end_n && n < L; n++)
|
||||
window[n] = 0.0f;
|
||||
for (i = 1; n < end_n+Ne && n < L; n++, i++)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * i / Ne));
|
||||
for (; n < L - (Ne) && n < L; n++)
|
||||
window[n] = 1.0f;
|
||||
for (i = Ne; n < L; n++, i--)
|
||||
window[n] = (FLAC__real)(0.5f - 0.5f * cosf(M_PI * i / Ne));
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__window_welch(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
const double N2 = (double)N / 2.;
|
||||
FLAC__int32 n;
|
||||
|
||||
for (n = 0; n <= N; n++) {
|
||||
const double k = ((double)n - N2) / N2;
|
||||
window[n] = (FLAC__real)(1.0f - k * k);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
#pragma warning ( default : 4244 )
|
||||
#endif
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ORDINALS_H
|
||||
#define FLAC__ORDINALS_H
|
||||
|
||||
/* This of course assumes C99 headers */
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef int8_t FLAC__int8;
|
||||
typedef uint8_t FLAC__uint8;
|
||||
|
||||
typedef int16_t FLAC__int16;
|
||||
typedef int32_t FLAC__int32;
|
||||
typedef int64_t FLAC__int64;
|
||||
typedef uint16_t FLAC__uint16;
|
||||
typedef uint32_t FLAC__uint32;
|
||||
typedef uint64_t FLAC__uint64;
|
||||
|
||||
typedef int FLAC__bool;
|
||||
|
||||
typedef FLAC__uint8 FLAC__byte;
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,54 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2013-2023 Xiph.Org Foundation
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of the Xiph.org Foundation nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__SHARE__PRIVATE_H
|
||||
#define FLAC__SHARE__PRIVATE_H
|
||||
|
||||
/*
|
||||
* Unpublished debug routines from libFLAC. This should not be used from any
|
||||
* client code other than code shipped with the FLAC sources.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_instruction_set(FLAC__StreamEncoder *encoder, int value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_constant_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_fixed_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_disable_verbatim_subframes(FLAC__StreamEncoder *encoder, FLAC__bool value);
|
||||
/*
|
||||
* The following two routines were intended as debug routines and are not
|
||||
* in the public headers, but SHOULD NOT CHANGE! It is known they are used
|
||||
* in some non-audio projects needing every last bit of performance.
|
||||
* See https://github.com/xiph/flac/issues/547 for details. These projects
|
||||
* provide their own prototypes, so changing the signature of these
|
||||
* functions would break building.
|
||||
*/
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_set_do_md5(FLAC__StreamEncoder *encoder, FLAC__bool value);
|
||||
FLAC_API FLAC__bool FLAC__stream_encoder_get_do_md5(const FLAC__StreamEncoder *encoder);
|
||||
|
||||
#endif /* FLAC__SHARE__PRIVATE_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and Writes AIFF format audio files.
|
||||
|
||||
@see AudioFormat
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API AiffAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an format object. */
|
||||
AiffAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~AiffAudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleOneShot;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleRootSet;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleRootNote;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleBeats;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleDenominator;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleNumerator;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleTag;
|
||||
/** Metadata property name used when reading a aiff file with a basc chunk. */
|
||||
static const char* const appleKey;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
|
||||
#if JUCE_MAC
|
||||
bool canHandleFile (const File& fileToTest) override;
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
MemoryMappedAudioFormatReader* createMemoryMappedReader (const File&) override;
|
||||
MemoryMappedAudioFormatReader* createMemoryMappedReader (FileInputStream*) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AiffAudioFormat)
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,928 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
|
||||
#include <juce_audio_basics/native/juce_CoreAudioLayouts_mac.h>
|
||||
#include <juce_core/native/juce_CFHelpers_mac.h>
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
namespace
|
||||
{
|
||||
const char* const coreAudioFormatName = "CoreAudio supported file";
|
||||
|
||||
StringArray getStringInfo (AudioFilePropertyID property, UInt32 size, void* data)
|
||||
{
|
||||
CFObjectHolder<CFArrayRef> extensions;
|
||||
UInt32 sizeOfArray = sizeof (extensions.object);
|
||||
|
||||
const auto err = AudioFileGetGlobalInfo (property,
|
||||
size,
|
||||
data,
|
||||
&sizeOfArray,
|
||||
&extensions.object);
|
||||
|
||||
if (err != noErr)
|
||||
return {};
|
||||
|
||||
const auto numValues = CFArrayGetCount (extensions.object);
|
||||
|
||||
StringArray extensionsArray;
|
||||
|
||||
for (CFIndex i = 0; i < numValues; ++i)
|
||||
extensionsArray.add ("." + String::fromCFString ((CFStringRef) CFArrayGetValueAtIndex (extensions.object, i)));
|
||||
|
||||
return extensionsArray;
|
||||
}
|
||||
|
||||
StringArray findFileExtensionsForCoreAudioCodec (AudioFileTypeID type)
|
||||
{
|
||||
return getStringInfo (kAudioFileGlobalInfo_ExtensionsForType, sizeof (AudioFileTypeID), &type);
|
||||
}
|
||||
|
||||
StringArray findFileExtensionsForCoreAudioCodecs()
|
||||
{
|
||||
return getStringInfo (kAudioFileGlobalInfo_AllExtensions, 0, nullptr);
|
||||
}
|
||||
|
||||
static AudioFileTypeID toAudioFileTypeID (CoreAudioFormat::StreamKind kind)
|
||||
{
|
||||
using StreamKind = CoreAudioFormat::StreamKind;
|
||||
|
||||
switch (kind)
|
||||
{
|
||||
case StreamKind::kAiff: return kAudioFileAIFFType;
|
||||
case StreamKind::kAifc: return kAudioFileAIFCType;
|
||||
case StreamKind::kWave: return kAudioFileWAVEType;
|
||||
case StreamKind::kSoundDesigner2: return kAudioFileSoundDesigner2Type;
|
||||
case StreamKind::kNext: return kAudioFileNextType;
|
||||
case StreamKind::kMp3: return kAudioFileMP3Type;
|
||||
case StreamKind::kMp2: return kAudioFileMP2Type;
|
||||
case StreamKind::kMp1: return kAudioFileMP1Type;
|
||||
case StreamKind::kAc3: return kAudioFileAC3Type;
|
||||
case StreamKind::kAacAdts: return kAudioFileAAC_ADTSType;
|
||||
case StreamKind::kMpeg4: return kAudioFileMPEG4Type;
|
||||
case StreamKind::kM4a: return kAudioFileM4AType;
|
||||
case StreamKind::kM4b: return kAudioFileM4BType;
|
||||
case StreamKind::kCaf: return kAudioFileCAFType;
|
||||
case StreamKind::k3gp: return kAudioFile3GPType;
|
||||
case StreamKind::k3gp2: return kAudioFile3GP2Type;
|
||||
case StreamKind::kAmr: return kAudioFileAMRType;
|
||||
|
||||
case StreamKind::kNone: break;
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const char* const CoreAudioFormat::midiDataBase64 = "midiDataBase64";
|
||||
const char* const CoreAudioFormat::tempo = "tempo";
|
||||
const char* const CoreAudioFormat::timeSig = "time signature";
|
||||
const char* const CoreAudioFormat::keySig = "key signature";
|
||||
|
||||
//==============================================================================
|
||||
struct CoreAudioFormatMetatdata
|
||||
{
|
||||
static uint32 chunkName (const char* const name) noexcept { return ByteOrder::bigEndianInt (name); }
|
||||
|
||||
//==============================================================================
|
||||
struct FileHeader
|
||||
{
|
||||
FileHeader (InputStream& input)
|
||||
{
|
||||
fileType = (uint32) input.readIntBigEndian();
|
||||
fileVersion = (uint16) input.readShortBigEndian();
|
||||
fileFlags = (uint16) input.readShortBigEndian();
|
||||
}
|
||||
|
||||
uint32 fileType;
|
||||
uint16 fileVersion;
|
||||
uint16 fileFlags;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct ChunkHeader
|
||||
{
|
||||
ChunkHeader (InputStream& input)
|
||||
{
|
||||
chunkType = (uint32) input.readIntBigEndian();
|
||||
chunkSize = (int64) input.readInt64BigEndian();
|
||||
}
|
||||
|
||||
uint32 chunkType;
|
||||
int64 chunkSize;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct AudioDescriptionChunk
|
||||
{
|
||||
AudioDescriptionChunk (InputStream& input)
|
||||
{
|
||||
sampleRate = input.readDoubleBigEndian();
|
||||
formatID = (uint32) input.readIntBigEndian();
|
||||
formatFlags = (uint32) input.readIntBigEndian();
|
||||
bytesPerPacket = (uint32) input.readIntBigEndian();
|
||||
framesPerPacket = (uint32) input.readIntBigEndian();
|
||||
channelsPerFrame = (uint32) input.readIntBigEndian();
|
||||
bitsPerChannel = (uint32) input.readIntBigEndian();
|
||||
}
|
||||
|
||||
double sampleRate;
|
||||
uint32 formatID;
|
||||
uint32 formatFlags;
|
||||
uint32 bytesPerPacket;
|
||||
uint32 framesPerPacket;
|
||||
uint32 channelsPerFrame;
|
||||
uint32 bitsPerChannel;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static StringPairArray parseUserDefinedChunk (InputStream& input, int64 size)
|
||||
{
|
||||
StringPairArray infoStrings;
|
||||
auto originalPosition = input.getPosition();
|
||||
|
||||
uint8 uuid[16];
|
||||
input.read (uuid, sizeof (uuid));
|
||||
|
||||
if (memcmp (uuid, "\x29\x81\x92\x73\xB5\xBF\x4A\xEF\xB7\x8D\x62\xD1\xEF\x90\xBB\x2C", 16) == 0)
|
||||
{
|
||||
auto numEntries = (uint32) input.readIntBigEndian();
|
||||
|
||||
for (uint32 i = 0; i < numEntries && input.getPosition() < originalPosition + size; ++i)
|
||||
{
|
||||
String keyName = input.readString();
|
||||
infoStrings.set (keyName, input.readString());
|
||||
}
|
||||
}
|
||||
|
||||
input.setPosition (originalPosition + size);
|
||||
return infoStrings;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static StringPairArray parseMidiChunk (InputStream& input, int64 size)
|
||||
{
|
||||
auto originalPosition = input.getPosition();
|
||||
|
||||
MemoryBlock midiBlock;
|
||||
input.readIntoMemoryBlock (midiBlock, (ssize_t) size);
|
||||
MemoryInputStream midiInputStream (midiBlock, false);
|
||||
|
||||
StringPairArray midiMetadata;
|
||||
MidiFile midiFile;
|
||||
|
||||
if (midiFile.readFrom (midiInputStream))
|
||||
{
|
||||
midiMetadata.set (CoreAudioFormat::midiDataBase64, midiBlock.toBase64Encoding());
|
||||
|
||||
findTempoEvents (midiFile, midiMetadata);
|
||||
findTimeSigEvents (midiFile, midiMetadata);
|
||||
findKeySigEvents (midiFile, midiMetadata);
|
||||
}
|
||||
|
||||
input.setPosition (originalPosition + size);
|
||||
return midiMetadata;
|
||||
}
|
||||
|
||||
static void findTempoEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
|
||||
{
|
||||
MidiMessageSequence tempoEvents;
|
||||
midiFile.findAllTempoEvents (tempoEvents);
|
||||
|
||||
auto numTempoEvents = tempoEvents.getNumEvents();
|
||||
MemoryOutputStream tempoSequence;
|
||||
|
||||
for (int i = 0; i < numTempoEvents; ++i)
|
||||
{
|
||||
auto tempo = getTempoFromTempoMetaEvent (tempoEvents.getEventPointer (i));
|
||||
|
||||
if (tempo > 0.0)
|
||||
{
|
||||
if (i == 0)
|
||||
midiMetadata.set (CoreAudioFormat::tempo, String (tempo));
|
||||
|
||||
if (numTempoEvents > 1)
|
||||
tempoSequence << String (tempo) << ',' << tempoEvents.getEventTime (i) << ';';
|
||||
}
|
||||
}
|
||||
|
||||
if (tempoSequence.getDataSize() > 0)
|
||||
midiMetadata.set ("tempo sequence", tempoSequence.toUTF8());
|
||||
}
|
||||
|
||||
static double getTempoFromTempoMetaEvent (MidiMessageSequence::MidiEventHolder* holder)
|
||||
{
|
||||
if (holder != nullptr)
|
||||
{
|
||||
auto& midiMessage = holder->message;
|
||||
|
||||
if (midiMessage.isTempoMetaEvent())
|
||||
{
|
||||
auto tempoSecondsPerQuarterNote = midiMessage.getTempoSecondsPerQuarterNote();
|
||||
|
||||
if (tempoSecondsPerQuarterNote > 0.0)
|
||||
return 60.0 / tempoSecondsPerQuarterNote;
|
||||
}
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
static void findTimeSigEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
|
||||
{
|
||||
MidiMessageSequence timeSigEvents;
|
||||
midiFile.findAllTimeSigEvents (timeSigEvents);
|
||||
auto numTimeSigEvents = timeSigEvents.getNumEvents();
|
||||
|
||||
MemoryOutputStream timeSigSequence;
|
||||
|
||||
for (int i = 0; i < numTimeSigEvents; ++i)
|
||||
{
|
||||
int numerator, denominator;
|
||||
timeSigEvents.getEventPointer (i)->message.getTimeSignatureInfo (numerator, denominator);
|
||||
|
||||
String timeSigString;
|
||||
timeSigString << numerator << '/' << denominator;
|
||||
|
||||
if (i == 0)
|
||||
midiMetadata.set (CoreAudioFormat::timeSig, timeSigString);
|
||||
|
||||
if (numTimeSigEvents > 1)
|
||||
timeSigSequence << timeSigString << ',' << timeSigEvents.getEventTime (i) << ';';
|
||||
}
|
||||
|
||||
if (timeSigSequence.getDataSize() > 0)
|
||||
midiMetadata.set ("time signature sequence", timeSigSequence.toUTF8());
|
||||
}
|
||||
|
||||
static void findKeySigEvents (MidiFile& midiFile, StringPairArray& midiMetadata)
|
||||
{
|
||||
MidiMessageSequence keySigEvents;
|
||||
midiFile.findAllKeySigEvents (keySigEvents);
|
||||
auto numKeySigEvents = keySigEvents.getNumEvents();
|
||||
|
||||
MemoryOutputStream keySigSequence;
|
||||
|
||||
for (int i = 0; i < numKeySigEvents; ++i)
|
||||
{
|
||||
auto& message (keySigEvents.getEventPointer (i)->message);
|
||||
auto key = jlimit (0, 14, message.getKeySignatureNumberOfSharpsOrFlats() + 7);
|
||||
bool isMajor = message.isKeySignatureMajorKey();
|
||||
|
||||
static const char* majorKeys[] = { "Cb", "Gb", "Db", "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#" };
|
||||
static const char* minorKeys[] = { "Ab", "Eb", "Bb", "F", "C", "G", "D", "A", "E", "B", "F#", "C#", "G#", "D#", "A#" };
|
||||
|
||||
String keySigString (isMajor ? majorKeys[key]
|
||||
: minorKeys[key]);
|
||||
|
||||
if (! isMajor)
|
||||
keySigString << 'm';
|
||||
|
||||
if (i == 0)
|
||||
midiMetadata.set (CoreAudioFormat::keySig, keySigString);
|
||||
|
||||
if (numKeySigEvents > 1)
|
||||
keySigSequence << keySigString << ',' << keySigEvents.getEventTime (i) << ';';
|
||||
}
|
||||
|
||||
if (keySigSequence.getDataSize() > 0)
|
||||
midiMetadata.set ("key signature sequence", keySigSequence.toUTF8());
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static StringPairArray parseInformationChunk (InputStream& input)
|
||||
{
|
||||
StringPairArray infoStrings;
|
||||
auto numEntries = (uint32) input.readIntBigEndian();
|
||||
|
||||
for (uint32 i = 0; i < numEntries; ++i)
|
||||
infoStrings.set (input.readString(), input.readString());
|
||||
|
||||
return infoStrings;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static bool read (InputStream& input, StringPairArray& metadataValues)
|
||||
{
|
||||
auto originalPos = input.getPosition();
|
||||
|
||||
const FileHeader cafFileHeader (input);
|
||||
const bool isCafFile = cafFileHeader.fileType == chunkName ("caff");
|
||||
|
||||
if (isCafFile)
|
||||
{
|
||||
while (! input.isExhausted())
|
||||
{
|
||||
const ChunkHeader chunkHeader (input);
|
||||
|
||||
if (chunkHeader.chunkType == chunkName ("desc"))
|
||||
{
|
||||
AudioDescriptionChunk audioDescriptionChunk (input);
|
||||
}
|
||||
else if (chunkHeader.chunkType == chunkName ("uuid"))
|
||||
{
|
||||
metadataValues.addArray (parseUserDefinedChunk (input, chunkHeader.chunkSize));
|
||||
}
|
||||
else if (chunkHeader.chunkType == chunkName ("data"))
|
||||
{
|
||||
// -1 signifies an unknown data size so the data has to be at the
|
||||
// end of the file so we must have finished the header
|
||||
|
||||
if (chunkHeader.chunkSize == -1)
|
||||
break;
|
||||
|
||||
input.setPosition (input.getPosition() + chunkHeader.chunkSize);
|
||||
}
|
||||
else if (chunkHeader.chunkType == chunkName ("midi"))
|
||||
{
|
||||
metadataValues.addArray (parseMidiChunk (input, chunkHeader.chunkSize));
|
||||
}
|
||||
else if (chunkHeader.chunkType == chunkName ("info"))
|
||||
{
|
||||
metadataValues.addArray (parseInformationChunk (input));
|
||||
}
|
||||
else
|
||||
{
|
||||
// we aren't decoding this chunk yet so just skip over it
|
||||
input.setPosition (input.getPosition() + chunkHeader.chunkSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.setPosition (originalPos);
|
||||
|
||||
return isCafFile;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class CoreAudioReader final : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
using StreamKind = CoreAudioFormat::StreamKind;
|
||||
|
||||
CoreAudioReader (InputStream* inp, StreamKind streamKind)
|
||||
: AudioFormatReader (inp, coreAudioFormatName)
|
||||
{
|
||||
usesFloatingPointData = true;
|
||||
bitsPerSample = 32;
|
||||
|
||||
if (input != nullptr)
|
||||
CoreAudioFormatMetatdata::read (*input, metadataValues);
|
||||
|
||||
auto status = AudioFileOpenWithCallbacks (this,
|
||||
&readCallback,
|
||||
nullptr, // write needs to be null to avoid permissions errors
|
||||
&getSizeCallback,
|
||||
nullptr, // setSize needs to be null to avoid permissions errors
|
||||
toAudioFileTypeID (streamKind),
|
||||
&audioFileID);
|
||||
if (status == noErr)
|
||||
{
|
||||
status = ExtAudioFileWrapAudioFileID (audioFileID, false, &audioFileRef);
|
||||
|
||||
if (status == noErr)
|
||||
{
|
||||
AudioStreamBasicDescription sourceAudioFormat;
|
||||
UInt32 audioStreamBasicDescriptionSize = sizeof (AudioStreamBasicDescription);
|
||||
ExtAudioFileGetProperty (audioFileRef,
|
||||
kExtAudioFileProperty_FileDataFormat,
|
||||
&audioStreamBasicDescriptionSize,
|
||||
&sourceAudioFormat);
|
||||
|
||||
numChannels = sourceAudioFormat.mChannelsPerFrame;
|
||||
sampleRate = sourceAudioFormat.mSampleRate;
|
||||
|
||||
UInt32 sizeOfLengthProperty = sizeof (int64);
|
||||
ExtAudioFileGetProperty (audioFileRef,
|
||||
kExtAudioFileProperty_FileLengthFrames,
|
||||
&sizeOfLengthProperty,
|
||||
&lengthInSamples);
|
||||
|
||||
HeapBlock<AudioChannelLayout> caLayout;
|
||||
bool hasLayout = false;
|
||||
UInt32 sizeOfLayout = 0, isWritable = 0;
|
||||
|
||||
status = AudioFileGetPropertyInfo (audioFileID, kAudioFilePropertyChannelLayout, &sizeOfLayout, &isWritable);
|
||||
|
||||
if (status == noErr && sizeOfLayout >= (sizeof (AudioChannelLayout) - sizeof (AudioChannelDescription)))
|
||||
{
|
||||
caLayout.malloc (1, static_cast<size_t> (sizeOfLayout));
|
||||
|
||||
status = AudioFileGetProperty (audioFileID, kAudioFilePropertyChannelLayout,
|
||||
&sizeOfLayout, caLayout.get());
|
||||
|
||||
if (status == noErr)
|
||||
{
|
||||
auto fileLayout = CoreAudioLayouts::fromCoreAudio (*caLayout.get());
|
||||
|
||||
if (fileLayout.size() == static_cast<int> (numChannels))
|
||||
{
|
||||
hasLayout = true;
|
||||
channelSet = fileLayout;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
destinationAudioFormat.mSampleRate = sampleRate;
|
||||
destinationAudioFormat.mFormatID = kAudioFormatLinearPCM;
|
||||
destinationAudioFormat.mFormatFlags = kLinearPCMFormatFlagIsFloat | kLinearPCMFormatFlagIsNonInterleaved | kAudioFormatFlagsNativeEndian;
|
||||
destinationAudioFormat.mBitsPerChannel = sizeof (float) * 8;
|
||||
destinationAudioFormat.mChannelsPerFrame = numChannels;
|
||||
destinationAudioFormat.mBytesPerFrame = sizeof (float);
|
||||
destinationAudioFormat.mFramesPerPacket = 1;
|
||||
destinationAudioFormat.mBytesPerPacket = destinationAudioFormat.mFramesPerPacket * destinationAudioFormat.mBytesPerFrame;
|
||||
|
||||
status = ExtAudioFileSetProperty (audioFileRef,
|
||||
kExtAudioFileProperty_ClientDataFormat,
|
||||
sizeof (AudioStreamBasicDescription),
|
||||
&destinationAudioFormat);
|
||||
if (status == noErr)
|
||||
{
|
||||
bufferList.malloc (1, sizeof (AudioBufferList) + numChannels * sizeof (::AudioBuffer));
|
||||
bufferList->mNumberBuffers = numChannels;
|
||||
channelMap.malloc (numChannels);
|
||||
|
||||
if (hasLayout && caLayout != nullptr)
|
||||
{
|
||||
auto caOrder = CoreAudioLayouts::getCoreAudioLayoutChannels (*caLayout);
|
||||
|
||||
for (int i = 0; i < static_cast<int> (numChannels); ++i)
|
||||
{
|
||||
auto idx = channelSet.getChannelIndexForType (caOrder.getReference (i));
|
||||
jassert (isPositiveAndBelow (idx, static_cast<int> (numChannels)));
|
||||
|
||||
channelMap[i] = idx;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < static_cast<int> (numChannels); ++i)
|
||||
channelMap[i] = i;
|
||||
}
|
||||
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~CoreAudioReader() override
|
||||
{
|
||||
ExtAudioFileDispose (audioFileRef);
|
||||
AudioFileClose (audioFileID);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
|
||||
startSampleInFile, numSamples, lengthInSamples);
|
||||
|
||||
if (numSamples <= 0)
|
||||
return true;
|
||||
|
||||
if (lastReadPosition != startSampleInFile)
|
||||
{
|
||||
OSStatus status = ExtAudioFileSeek (audioFileRef, startSampleInFile);
|
||||
if (status != noErr)
|
||||
return false;
|
||||
|
||||
lastReadPosition = startSampleInFile;
|
||||
}
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
auto numThisTime = jmin (8192, numSamples);
|
||||
auto numBytes = (size_t) numThisTime * sizeof (float);
|
||||
|
||||
audioDataBlock.ensureSize (numBytes * numChannels, false);
|
||||
auto* data = static_cast<float*> (audioDataBlock.getData());
|
||||
|
||||
for (int j = (int) numChannels; --j >= 0;)
|
||||
{
|
||||
bufferList->mBuffers[j].mNumberChannels = 1;
|
||||
bufferList->mBuffers[j].mDataByteSize = (UInt32) numBytes;
|
||||
bufferList->mBuffers[j].mData = data;
|
||||
data += numThisTime;
|
||||
}
|
||||
|
||||
auto numFramesToRead = (UInt32) numThisTime;
|
||||
auto status = ExtAudioFileRead (audioFileRef, &numFramesToRead, bufferList);
|
||||
|
||||
if (status != noErr)
|
||||
return false;
|
||||
|
||||
if (numFramesToRead == 0)
|
||||
break;
|
||||
|
||||
if ((int) numFramesToRead < numThisTime)
|
||||
{
|
||||
numThisTime = (int) numFramesToRead;
|
||||
numBytes = (size_t) numThisTime * sizeof (float);
|
||||
}
|
||||
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
{
|
||||
auto* dest = destSamples[(i < (int) numChannels ? channelMap[i] : i)];
|
||||
|
||||
if (dest != nullptr)
|
||||
{
|
||||
if (i < (int) numChannels)
|
||||
memcpy (dest + startOffsetInDestBuffer, bufferList->mBuffers[i].mData, numBytes);
|
||||
else
|
||||
zeromem (dest + startOffsetInDestBuffer, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
startOffsetInDestBuffer += numThisTime;
|
||||
numSamples -= numThisTime;
|
||||
lastReadPosition += numThisTime;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioChannelSet getChannelLayout() override
|
||||
{
|
||||
if (channelSet.size() == static_cast<int> (numChannels))
|
||||
return channelSet;
|
||||
|
||||
return AudioFormatReader::getChannelLayout();
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
private:
|
||||
AudioFileID audioFileID;
|
||||
ExtAudioFileRef audioFileRef;
|
||||
AudioChannelSet channelSet;
|
||||
AudioStreamBasicDescription destinationAudioFormat;
|
||||
MemoryBlock audioDataBlock;
|
||||
HeapBlock<AudioBufferList> bufferList;
|
||||
int64 lastReadPosition = 0;
|
||||
HeapBlock<int> channelMap;
|
||||
|
||||
static SInt64 getSizeCallback (void* inClientData)
|
||||
{
|
||||
return static_cast<CoreAudioReader*> (inClientData)->input->getTotalLength();
|
||||
}
|
||||
|
||||
static OSStatus readCallback (void* inClientData, SInt64 inPosition, UInt32 requestCount,
|
||||
void* buffer, UInt32* actualCount)
|
||||
{
|
||||
auto* reader = static_cast<CoreAudioReader*> (inClientData);
|
||||
reader->input->setPosition (inPosition);
|
||||
*actualCount = (UInt32) reader->input->read (buffer, (int) requestCount);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioReader)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
CoreAudioFormat::CoreAudioFormat()
|
||||
: AudioFormat (coreAudioFormatName, findFileExtensionsForCoreAudioCodecs()),
|
||||
streamKind (StreamKind::kNone)
|
||||
{
|
||||
}
|
||||
|
||||
CoreAudioFormat::CoreAudioFormat (StreamKind kind)
|
||||
: AudioFormat (coreAudioFormatName, findFileExtensionsForCoreAudioCodec (toAudioFileTypeID (kind))),
|
||||
streamKind (kind)
|
||||
{
|
||||
}
|
||||
|
||||
CoreAudioFormat::~CoreAudioFormat() = default;
|
||||
|
||||
Array<int> CoreAudioFormat::getPossibleSampleRates() { return {}; }
|
||||
Array<int> CoreAudioFormat::getPossibleBitDepths() { return {}; }
|
||||
|
||||
bool CoreAudioFormat::canDoStereo() { return true; }
|
||||
bool CoreAudioFormat::canDoMono() { return true; }
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* CoreAudioFormat::createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
std::unique_ptr<CoreAudioReader> r (new CoreAudioReader (sourceStream, streamKind));
|
||||
|
||||
if (r->ok)
|
||||
return r.release();
|
||||
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* CoreAudioFormat::createWriterFor (OutputStream*,
|
||||
double /*sampleRateToUse*/,
|
||||
unsigned int /*numberOfChannels*/,
|
||||
int /*bitsPerSample*/,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
jassertfalse; // not yet implemented!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
//==============================================================================
|
||||
#if JUCE_UNIT_TESTS
|
||||
|
||||
#define DEFINE_CHANNEL_LAYOUT_DFL_ENTRY(x) CoreAudioChannelLayoutTag { x, #x, AudioChannelSet() }
|
||||
#define DEFINE_CHANNEL_LAYOUT_TAG_ENTRY(x, y) CoreAudioChannelLayoutTag { x, #x, y }
|
||||
|
||||
class CoreAudioLayoutsUnitTest final : public UnitTest
|
||||
{
|
||||
public:
|
||||
CoreAudioLayoutsUnitTest()
|
||||
: UnitTest ("Core Audio Layout <-> JUCE channel layout conversion", UnitTestCategories::audio)
|
||||
{}
|
||||
|
||||
// some ambisonic tags which are not explicitly defined
|
||||
enum
|
||||
{
|
||||
kAudioChannelLayoutTag_HOA_ACN_SN3D_0Order = (190U<<16) | 1,
|
||||
kAudioChannelLayoutTag_HOA_ACN_SN3D_1Order = (190U<<16) | 4,
|
||||
kAudioChannelLayoutTag_HOA_ACN_SN3D_2Order = (190U<<16) | 9,
|
||||
kAudioChannelLayoutTag_HOA_ACN_SN3D_3Order = (190U<<16) | 16,
|
||||
kAudioChannelLayoutTag_HOA_ACN_SN3D_4Order = (190U<<16) | 25,
|
||||
kAudioChannelLayoutTag_HOA_ACN_SN3D_5Order = (190U<<16) | 36
|
||||
};
|
||||
|
||||
void runTest() override
|
||||
{
|
||||
auto& knownTags = getAllKnownLayoutTags();
|
||||
|
||||
{
|
||||
// Check that all known tags defined in CoreAudio SDK version 10.12.4 are known to JUCE
|
||||
// Include all defined tags even if there are duplicates as Apple will sometimes change
|
||||
// definitions
|
||||
beginTest ("All CA tags handled");
|
||||
|
||||
for (auto tagEntry : knownTags)
|
||||
{
|
||||
auto labels = CoreAudioLayouts::fromCoreAudio (tagEntry.tag);
|
||||
|
||||
expect (! labels.isDiscreteLayout(), "Tag \"" + String (tagEntry.name) + "\" is not handled by JUCE");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("Number of speakers");
|
||||
|
||||
for (auto tagEntry : knownTags)
|
||||
{
|
||||
auto labels = CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag);
|
||||
|
||||
expect (labels.size() == (tagEntry.tag & 0xffff), "Tag \"" + String (tagEntry.name) + "\" has incorrect channel count");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("No duplicate speaker");
|
||||
|
||||
for (auto tagEntry : knownTags)
|
||||
{
|
||||
auto labels = CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag);
|
||||
labels.sort();
|
||||
|
||||
for (int i = 0; i < (labels.size() - 1); ++i)
|
||||
expect (labels.getReference (i) != labels.getReference (i + 1),
|
||||
"Tag \"" + String (tagEntry.name) + "\" has the same speaker twice");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("CA speaker list and juce layouts are consistent");
|
||||
|
||||
for (auto tagEntry : knownTags)
|
||||
expect (AudioChannelSet::channelSetWithChannels (CoreAudioLayouts::getSpeakerLayoutForCoreAudioTag (tagEntry.tag))
|
||||
== CoreAudioLayouts::fromCoreAudio (tagEntry.tag),
|
||||
"Tag \"" + String (tagEntry.name) + "\" is not converted consistently by JUCE");
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("AudioChannelSet documentation is correct");
|
||||
|
||||
for (auto tagEntry : knownTags)
|
||||
{
|
||||
if (tagEntry.equivalentChannelSet.isDisabled())
|
||||
continue;
|
||||
|
||||
expect (CoreAudioLayouts::fromCoreAudio (tagEntry.tag) == tagEntry.equivalentChannelSet,
|
||||
"Documentation for tag \"" + String (tagEntry.name) + "\" is incorrect");
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
beginTest ("CA tag reverse conversion");
|
||||
|
||||
for (auto tagEntry : knownTags)
|
||||
{
|
||||
if (tagEntry.equivalentChannelSet.isDisabled())
|
||||
continue;
|
||||
|
||||
expect (CoreAudioLayouts::toCoreAudio (tagEntry.equivalentChannelSet) == tagEntry.tag,
|
||||
"Incorrect reverse conversion for tag \"" + String (tagEntry.name) + "\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct CoreAudioChannelLayoutTag
|
||||
{
|
||||
AudioChannelLayoutTag tag;
|
||||
const char* name;
|
||||
AudioChannelSet equivalentChannelSet; /* referred to this in the AudioChannelSet documentation */
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
const Array<CoreAudioChannelLayoutTag>& getAllKnownLayoutTags() const
|
||||
{
|
||||
static CoreAudioChannelLayoutTag tags[] = {
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Mono, AudioChannelSet::mono()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Stereo, AudioChannelSet::stereo()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_StereoHeadphones),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MatrixStereo),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MidSide),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_XY),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Binaural),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Ambisonic_B_Format),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Quadraphonic, AudioChannelSet::quadraphonic()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Pentagonal, AudioChannelSet::pentagonal()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Hexagonal, AudioChannelSet::hexagonal()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_Octagonal, AudioChannelSet::octagonal()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Cube),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_1_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_2_0),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_3_0_A, AudioChannelSet::createLCR()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_3_0_B),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_4_0_A, AudioChannelSet::createLCRS()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_4_0_B),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_A, AudioChannelSet::create5point0()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_C),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_0_D),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_A, AudioChannelSet::create5point1()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_C),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_5_1_D),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_6_1_A, AudioChannelSet::create6point1()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_7_1_A, AudioChannelSet::create7point1SDDS()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_MPEG_7_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_MPEG_7_1_C, AudioChannelSet::create7point1()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_Emagic_Default_7_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_SMPTE_DTV),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_1_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_2_0),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_ITU_2_1, AudioChannelSet::createLRS()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_2_2),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_2),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_2_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_ITU_3_4_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_2),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_3),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_4),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_5),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_6),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_7),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_8),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_9),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_10),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_11),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_12),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_13),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_14),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_15),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_16),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_17),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_18),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_19),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DVD_20),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_4),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_5),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_6),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_8),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_5_0),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_AudioUnit_6_0, AudioChannelSet::create6point0()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_0, AudioChannelSet::create7point0()),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_0_Front, AudioChannelSet::create7point0SDDS()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_5_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_6_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AudioUnit_7_1_Front),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_3_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_Quadraphonic),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_4_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_5_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_5_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_6_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_6_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_7_1_C),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AAC_Octagonal),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_TMH_10_2_std),
|
||||
// DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_TMH_10_2_full), no indication on how to handle this tag
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_1_0_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_0_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_2_1_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_AC3_3_1_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC_6_0_A),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC_7_0_A),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_6_1_A),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_6_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_6_1_C),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_A),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_C),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_D),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_E),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_F),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_G),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_EAC3_7_1_H),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_3_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_4_1),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_DTS_6_0_A, AudioChannelSet::create6point0Music()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_0_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_0_C),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_DTS_6_1_A, AudioChannelSet::create6point1Music()),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_C),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_7_0),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_7_1),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_0_A),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_0_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_1_A),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_8_1_B),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_D),
|
||||
DEFINE_CHANNEL_LAYOUT_DFL_ENTRY (kAudioChannelLayoutTag_DTS_6_1_D),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_0Order, AudioChannelSet::ambisonic (0)),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_1Order, AudioChannelSet::ambisonic (1)),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_2Order, AudioChannelSet::ambisonic (2)),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_3Order, AudioChannelSet::ambisonic (3)),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_4Order, AudioChannelSet::ambisonic (4)),
|
||||
DEFINE_CHANNEL_LAYOUT_TAG_ENTRY (kAudioChannelLayoutTag_HOA_ACN_SN3D_5Order, AudioChannelSet::ambisonic (5))
|
||||
};
|
||||
static Array<CoreAudioChannelLayoutTag> knownTags (tags, sizeof (tags) / sizeof (CoreAudioChannelLayoutTag));
|
||||
|
||||
return knownTags;
|
||||
}
|
||||
};
|
||||
|
||||
static CoreAudioLayoutsUnitTest coreAudioLayoutsUnitTest;
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
OSX and iOS only - This uses the AudioToolbox framework to read any audio
|
||||
format that the system has a codec for.
|
||||
|
||||
This should be able to understand formats such as mp3, m4a, etc.
|
||||
|
||||
@see AudioFormat
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API CoreAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
/** File type hints. */
|
||||
enum class StreamKind
|
||||
{
|
||||
kNone,
|
||||
kAiff,
|
||||
kAifc,
|
||||
kWave,
|
||||
kSoundDesigner2,
|
||||
kNext,
|
||||
kMp3,
|
||||
kMp2,
|
||||
kMp1,
|
||||
kAc3,
|
||||
kAacAdts,
|
||||
kMpeg4,
|
||||
kM4a,
|
||||
kM4b,
|
||||
kCaf,
|
||||
k3gp,
|
||||
k3gp2,
|
||||
kAmr,
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
/** Creates a format object. */
|
||||
CoreAudioFormat();
|
||||
|
||||
/** Creates a format object and provides a hint as to the format of data
|
||||
to be read or written.
|
||||
*/
|
||||
explicit CoreAudioFormat (StreamKind);
|
||||
|
||||
/** Destructor. */
|
||||
~CoreAudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used when reading a caf file with a MIDI chunk. */
|
||||
static const char* const midiDataBase64;
|
||||
/** Metadata property name used when reading a caf file with tempo information. */
|
||||
static const char* const tempo;
|
||||
/** Metadata property name used when reading a caf file time signature information. */
|
||||
static const char* const timeSig;
|
||||
/** Metadata property name used when reading a caf file time signature information. */
|
||||
static const char* const keySig;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream*,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
StreamKind streamKind = StreamKind::kNone;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioFormat)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,628 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
}
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
#include <io.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
|
||||
#include <sys/types.h> /* for off_t */
|
||||
#endif
|
||||
|
||||
#if HAVE_INTTYPES_H
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __MINGW32__ || defined __CYGWIN__ || defined __EMX__
|
||||
#include <io.h> /* for _setmode(), chmod() */
|
||||
#include <fcntl.h> /* for _O_BINARY */
|
||||
#else
|
||||
#include <unistd.h> /* for chown(), unlink() */
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINGW32__
|
||||
#if defined __BORLANDC__
|
||||
#include <utime.h> /* for utime() */
|
||||
#else
|
||||
#include <sys/utime.h> /* for utime() */
|
||||
#endif
|
||||
#else
|
||||
#include <sys/types.h> /* some flavors of BSD (like OS X) require this to get time_t */
|
||||
#include <utime.h> /* for utime() */
|
||||
#endif
|
||||
|
||||
#if defined _MSC_VER
|
||||
#if _MSC_VER >= 1600
|
||||
#include <stdint.h>
|
||||
#else
|
||||
#include <limits.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
#include <assert.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
namespace FlacNamespace
|
||||
{
|
||||
#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)
|
||||
|
||||
#undef PACKAGE_VERSION
|
||||
#define PACKAGE_VERSION "1.4.3"
|
||||
|
||||
#define FLAC__NO_DLL 1
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4312 4505 4365 4005 4334 181 111 6340 6308 6297 6001 6320)
|
||||
#if ! JUCE_MSVC
|
||||
#define HAVE_LROUND 1
|
||||
#endif
|
||||
|
||||
#if JUCE_MAC
|
||||
#define FLAC__SYS_DARWIN 1
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX 0xffffffff
|
||||
#endif
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",
|
||||
"-Wdeprecated-register",
|
||||
"-Wfloat-equal",
|
||||
"-Wimplicit-fallthrough",
|
||||
"-Wlanguage-extension-token",
|
||||
"-Wredundant-decls",
|
||||
"-Wshadow",
|
||||
"-Wsign-conversion",
|
||||
"-Wswitch-default",
|
||||
"-Wswitch-enum",
|
||||
"-Wzero-as-null-pointer-constant")
|
||||
|
||||
#if JUCE_INTEL
|
||||
#if JUCE_32BIT
|
||||
#define FLAC__CPU_IA32 1
|
||||
#endif
|
||||
#if JUCE_64BIT
|
||||
#define FLAC__CPU_X86_64 1
|
||||
#endif
|
||||
#define FLAC__HAS_X86INTRIN 1
|
||||
#endif
|
||||
|
||||
#if JUCE_ARM && JUCE_64BIT
|
||||
#define FLAC__CPU_ARM64 1
|
||||
|
||||
#if JUCE_USE_ARM_NEON
|
||||
#define FLAC__HAS_NEONINTRIN 1
|
||||
#define FLAC__HAS_A64NEONINTRIN 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define flac_max jmax
|
||||
#define flac_min jmin
|
||||
|
||||
#pragma push_macro ("DEBUG")
|
||||
#pragma push_macro ("NDEBUG")
|
||||
#undef DEBUG // (some flac code dumps debug trace if the app defines this macro)
|
||||
|
||||
#ifndef NDEBUG
|
||||
#define NDEBUG // (some flac code prints cpu info if this isn't defined)
|
||||
#endif
|
||||
|
||||
#include "flac/all.h"
|
||||
#include "flac/libFLAC/bitmath.c"
|
||||
#include "flac/libFLAC/bitreader.c"
|
||||
#include "flac/libFLAC/bitwriter.c"
|
||||
#include "flac/libFLAC/cpu.c"
|
||||
#include "flac/libFLAC/crc.c"
|
||||
#include "flac/libFLAC/fixed.c"
|
||||
#include "flac/libFLAC/float.c"
|
||||
#include "flac/libFLAC/format.c"
|
||||
#include "flac/libFLAC/lpc_flac.c"
|
||||
#include "flac/libFLAC/lpc_intrin_neon.c"
|
||||
#include "flac/libFLAC/md5.c"
|
||||
#include "flac/libFLAC/memory.c"
|
||||
#include "flac/libFLAC/stream_decoder.c"
|
||||
#include "flac/libFLAC/stream_encoder.c"
|
||||
#include "flac/libFLAC/stream_encoder_framing.c"
|
||||
#include "flac/libFLAC/window_flac.c"
|
||||
|
||||
#pragma pop_macro ("DEBUG")
|
||||
#pragma pop_macro ("NDEBUG")
|
||||
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
|
||||
#else
|
||||
#include <FLAC/all.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
//==============================================================================
|
||||
static const char* const flacFormatName = "FLAC file";
|
||||
|
||||
template <typename Item>
|
||||
auto emptyRange (Item item) { return Range<Item>::emptyRange (item); }
|
||||
|
||||
//==============================================================================
|
||||
class FlacReader final : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
FlacReader (InputStream* in) : AudioFormatReader (in, flacFormatName)
|
||||
{
|
||||
lengthInSamples = 0;
|
||||
decoder = FlacNamespace::FLAC__stream_decoder_new();
|
||||
|
||||
ok = FLAC__stream_decoder_init_stream (decoder,
|
||||
readCallback_, seekCallback_, tellCallback_, lengthCallback_,
|
||||
eofCallback_, writeCallback_, metadataCallback_, errorCallback_,
|
||||
this) == FlacNamespace::FLAC__STREAM_DECODER_INIT_STATUS_OK;
|
||||
|
||||
if (ok)
|
||||
{
|
||||
FLAC__stream_decoder_process_until_end_of_metadata (decoder);
|
||||
|
||||
if (lengthInSamples == 0 && sampleRate > 0)
|
||||
{
|
||||
// the length hasn't been stored in the metadata, so we'll need to
|
||||
// work it out the length the hard way, by scanning the whole file..
|
||||
scanningForLength = true;
|
||||
FLAC__stream_decoder_process_until_end_of_stream (decoder);
|
||||
scanningForLength = false;
|
||||
auto tempLength = lengthInSamples;
|
||||
|
||||
FLAC__stream_decoder_reset (decoder);
|
||||
FLAC__stream_decoder_process_until_end_of_metadata (decoder);
|
||||
lengthInSamples = tempLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~FlacReader() override
|
||||
{
|
||||
FlacNamespace::FLAC__stream_decoder_delete (decoder);
|
||||
}
|
||||
|
||||
void useMetadata (const FlacNamespace::FLAC__StreamMetadata_StreamInfo& info)
|
||||
{
|
||||
sampleRate = info.sample_rate;
|
||||
bitsPerSample = info.bits_per_sample;
|
||||
lengthInSamples = (unsigned int) info.total_samples;
|
||||
numChannels = info.channels;
|
||||
|
||||
reservoir.setSize ((int) numChannels, 2 * (int) info.max_blocksize, false, false, true);
|
||||
}
|
||||
|
||||
bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
if (! ok)
|
||||
return false;
|
||||
|
||||
const auto getBufferedRange = [this] { return bufferedRange; };
|
||||
|
||||
const auto readFromReservoir = [this, &destSamples, &numDestChannels, &startOffsetInDestBuffer, &startSampleInFile] (const Range<int64> rangeToRead)
|
||||
{
|
||||
const auto bufferIndices = rangeToRead - bufferedRange.getStart();
|
||||
const auto writePos = (int64) startOffsetInDestBuffer + (rangeToRead.getStart() - startSampleInFile);
|
||||
|
||||
for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
|
||||
{
|
||||
if (destSamples[i] != nullptr)
|
||||
{
|
||||
memcpy (destSamples[i] + writePos,
|
||||
reservoir.getReadPointer (i) + bufferIndices.getStart(),
|
||||
(size_t) bufferIndices.getLength() * sizeof (int));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const auto fillReservoir = [this] (const int64 requestedStart)
|
||||
{
|
||||
if (requestedStart >= lengthInSamples)
|
||||
{
|
||||
bufferedRange = emptyRange (requestedStart);
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestedStart < bufferedRange.getStart()
|
||||
|| jmax (bufferedRange.getEnd(), bufferedRange.getStart() + (int64) 511) < requestedStart)
|
||||
{
|
||||
// had some problems with flac crashing if the read pos is aligned more
|
||||
// accurately than this. Probably fixed in newer versions of the library, though.
|
||||
bufferedRange = emptyRange (requestedStart & ~511);
|
||||
FLAC__stream_decoder_seek_absolute (decoder, (FlacNamespace::FLAC__uint64) bufferedRange.getStart());
|
||||
return;
|
||||
}
|
||||
|
||||
bufferedRange = emptyRange (bufferedRange.getEnd());
|
||||
FLAC__stream_decoder_process_single (decoder);
|
||||
};
|
||||
|
||||
const auto remainingSamples = Reservoir::doBufferedRead (Range<int64> { startSampleInFile, startSampleInFile + numSamples },
|
||||
getBufferedRange,
|
||||
readFromReservoir,
|
||||
fillReservoir);
|
||||
|
||||
if (! remainingSamples.isEmpty())
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer + (remainingSamples.getStart() - startSampleInFile),
|
||||
(size_t) remainingSamples.getLength() * sizeof (int));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void useSamples (const FlacNamespace::FLAC__int32* const buffer[], int numSamples)
|
||||
{
|
||||
if (scanningForLength)
|
||||
{
|
||||
lengthInSamples += numSamples;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numSamples > reservoir.getNumSamples())
|
||||
reservoir.setSize ((int) numChannels, numSamples, false, false, true);
|
||||
|
||||
auto bitsToShift = 32 - bitsPerSample;
|
||||
|
||||
for (int i = 0; i < (int) numChannels; ++i)
|
||||
{
|
||||
auto* src = buffer[i];
|
||||
int n = i;
|
||||
|
||||
while (src == nullptr && n > 0)
|
||||
src = buffer [--n];
|
||||
|
||||
if (src != nullptr)
|
||||
{
|
||||
auto* dest = reinterpret_cast<int*> (reservoir.getWritePointer (i));
|
||||
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
dest[j] = src[j] << bitsToShift;
|
||||
}
|
||||
}
|
||||
|
||||
bufferedRange.setLength (numSamples);
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[], size_t* bytes, void* client_data)
|
||||
{
|
||||
*bytes = (size_t) static_cast<const FlacReader*> (client_data)->input->read (buffer, (int) *bytes);
|
||||
return FlacNamespace::FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset, void* client_data)
|
||||
{
|
||||
static_cast<const FlacReader*> (client_data)->input->setPosition ((int) absolute_byte_offset);
|
||||
return FlacNamespace::FLAC__STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
|
||||
{
|
||||
*absolute_byte_offset = (uint64) static_cast<const FlacReader*> (client_data)->input->getPosition();
|
||||
return FlacNamespace::FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length, void* client_data)
|
||||
{
|
||||
*stream_length = (uint64) static_cast<const FlacReader*> (client_data)->input->getTotalLength();
|
||||
return FlacNamespace::FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__bool eofCallback_ (const FlacNamespace::FLAC__StreamDecoder*, void* client_data)
|
||||
{
|
||||
return static_cast<const FlacReader*> (client_data)->input->isExhausted();
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderWriteStatus writeCallback_ (const FlacNamespace::FLAC__StreamDecoder*,
|
||||
const FlacNamespace::FLAC__Frame* frame,
|
||||
const FlacNamespace::FLAC__int32* const buffer[],
|
||||
void* client_data)
|
||||
{
|
||||
static_cast<FlacReader*> (client_data)->useSamples (buffer, (int) frame->header.blocksize);
|
||||
return FlacNamespace::FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static void metadataCallback_ (const FlacNamespace::FLAC__StreamDecoder*,
|
||||
const FlacNamespace::FLAC__StreamMetadata* metadata,
|
||||
void* client_data)
|
||||
{
|
||||
static_cast<FlacReader*> (client_data)->useMetadata (metadata->data.stream_info);
|
||||
}
|
||||
|
||||
static void errorCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__StreamDecoderErrorStatus, void*)
|
||||
{
|
||||
}
|
||||
|
||||
private:
|
||||
FlacNamespace::FLAC__StreamDecoder* decoder;
|
||||
AudioBuffer<float> reservoir;
|
||||
Range<int64> bufferedRange;
|
||||
bool ok = false, scanningForLength = false;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacReader)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class FlacWriter final : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
FlacWriter (OutputStream* out, double rate, uint32 numChans, uint32 bits, int qualityOptionIndex)
|
||||
: AudioFormatWriter (out, flacFormatName, rate, numChans, bits),
|
||||
streamStartPos (output != nullptr ? jmax (output->getPosition(), 0ll) : 0ll)
|
||||
{
|
||||
encoder = FlacNamespace::FLAC__stream_encoder_new();
|
||||
|
||||
if (qualityOptionIndex > 0)
|
||||
FLAC__stream_encoder_set_compression_level (encoder, (uint32) jmin (8, qualityOptionIndex));
|
||||
|
||||
FLAC__stream_encoder_set_do_mid_side_stereo (encoder, numChannels == 2);
|
||||
FLAC__stream_encoder_set_loose_mid_side_stereo (encoder, numChannels == 2);
|
||||
FLAC__stream_encoder_set_channels (encoder, numChannels);
|
||||
FLAC__stream_encoder_set_bits_per_sample (encoder, jmin ((unsigned int) 24, bitsPerSample));
|
||||
FLAC__stream_encoder_set_sample_rate (encoder, (unsigned int) sampleRate);
|
||||
FLAC__stream_encoder_set_blocksize (encoder, 0);
|
||||
FLAC__stream_encoder_set_do_escape_coding (encoder, true);
|
||||
|
||||
ok = FLAC__stream_encoder_init_stream (encoder,
|
||||
encodeWriteCallback, encodeSeekCallback,
|
||||
encodeTellCallback, encodeMetadataCallback,
|
||||
this) == FlacNamespace::FLAC__STREAM_ENCODER_INIT_STATUS_OK;
|
||||
}
|
||||
|
||||
~FlacWriter() override
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
FlacNamespace::FLAC__stream_encoder_finish (encoder);
|
||||
output->flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
output = nullptr; // to stop the base class deleting this, as it needs to be returned
|
||||
// to the caller of createWriter()
|
||||
}
|
||||
|
||||
FlacNamespace::FLAC__stream_encoder_delete (encoder);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (const int** samplesToWrite, int numSamples) override
|
||||
{
|
||||
if (! ok)
|
||||
return false;
|
||||
|
||||
HeapBlock<int*> channels;
|
||||
HeapBlock<int> temp;
|
||||
auto bitsToShift = 32 - (int) bitsPerSample;
|
||||
|
||||
if (bitsToShift > 0)
|
||||
{
|
||||
temp.malloc (numChannels * (size_t) numSamples);
|
||||
channels.calloc (numChannels + 1);
|
||||
|
||||
for (unsigned int i = 0; i < numChannels; ++i)
|
||||
{
|
||||
if (samplesToWrite[i] == nullptr)
|
||||
break;
|
||||
|
||||
auto* destData = temp.get() + i * (size_t) numSamples;
|
||||
channels[i] = destData;
|
||||
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
destData[j] = (samplesToWrite[i][j] >> bitsToShift);
|
||||
}
|
||||
|
||||
samplesToWrite = const_cast<const int**> (channels.get());
|
||||
}
|
||||
|
||||
return FLAC__stream_encoder_process (encoder, (const FlacNamespace::FLAC__int32**) samplesToWrite, (unsigned) numSamples) != 0;
|
||||
}
|
||||
|
||||
bool writeData (const void* const data, const int size) const
|
||||
{
|
||||
return output->write (data, (size_t) size);
|
||||
}
|
||||
|
||||
static void packUint32 (FlacNamespace::FLAC__uint32 val, FlacNamespace::FLAC__byte* b, const int bytes)
|
||||
{
|
||||
b += bytes;
|
||||
|
||||
for (int i = 0; i < bytes; ++i)
|
||||
{
|
||||
*(--b) = (FlacNamespace::FLAC__byte) (val & 0xff);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void writeMetaData (const FlacNamespace::FLAC__StreamMetadata* metadata)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
auto& info = metadata->data.stream_info;
|
||||
|
||||
unsigned char buffer[FLAC__STREAM_METADATA_STREAMINFO_LENGTH];
|
||||
const unsigned int channelsMinus1 = info.channels - 1;
|
||||
const unsigned int bitsMinus1 = info.bits_per_sample - 1;
|
||||
|
||||
packUint32 (info.min_blocksize, buffer, 2);
|
||||
packUint32 (info.max_blocksize, buffer + 2, 2);
|
||||
packUint32 (info.min_framesize, buffer + 4, 3);
|
||||
packUint32 (info.max_framesize, buffer + 7, 3);
|
||||
buffer[10] = (uint8) ((info.sample_rate >> 12) & 0xff);
|
||||
buffer[11] = (uint8) ((info.sample_rate >> 4) & 0xff);
|
||||
buffer[12] = (uint8) (((info.sample_rate & 0x0f) << 4) | (channelsMinus1 << 1) | (bitsMinus1 >> 4));
|
||||
buffer[13] = (FLAC__byte) (((bitsMinus1 & 0x0f) << 4) | (unsigned int) ((info.total_samples >> 32) & 0x0f));
|
||||
packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4);
|
||||
memcpy (buffer + 18, info.md5sum, 16);
|
||||
|
||||
[[maybe_unused]] const bool seekOk = output->setPosition (streamStartPos + 4);
|
||||
|
||||
// if this fails, you've given it an output stream that can't seek! It needs
|
||||
// to be able to seek back to write the header
|
||||
jassert (seekOk);
|
||||
|
||||
output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
|
||||
output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static FlacNamespace::FLAC__StreamEncoderWriteStatus encodeWriteCallback (const FlacNamespace::FLAC__StreamEncoder*,
|
||||
const FlacNamespace::FLAC__byte buffer[],
|
||||
size_t bytes,
|
||||
unsigned int /*samples*/,
|
||||
unsigned int /*current_frame*/,
|
||||
void* client_data)
|
||||
{
|
||||
return static_cast<FlacWriter*> (client_data)->writeData (buffer, (int) bytes)
|
||||
? FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_OK
|
||||
: FlacNamespace::FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64, void*)
|
||||
{
|
||||
return FlacNamespace::FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamEncoderTellStatus encodeTellCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
|
||||
{
|
||||
if (client_data == nullptr)
|
||||
return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
|
||||
|
||||
*absolute_byte_offset = (FlacNamespace::FLAC__uint64) static_cast<FlacWriter*> (client_data)->output->getPosition();
|
||||
return FlacNamespace::FLAC__STREAM_ENCODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static void encodeMetadataCallback (const FlacNamespace::FLAC__StreamEncoder*, const FlacNamespace::FLAC__StreamMetadata* metadata, void* client_data)
|
||||
{
|
||||
static_cast<FlacWriter*> (client_data)->writeMetaData (metadata);
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
private:
|
||||
FlacNamespace::FLAC__StreamEncoder* encoder;
|
||||
int64 streamStartPos;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacWriter)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FlacAudioFormat::FlacAudioFormat() : AudioFormat (flacFormatName, ".flac") {}
|
||||
FlacAudioFormat::~FlacAudioFormat() {}
|
||||
|
||||
Array<int> FlacAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
return { 8000, 11025, 12000, 16000, 22050, 32000, 44100, 48000,
|
||||
88200, 96000, 176400, 192000, 352800, 384000 };
|
||||
}
|
||||
|
||||
Array<int> FlacAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
return { 16, 24 };
|
||||
}
|
||||
|
||||
bool FlacAudioFormat::canDoStereo() { return true; }
|
||||
bool FlacAudioFormat::canDoMono() { return true; }
|
||||
bool FlacAudioFormat::isCompressed() { return true; }
|
||||
|
||||
AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
std::unique_ptr<FlacReader> r (new FlacReader (in));
|
||||
|
||||
if (r->sampleRate > 0)
|
||||
return r.release();
|
||||
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
if (out != nullptr && getPossibleBitDepths().contains (bitsPerSample))
|
||||
{
|
||||
std::unique_ptr<FlacWriter> w (new FlacWriter (out, sampleRate, numberOfChannels,
|
||||
(uint32) bitsPerSample, qualityOptionIndex));
|
||||
if (w->ok)
|
||||
return w.release();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StringArray FlacAudioFormat::getQualityOptions()
|
||||
{
|
||||
return { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)" };
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_FLAC || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and writes the lossless-compression FLAC audio format.
|
||||
|
||||
To compile this, you'll need to set the JUCE_USE_FLAC flag.
|
||||
|
||||
@see AudioFormat
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API FlacAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FlacAudioFormat();
|
||||
~FlacAudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
bool isCompressed() override;
|
||||
StringArray getQualityOptions() override;
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacAudioFormat)
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_LAME_AUDIO_FORMAT
|
||||
|
||||
class LAMEEncoderAudioFormat::Writer final : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
Writer (OutputStream* destStream, const String& formatName,
|
||||
const File& appFile, int vbr, int cbr,
|
||||
double sampleRateIn, unsigned int numberOfChannels,
|
||||
int bitsPerSampleIn, const StringPairArray& metadata)
|
||||
: AudioFormatWriter (destStream, formatName, sampleRateIn,
|
||||
numberOfChannels, (unsigned int) bitsPerSampleIn),
|
||||
vbrLevel (vbr), cbrBitrate (cbr)
|
||||
{
|
||||
WavAudioFormat wavFormat;
|
||||
|
||||
if (auto out = tempWav.getFile().createOutputStream())
|
||||
{
|
||||
writer.reset (wavFormat.createWriterFor (out.release(), sampleRateIn, numChannels,
|
||||
bitsPerSampleIn, metadata, 0));
|
||||
|
||||
args.add (appFile.getFullPathName());
|
||||
|
||||
args.add ("--quiet");
|
||||
|
||||
if (cbrBitrate == 0)
|
||||
{
|
||||
args.add ("--vbr-new");
|
||||
args.add ("-V");
|
||||
args.add (String (vbrLevel));
|
||||
}
|
||||
else
|
||||
{
|
||||
args.add ("--cbr");
|
||||
args.add ("-b");
|
||||
args.add (String (cbrBitrate));
|
||||
}
|
||||
|
||||
addMetadataArg (metadata, "id3title", "--tt");
|
||||
addMetadataArg (metadata, "id3artist", "--ta");
|
||||
addMetadataArg (metadata, "id3album", "--tl");
|
||||
addMetadataArg (metadata, "id3comment", "--tc");
|
||||
addMetadataArg (metadata, "id3date", "--ty");
|
||||
addMetadataArg (metadata, "id3genre", "--tg");
|
||||
addMetadataArg (metadata, "id3trackNumber", "--tn");
|
||||
}
|
||||
}
|
||||
|
||||
void addMetadataArg (const StringPairArray& metadata, const char* key, const char* lameFlag)
|
||||
{
|
||||
auto value = metadata.getValue (key, {});
|
||||
|
||||
if (value.isNotEmpty())
|
||||
{
|
||||
args.add (lameFlag);
|
||||
args.add (value);
|
||||
}
|
||||
}
|
||||
|
||||
~Writer()
|
||||
{
|
||||
if (writer != nullptr)
|
||||
{
|
||||
writer = nullptr;
|
||||
|
||||
if (! convertToMP3())
|
||||
convertToMP3(); // try again
|
||||
}
|
||||
}
|
||||
|
||||
bool write (const int** samplesToWrite, int numSamples)
|
||||
{
|
||||
return writer != nullptr && writer->write (samplesToWrite, numSamples);
|
||||
}
|
||||
|
||||
private:
|
||||
int vbrLevel, cbrBitrate;
|
||||
TemporaryFile tempWav { ".wav" };
|
||||
std::unique_ptr<AudioFormatWriter> writer;
|
||||
StringArray args;
|
||||
|
||||
bool runLameChildProcess (const TemporaryFile& tempMP3, const StringArray& processArgs) const
|
||||
{
|
||||
ChildProcess cp;
|
||||
|
||||
if (cp.start (processArgs))
|
||||
{
|
||||
[[maybe_unused]] auto childOutput = cp.readAllProcessOutput();
|
||||
DBG (childOutput);
|
||||
|
||||
cp.waitForProcessToFinish (10000);
|
||||
return tempMP3.getFile().getSize() > 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool convertToMP3() const
|
||||
{
|
||||
TemporaryFile tempMP3 (".mp3");
|
||||
|
||||
StringArray args2 (args);
|
||||
args2.add (tempWav.getFile().getFullPathName());
|
||||
args2.add (tempMP3.getFile().getFullPathName());
|
||||
|
||||
DBG (args2.joinIntoString (" "));
|
||||
|
||||
if (runLameChildProcess (tempMP3, args2))
|
||||
{
|
||||
FileInputStream fis (tempMP3.getFile());
|
||||
|
||||
if (fis.openedOk() && output->writeFromInputStream (fis, -1) > 0)
|
||||
{
|
||||
output->flush();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Writer)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
LAMEEncoderAudioFormat::LAMEEncoderAudioFormat (const File& lameApplication)
|
||||
: AudioFormat ("MP3 file", ".mp3"),
|
||||
lameApp (lameApplication)
|
||||
{
|
||||
}
|
||||
|
||||
LAMEEncoderAudioFormat::~LAMEEncoderAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
bool LAMEEncoderAudioFormat::canHandleFile (const File&)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Array<int> LAMEEncoderAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
return { 32000, 44100, 48000 };
|
||||
}
|
||||
|
||||
Array<int> LAMEEncoderAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
return { 16 };
|
||||
}
|
||||
|
||||
bool LAMEEncoderAudioFormat::canDoStereo() { return true; }
|
||||
bool LAMEEncoderAudioFormat::canDoMono() { return true; }
|
||||
bool LAMEEncoderAudioFormat::isCompressed() { return true; }
|
||||
|
||||
StringArray LAMEEncoderAudioFormat::getQualityOptions()
|
||||
{
|
||||
static const char* vbrOptions[] = { "VBR quality 0 (best)", "VBR quality 1", "VBR quality 2", "VBR quality 3",
|
||||
"VBR quality 4 (normal)", "VBR quality 5", "VBR quality 6", "VBR quality 7",
|
||||
"VBR quality 8", "VBR quality 9 (smallest)", nullptr };
|
||||
StringArray opts (vbrOptions);
|
||||
|
||||
const int cbrRates[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 };
|
||||
|
||||
for (int i = 0; i < numElementsInArray (cbrRates); ++i)
|
||||
opts.add (String (cbrRates[i]) + " Kb/s CBR");
|
||||
|
||||
return opts;
|
||||
}
|
||||
|
||||
AudioFormatReader* LAMEEncoderAudioFormat::createReaderFor (InputStream*, const bool)
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* LAMEEncoderAudioFormat::createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
if (streamToWriteTo == nullptr)
|
||||
return nullptr;
|
||||
|
||||
int vbr = 4;
|
||||
int cbr = 0;
|
||||
|
||||
const String qual (getQualityOptions() [qualityOptionIndex]);
|
||||
|
||||
if (qual.contains ("VBR"))
|
||||
vbr = qual.retainCharacters ("0123456789").getIntValue();
|
||||
else
|
||||
cbr = qual.getIntValue();
|
||||
|
||||
return new Writer (streamToWriteTo, getFormatName(), lameApp, vbr, cbr,
|
||||
sampleRateToUse, numberOfChannels, bitsPerSample, metadataValues);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_LAME_AUDIO_FORMAT || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An AudioFormat class which can use an installed version of the LAME mp3
|
||||
encoder to encode a file.
|
||||
|
||||
This format can't read MP3s, it just writes them. Internally, the
|
||||
AudioFormatWriter object that is returned writes the incoming audio data
|
||||
to a temporary WAV file, and then when the writer is deleted, it invokes
|
||||
the LAME executable to convert the data to an MP3, whose data is then
|
||||
piped into the original OutputStream that was used when first creating
|
||||
the writer.
|
||||
|
||||
@see AudioFormat
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API LAMEEncoderAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
/** Creates a LAMEEncoderAudioFormat that expects to find a working LAME
|
||||
executable at the location given.
|
||||
*/
|
||||
LAMEEncoderAudioFormat (const File& lameExecutableToUse);
|
||||
~LAMEEncoderAudioFormat();
|
||||
|
||||
bool canHandleFile (const File&);
|
||||
Array<int> getPossibleSampleRates();
|
||||
Array<int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
bool isCompressed();
|
||||
StringArray getQualityOptions();
|
||||
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex);
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
File lameApp;
|
||||
class Writer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LAMEEncoderAudioFormat)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_MP3AUDIOFORMAT || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Software-based MP3 decoding format (doesn't currently provide an encoder).
|
||||
|
||||
IMPORTANT DISCLAIMER: By choosing to enable the JUCE_USE_MP3AUDIOFORMAT flag and
|
||||
to compile the MP3 code into your software, you do so AT YOUR OWN RISK! By doing so,
|
||||
you are agreeing that Raw Material Software Limited is in no way responsible for any patent,
|
||||
copyright, or other legal issues that you may suffer as a result.
|
||||
|
||||
The code in juce_MP3AudioFormat.cpp is NOT guaranteed to be free from infringements of 3rd-party
|
||||
intellectual property. If you wish to use it, please seek your own independent advice about the
|
||||
legality of doing so. If you are not willing to accept full responsibility for the consequences
|
||||
of using this code, then do not enable the JUCE_USE_MP3AUDIOFORMAT setting.
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class MP3AudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MP3AudioFormat();
|
||||
~MP3AudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
bool isCompressed() override;
|
||||
StringArray getQualityOptions() override;
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,522 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
#if JUCE_MAC && ! defined (__MACOSX__)
|
||||
#define __MACOSX__ 1
|
||||
#endif
|
||||
|
||||
namespace OggVorbisNamespace
|
||||
{
|
||||
#if JUCE_INCLUDE_OGGVORBIS_CODE || ! defined (JUCE_INCLUDE_OGGVORBIS_CODE)
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4267 4127 4244 4100 4701 4702 4013 4133 4206 4305 4189 4706 4995 4365 4456 4457 4459 6297 6011 6001 6308 6255 6386 6385 6246 6387 6263 6262 28182)
|
||||
|
||||
JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wcast-align",
|
||||
"-Wconversion",
|
||||
"-Wdeprecated-register",
|
||||
"-Wfloat-conversion",
|
||||
"-Wfloat-equal",
|
||||
"-Wmaybe-uninitialized",
|
||||
"-Wmisleading-indentation",
|
||||
"-Wmissing-prototypes",
|
||||
"-Wredundant-decls",
|
||||
"-Wshadow",
|
||||
"-Wsign-conversion",
|
||||
"-Wswitch-default",
|
||||
"-Wswitch-enum",
|
||||
"-Wzero-as-null-pointer-constant")
|
||||
|
||||
JUCE_BEGIN_IGNORE_DEPRECATION_WARNINGS
|
||||
|
||||
JUCE_BEGIN_NO_SANITIZE ("undefined")
|
||||
|
||||
#include "oggvorbis/vorbisenc.h"
|
||||
#include "oggvorbis/codec.h"
|
||||
#include "oggvorbis/vorbisfile.h"
|
||||
|
||||
#include "oggvorbis/bitwise.c"
|
||||
#include "oggvorbis/framing.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/analysis.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/bitrate.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/block.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/codebook.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/envelope.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/floor0.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/floor1.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/info.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/lpc.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/lsp.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/mapping0.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/mdct.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/psy.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/registry.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/res0.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/sharedbook.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/smallft.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/synthesis.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/vorbisenc.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/vorbisfile.c"
|
||||
#include "oggvorbis/libvorbis-1.3.7/lib/window.c"
|
||||
|
||||
JUCE_END_NO_SANITIZE
|
||||
JUCE_END_IGNORE_DEPRECATION_WARNINGS
|
||||
JUCE_END_IGNORE_WARNINGS_MSVC
|
||||
JUCE_END_IGNORE_WARNINGS_GCC_LIKE
|
||||
#else
|
||||
#include <vorbis/vorbisenc.h>
|
||||
#include <vorbis/codec.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
//==============================================================================
|
||||
static const char* const oggFormatName = "Ogg-Vorbis file";
|
||||
|
||||
const char* const OggVorbisAudioFormat::encoderName = "encoder";
|
||||
const char* const OggVorbisAudioFormat::id3title = "id3title";
|
||||
const char* const OggVorbisAudioFormat::id3artist = "id3artist";
|
||||
const char* const OggVorbisAudioFormat::id3album = "id3album";
|
||||
const char* const OggVorbisAudioFormat::id3comment = "id3comment";
|
||||
const char* const OggVorbisAudioFormat::id3date = "id3date";
|
||||
const char* const OggVorbisAudioFormat::id3genre = "id3genre";
|
||||
const char* const OggVorbisAudioFormat::id3trackNumber = "id3trackNumber";
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class OggReader final : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
OggReader (InputStream* inp) : AudioFormatReader (inp, oggFormatName)
|
||||
{
|
||||
sampleRate = 0;
|
||||
usesFloatingPointData = true;
|
||||
|
||||
callbacks.read_func = &oggReadCallback;
|
||||
callbacks.seek_func = &oggSeekCallback;
|
||||
callbacks.close_func = &oggCloseCallback;
|
||||
callbacks.tell_func = &oggTellCallback;
|
||||
|
||||
auto err = ov_open_callbacks (input, &ovFile, nullptr, 0, callbacks);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
auto* info = ov_info (&ovFile, -1);
|
||||
|
||||
auto* comment = ov_comment (&ovFile, -1);
|
||||
addMetadataItem (comment, "ENCODER", OggVorbisAudioFormat::encoderName);
|
||||
addMetadataItem (comment, "TITLE", OggVorbisAudioFormat::id3title);
|
||||
addMetadataItem (comment, "ARTIST", OggVorbisAudioFormat::id3artist);
|
||||
addMetadataItem (comment, "ALBUM", OggVorbisAudioFormat::id3album);
|
||||
addMetadataItem (comment, "COMMENT", OggVorbisAudioFormat::id3comment);
|
||||
addMetadataItem (comment, "DATE", OggVorbisAudioFormat::id3date);
|
||||
addMetadataItem (comment, "GENRE", OggVorbisAudioFormat::id3genre);
|
||||
addMetadataItem (comment, "TRACKNUMBER", OggVorbisAudioFormat::id3trackNumber);
|
||||
|
||||
lengthInSamples = (uint32) ov_pcm_total (&ovFile, -1);
|
||||
numChannels = (unsigned int) info->channels;
|
||||
bitsPerSample = 16;
|
||||
sampleRate = (double) info->rate;
|
||||
|
||||
reservoir.setSize ((int) numChannels, (int) jmin (lengthInSamples, (int64) 4096));
|
||||
}
|
||||
}
|
||||
|
||||
~OggReader() override
|
||||
{
|
||||
ov_clear (&ovFile);
|
||||
}
|
||||
|
||||
void addMetadataItem (OggVorbisNamespace::vorbis_comment* comment, const char* name, const char* metadataName)
|
||||
{
|
||||
if (auto* value = vorbis_comment_query (comment, name, 0))
|
||||
metadataValues.set (metadataName, value);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
const auto getBufferedRange = [this] { return bufferedRange; };
|
||||
|
||||
const auto readFromReservoir = [this, &destSamples, &numDestChannels, &startOffsetInDestBuffer, &startSampleInFile] (const Range<int64> rangeToRead)
|
||||
{
|
||||
const auto bufferIndices = rangeToRead - bufferedRange.getStart();
|
||||
const auto writePos = (int64) startOffsetInDestBuffer + (rangeToRead.getStart() - startSampleInFile);
|
||||
|
||||
for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
memcpy (destSamples[i] + writePos,
|
||||
reservoir.getReadPointer (i) + bufferIndices.getStart(),
|
||||
(size_t) bufferIndices.getLength() * sizeof (float));
|
||||
};
|
||||
|
||||
const auto fillReservoir = [this] (int64 requestedStart)
|
||||
{
|
||||
const auto newStart = jmax ((int64) 0, requestedStart);
|
||||
bufferedRange = Range<int64> { newStart, newStart + reservoir.getNumSamples() };
|
||||
|
||||
if (bufferedRange.getStart() != ov_pcm_tell (&ovFile))
|
||||
ov_pcm_seek (&ovFile, bufferedRange.getStart());
|
||||
|
||||
int bitStream = 0;
|
||||
int offset = 0;
|
||||
int numToRead = (int) bufferedRange.getLength();
|
||||
|
||||
while (numToRead > 0)
|
||||
{
|
||||
float** dataIn = nullptr;
|
||||
auto samps = static_cast<int> (ov_read_float (&ovFile, &dataIn, numToRead, &bitStream));
|
||||
|
||||
if (samps <= 0)
|
||||
break;
|
||||
|
||||
jassert (samps <= numToRead);
|
||||
|
||||
for (int i = jmin ((int) numChannels, reservoir.getNumChannels()); --i >= 0;)
|
||||
memcpy (reservoir.getWritePointer (i, offset), dataIn[i], (size_t) samps * sizeof (float));
|
||||
|
||||
numToRead -= samps;
|
||||
offset += samps;
|
||||
}
|
||||
|
||||
if (numToRead > 0)
|
||||
reservoir.clear (offset, numToRead);
|
||||
};
|
||||
|
||||
const auto remainingSamples = Reservoir::doBufferedRead (Range<int64> { startSampleInFile, startSampleInFile + numSamples },
|
||||
getBufferedRange,
|
||||
readFromReservoir,
|
||||
fillReservoir);
|
||||
|
||||
if (! remainingSamples.isEmpty())
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer + (remainingSamples.getStart() - startSampleInFile),
|
||||
(size_t) remainingSamples.getLength() * sizeof (int));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource)
|
||||
{
|
||||
return (size_t) (static_cast<InputStream*> (datasource)->read (ptr, (int) (size * nmemb))) / size;
|
||||
}
|
||||
|
||||
static int oggSeekCallback (void* datasource, OggVorbisNamespace::ogg_int64_t offset, int whence)
|
||||
{
|
||||
auto* in = static_cast<InputStream*> (datasource);
|
||||
|
||||
if (whence == SEEK_CUR)
|
||||
offset += in->getPosition();
|
||||
else if (whence == SEEK_END)
|
||||
offset += in->getTotalLength();
|
||||
|
||||
in->setPosition (offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int oggCloseCallback (void*)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static long oggTellCallback (void* datasource)
|
||||
{
|
||||
return (long) static_cast<InputStream*> (datasource)->getPosition();
|
||||
}
|
||||
|
||||
private:
|
||||
OggVorbisNamespace::OggVorbis_File ovFile;
|
||||
OggVorbisNamespace::ov_callbacks callbacks;
|
||||
AudioBuffer<float> reservoir;
|
||||
Range<int64> bufferedRange;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggReader)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class OggWriter final : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
OggWriter (OutputStream* out, double rate,
|
||||
unsigned int numChans, unsigned int bitsPerSamp,
|
||||
int qualityIndex, const StringPairArray& metadata)
|
||||
: AudioFormatWriter (out, oggFormatName, rate, numChans, bitsPerSamp)
|
||||
{
|
||||
vorbis_info_init (&vi);
|
||||
|
||||
if (vorbis_encode_init_vbr (&vi, (int) numChans, (int) rate,
|
||||
jlimit (0.0f, 1.0f, (float) qualityIndex * 0.1f)) == 0)
|
||||
{
|
||||
vorbis_comment_init (&vc);
|
||||
|
||||
addMetadata (metadata, OggVorbisAudioFormat::encoderName, "ENCODER");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3title, "TITLE");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3artist, "ARTIST");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3album, "ALBUM");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3comment, "COMMENT");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3date, "DATE");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3genre, "GENRE");
|
||||
addMetadata (metadata, OggVorbisAudioFormat::id3trackNumber, "TRACKNUMBER");
|
||||
|
||||
vorbis_analysis_init (&vd, &vi);
|
||||
vorbis_block_init (&vd, &vb);
|
||||
|
||||
ogg_stream_init (&os, Random::getSystemRandom().nextInt());
|
||||
|
||||
OggVorbisNamespace::ogg_packet header, header_comm, header_code;
|
||||
vorbis_analysis_headerout (&vd, &vc, &header, &header_comm, &header_code);
|
||||
|
||||
ogg_stream_packetin (&os, &header);
|
||||
ogg_stream_packetin (&os, &header_comm);
|
||||
ogg_stream_packetin (&os, &header_code);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (ogg_stream_flush (&os, &og) == 0)
|
||||
break;
|
||||
|
||||
output->write (og.header, (size_t) og.header_len);
|
||||
output->write (og.body, (size_t) og.body_len);
|
||||
}
|
||||
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
~OggWriter() override
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
// write a zero-length packet to show ogg that we're finished..
|
||||
writeSamples (0);
|
||||
|
||||
ogg_stream_clear (&os);
|
||||
vorbis_block_clear (&vb);
|
||||
vorbis_dsp_clear (&vd);
|
||||
vorbis_comment_clear (&vc);
|
||||
|
||||
vorbis_info_clear (&vi);
|
||||
output->flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
vorbis_info_clear (&vi);
|
||||
output = nullptr; // to stop the base class deleting this, as it needs to be returned
|
||||
// to the caller of createWriter()
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (const int** samplesToWrite, int numSamples) override
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
if (numSamples > 0)
|
||||
{
|
||||
const double gain = 1.0 / 0x80000000u;
|
||||
float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples);
|
||||
|
||||
for (int i = (int) numChannels; --i >= 0;)
|
||||
{
|
||||
if (auto* dst = vorbisBuffer[i])
|
||||
{
|
||||
if (const int* src = samplesToWrite [i])
|
||||
{
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
dst[j] = (float) (src[j] * gain);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeSamples (numSamples);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void writeSamples (int numSamples)
|
||||
{
|
||||
vorbis_analysis_wrote (&vd, numSamples);
|
||||
|
||||
while (vorbis_analysis_blockout (&vd, &vb) == 1)
|
||||
{
|
||||
vorbis_analysis (&vb, nullptr);
|
||||
vorbis_bitrate_addblock (&vb);
|
||||
|
||||
while (vorbis_bitrate_flushpacket (&vd, &op))
|
||||
{
|
||||
ogg_stream_packetin (&os, &op);
|
||||
|
||||
for (;;)
|
||||
{
|
||||
if (ogg_stream_pageout (&os, &og) == 0)
|
||||
break;
|
||||
|
||||
output->write (og.header, (size_t) og.header_len);
|
||||
output->write (og.body, (size_t) og.body_len);
|
||||
|
||||
if (ogg_page_eos (&og))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
|
||||
private:
|
||||
OggVorbisNamespace::ogg_stream_state os;
|
||||
OggVorbisNamespace::ogg_page og;
|
||||
OggVorbisNamespace::ogg_packet op;
|
||||
OggVorbisNamespace::vorbis_info vi;
|
||||
OggVorbisNamespace::vorbis_comment vc;
|
||||
OggVorbisNamespace::vorbis_dsp_state vd;
|
||||
OggVorbisNamespace::vorbis_block vb;
|
||||
|
||||
void addMetadata (const StringPairArray& metadata, const char* name, const char* vorbisName)
|
||||
{
|
||||
auto s = metadata [name];
|
||||
|
||||
if (s.isNotEmpty())
|
||||
vorbis_comment_add_tag (&vc, vorbisName, const_cast<char*> (s.toRawUTF8()));
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggWriter)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
OggVorbisAudioFormat::OggVorbisAudioFormat() : AudioFormat (oggFormatName, ".ogg")
|
||||
{
|
||||
}
|
||||
|
||||
OggVorbisAudioFormat::~OggVorbisAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
Array<int> OggVorbisAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
return { 8000, 11025, 12000, 16000, 22050, 32000,
|
||||
44100, 48000, 88200, 96000, 176400, 192000 };
|
||||
}
|
||||
|
||||
Array<int> OggVorbisAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
return { 32 };
|
||||
}
|
||||
|
||||
bool OggVorbisAudioFormat::canDoStereo() { return true; }
|
||||
bool OggVorbisAudioFormat::canDoMono() { return true; }
|
||||
bool OggVorbisAudioFormat::isCompressed() { return true; }
|
||||
|
||||
AudioFormatReader* OggVorbisAudioFormat::createReaderFor (InputStream* in, bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
std::unique_ptr<OggReader> r (new OggReader (in));
|
||||
|
||||
if (r->sampleRate > 0)
|
||||
return r.release();
|
||||
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* OggVorbisAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
if (out == nullptr)
|
||||
return nullptr;
|
||||
|
||||
std::unique_ptr<OggWriter> w (new OggWriter (out, sampleRate, numChannels,
|
||||
(unsigned int) bitsPerSample,
|
||||
qualityOptionIndex, metadataValues));
|
||||
|
||||
return w->ok ? w.release() : nullptr;
|
||||
}
|
||||
|
||||
StringArray OggVorbisAudioFormat::getQualityOptions()
|
||||
{
|
||||
return { "64 kbps", "80 kbps", "96 kbps", "112 kbps", "128 kbps", "160 kbps",
|
||||
"192 kbps", "224 kbps", "256 kbps", "320 kbps", "500 kbps" };
|
||||
}
|
||||
|
||||
int OggVorbisAudioFormat::estimateOggFileQuality (const File& source)
|
||||
{
|
||||
if (auto in = source.createInputStream())
|
||||
{
|
||||
if (auto r = std::unique_ptr<AudioFormatReader> (createReaderFor (in.release(), true)))
|
||||
{
|
||||
auto lengthSecs = (double) r->lengthInSamples / r->sampleRate;
|
||||
auto approxBitsPerSecond = (int) ((double) source.getSize() * 8 / lengthSecs);
|
||||
|
||||
auto qualities = getQualityOptions();
|
||||
int bestIndex = 0;
|
||||
int bestDiff = 10000;
|
||||
|
||||
for (int i = qualities.size(); --i >= 0;)
|
||||
{
|
||||
auto diff = std::abs (qualities[i].getIntValue() - approxBitsPerSecond);
|
||||
|
||||
if (diff < bestDiff)
|
||||
{
|
||||
bestDiff = diff;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return bestIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_USE_OGGVORBIS || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and writes the Ogg-Vorbis audio format.
|
||||
|
||||
To compile this, you'll need to set the JUCE_USE_OGGVORBIS flag.
|
||||
|
||||
@see AudioFormat,
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API OggVorbisAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
OggVorbisAudioFormat();
|
||||
~OggVorbisAudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
bool isCompressed() override;
|
||||
StringArray getQualityOptions() override;
|
||||
|
||||
//==============================================================================
|
||||
/** Tries to estimate the quality level of an ogg file based on its size.
|
||||
|
||||
If it can't read the file for some reason, this will just return 1 (medium quality),
|
||||
otherwise it will return the approximate quality setting that would have been used
|
||||
to create the file.
|
||||
|
||||
@see getQualityOptions
|
||||
*/
|
||||
int estimateOggFileQuality (const File& source);
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used by the Ogg writer - if you set a string for this
|
||||
value, it will be written into the ogg file as the name of the encoder app.
|
||||
|
||||
@see createWriterFor
|
||||
*/
|
||||
static const char* const encoderName;
|
||||
|
||||
static const char* const id3title; /**< Metadata key for setting an ID3 title. */
|
||||
static const char* const id3artist; /**< Metadata key for setting an ID3 artist name. */
|
||||
static const char* const id3album; /**< Metadata key for setting an ID3 album. */
|
||||
static const char* const id3comment; /**< Metadata key for setting an ID3 comment. */
|
||||
static const char* const id3date; /**< Metadata key for setting an ID3 date. */
|
||||
static const char* const id3genre; /**< Metadata key for setting an ID3 genre. */
|
||||
static const char* const id3trackNumber; /**< Metadata key for setting an ID3 track number. */
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggVorbisAudioFormat)
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
} // namespace juce
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,328 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and Writes WAV format audio files.
|
||||
|
||||
@see AudioFormat
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class JUCE_API WavAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a format object. */
|
||||
WavAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~WavAudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
// BWAV chunk properties:
|
||||
|
||||
static const char* const bwavDescription; /**< Metadata property name used in BWAV chunks. */
|
||||
static const char* const bwavOriginator; /**< Metadata property name used in BWAV chunks. */
|
||||
static const char* const bwavOriginatorRef; /**< Metadata property name used in BWAV chunks. */
|
||||
static const char* const bwavOriginationDate; /**< Metadata property name used in BWAV chunks. The format should be: yyyy-mm-dd */
|
||||
static const char* const bwavOriginationTime; /**< Metadata property name used in BWAV chunks. The format should be: format is: hh-mm-ss */
|
||||
static const char* const bwavCodingHistory; /**< Metadata property name used in BWAV chunks. */
|
||||
|
||||
/** Metadata property name used in BWAV chunks.
|
||||
This is the number of samples from the start of an edit that the
|
||||
file is supposed to begin at. Seems like an obvious mistake to
|
||||
only allow a file to occur in an edit once, but that's the way
|
||||
it is..
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavTimeReference;
|
||||
|
||||
/** Utility function to fill out the appropriate metadata for a BWAV file.
|
||||
|
||||
This just makes it easier than using the property names directly, and it
|
||||
fills out the time and date in the right format.
|
||||
*/
|
||||
static StringPairArray createBWAVMetadata (const String& description,
|
||||
const String& originator,
|
||||
const String& originatorRef,
|
||||
Time dateAndTime,
|
||||
int64 timeReferenceSamples,
|
||||
const String& codingHistory);
|
||||
|
||||
//==============================================================================
|
||||
// 'acid' chunk properties:
|
||||
|
||||
static const char* const acidOneShot; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidRootSet; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidStretch; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidDiskBased; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidizerFlag; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidRootNote; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidBeats; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidDenominator; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidNumerator; /**< Metadata property name used in acid chunks. */
|
||||
static const char* const acidTempo; /**< Metadata property name used in acid chunks. */
|
||||
|
||||
//==============================================================================
|
||||
// INFO chunk properties:
|
||||
|
||||
static const char* const riffInfoArchivalLocation; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoArtist; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoBaseURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoCinematographer; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoComment; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoComment2; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoComments; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoCommissioned; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoCopyright; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoCostumeDesigner; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoCountry; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoCropped; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDateCreated; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDateTimeOriginal; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDefaultAudioStream; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDimension; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDirectory; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDistributedBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoDotsPerInch; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoEditedBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoEighthLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoEncodedBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoEndTimecode; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoEngineer; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoFifthLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoFirstLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoFourthLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoGenre; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoKeywords; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoLength; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoLightness; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoLocation; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoLogoIconURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoLogoURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoMedium; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoMoreInfoBannerImage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoMoreInfoBannerURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoMoreInfoText; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoMoreInfoURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoMusicBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoNinthLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoNumberOfParts; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoOrganisation; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoPart; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoProducedBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoProductName; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoProductionDesigner; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoProductionStudio; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoRate; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoRated; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoRating; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoRippedBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSecondaryGenre; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSecondLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSeventhLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSharpness; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSixthLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSoftware; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSoundSchemeTitle; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSource; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSourceFrom; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoStarring_ISTR; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoStarring_STAR; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoStartTimecode; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoStatistics; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoSubject; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoTapeName; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoTechnician; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoThirdLanguage; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoTimeCode; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoTitle; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoTrackNo; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoTrackNumber; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoVegasVersionMajor; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoVegasVersionMinor; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoVersion; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoWatermarkURL; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoWrittenBy; /**< Metadata property name used in INFO chunks. */
|
||||
static const char* const riffInfoYear; /**< Metadata property name used in INFO chunks. */
|
||||
|
||||
//==============================================================================
|
||||
// ASWG chunk properties:
|
||||
|
||||
static const char* const aswgContentType; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgProject; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgOriginator; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgOriginatorStudio; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgNotes; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgSession; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgState; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgEditor; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMixer; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgFxChainName; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgChannelConfig; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgAmbisonicFormat; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgAmbisonicChnOrder; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgAmbisonicNorm; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMicType; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMicConfig; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMicDistance; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgRecordingLoc; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsDesigned; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgRecEngineer; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgRecStudio; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgImpulseLocation; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCategory; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgSubCategory; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCatId; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgUserCategory; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgUserData; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgVendorCategory; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgFxName; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgLibrary; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCreatorId; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgSourceId; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgRmsPower; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgLoudness; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgLoudnessRange; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMaxPeak; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgSpecDensity; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgZeroCrossRate; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgPapr; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgText; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgEfforts; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgEffortType; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgProjection; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgLanguage; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgTimingRestriction; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCharacterName; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCharacterGender; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCharacterAge; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgCharacterRole; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgActorName; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgActorGender; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgDirector; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgDirection; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgFxUsed; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgUsageRights; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsUnion; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgAccent; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgEmotion; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgComposor; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgArtist; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgSongTitle; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgGenre; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgSubGenre; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgProducer; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMusicSup; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgInstrument; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMusicPublisher; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgRightsOwner; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsSource; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsLoop; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIntensity; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsFinal; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgOrderRef; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsOst; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsCinematic; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsLicensed; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsDiegetic; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgMusicVersion; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgIsrcId; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgTempo; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgTimeSig; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgInKey; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgBillingCode; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
static const char* const aswgVersion; /**< Metadata property name used in ASWG/iXML chunks. */
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used when reading an ISRC code from an AXML chunk. */
|
||||
[[deprecated ("This string is identical to riffInfoSource, making it impossible to differentiate between the two")]]
|
||||
static const char* const ISRC;
|
||||
|
||||
/** Metadata property name used when reading and writing ISRC codes to/from AXML chunks. */
|
||||
static const char* const internationalStandardRecordingCode;
|
||||
|
||||
/** Metadata property name used when reading a WAV file with a Tracktion chunk. */
|
||||
static const char* const tracktionLoopInfo;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
bool isChannelLayoutSupported (const AudioChannelSet& channelSet) override;
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
MemoryMappedAudioFormatReader* createMemoryMappedReader (const File&) override;
|
||||
MemoryMappedAudioFormatReader* createMemoryMappedReader (FileInputStream*) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
const AudioChannelSet& channelLayout,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
|
||||
//==============================================================================
|
||||
/** Utility function to replace the metadata in a wav file with a new set of values.
|
||||
|
||||
If possible, this cheats by overwriting just the metadata region of the file, rather
|
||||
than by copying the whole file again.
|
||||
*/
|
||||
bool replaceMetadataInFile (const File& wavFile, const StringPairArray& newMetadata);
|
||||
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WavAudioFormat)
|
||||
};
|
||||
|
||||
} // namespace juce
|
||||
+1126
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE framework.
|
||||
Copyright (c) Raw Material Software Limited
|
||||
|
||||
JUCE is an open source framework subject to commercial or open source
|
||||
licensing.
|
||||
|
||||
By downloading, installing, or using the JUCE framework, or combining the
|
||||
JUCE framework with any other source code, object code, content or any other
|
||||
copyrightable work, you agree to the terms of the JUCE End User Licence
|
||||
Agreement, and all incorporated terms including the JUCE Privacy Policy and
|
||||
the JUCE Website Terms of Service, as applicable, which will bind you. If you
|
||||
do not agree to the terms of these agreements, we will not license the JUCE
|
||||
framework to you, and you must discontinue the installation or download
|
||||
process and cease use of the JUCE framework.
|
||||
|
||||
JUCE End User Licence Agreement: https://juce.com/legal/juce-8-licence/
|
||||
JUCE Privacy Policy: https://juce.com/juce-privacy-policy
|
||||
JUCE Website Terms of Service: https://juce.com/juce-website-terms-of-service/
|
||||
|
||||
Or:
|
||||
|
||||
You may also use this code under the terms of the AGPLv3:
|
||||
https://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
|
||||
THE JUCE FRAMEWORK IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL
|
||||
WARRANTIES, WHETHER EXPRESSED OR IMPLIED, INCLUDING WARRANTY OF
|
||||
MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, ARE DISCLAIMED.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
#if JUCE_WINDOWS || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Audio format which uses the Windows Media codecs (Windows only).
|
||||
|
||||
@tags{Audio}
|
||||
*/
|
||||
class WindowsMediaAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
WindowsMediaAudioFormat();
|
||||
~WindowsMediaAudioFormat() override;
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates() override;
|
||||
Array<int> getPossibleBitDepths() override;
|
||||
bool canDoStereo() override;
|
||||
bool canDoMono() override;
|
||||
bool isCompressed() override;
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream*, bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream*, double sampleRateToUse,
|
||||
unsigned int numberOfChannels, int bitsPerSample,
|
||||
const StringPairArray& metadataValues, int qualityOptionIndex) override;
|
||||
using AudioFormat::createWriterFor;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
=====================================================================
|
||||
|
||||
Ogg-Vorbis is incorporated directly into the JUCE codebase because it makes
|
||||
things much easier than having to make all your builds link correctly to
|
||||
the appropriate libraries on every different platform.
|
||||
|
||||
There are minimal changes to the Ogg-Vorbis code - a few include paths have
|
||||
been changed to make it build smoothly, and some headers have been added to
|
||||
allow you to exclude it from the build. Any significant code modifications
|
||||
are marked clearly by "JUCE CHANGE STARTS HERE" and "JUCE CHANGE ENDS HERE"
|
||||
comments.
|
||||
|
||||
=====================================================================
|
||||
|
||||
The following license is the BSD-style license that comes with the Ogg-Vorbis
|
||||
distribution, and which applies just to the header files included in this
|
||||
directory. For more info, and to get the rest of the distribution, visit the
|
||||
Ogg-Vorbis homepage: https://xiph.org/vorbis
|
||||
|
||||
=====================================================================
|
||||
|
||||
Copyright (c) 2002-2020 Xiph.org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,241 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _vorbis_codec_h_
|
||||
#define _vorbis_codec_h_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
typedef struct vorbis_info{
|
||||
int version;
|
||||
int channels;
|
||||
long rate;
|
||||
|
||||
/* The below bitrate declarations are *hints*.
|
||||
Combinations of the three values carry the following implications:
|
||||
|
||||
all three set to the same value:
|
||||
implies a fixed rate bitstream
|
||||
only nominal set:
|
||||
implies a VBR stream that averages the nominal bitrate. No hard
|
||||
upper/lower limit
|
||||
upper and or lower set:
|
||||
implies a VBR bitstream that obeys the bitrate limits. nominal
|
||||
may also be set to give a nominal rate.
|
||||
none set:
|
||||
the coder does not care to speculate.
|
||||
*/
|
||||
|
||||
long bitrate_upper;
|
||||
long bitrate_nominal;
|
||||
long bitrate_lower;
|
||||
long bitrate_window;
|
||||
|
||||
void *codec_setup;
|
||||
} vorbis_info;
|
||||
|
||||
/* vorbis_dsp_state buffers the current vorbis audio
|
||||
analysis/synthesis state. The DSP state belongs to a specific
|
||||
logical bitstream ****************************************************/
|
||||
typedef struct vorbis_dsp_state{
|
||||
int analysisp;
|
||||
vorbis_info *vi;
|
||||
|
||||
float **pcm;
|
||||
float **pcmret;
|
||||
int pcm_storage;
|
||||
int pcm_current;
|
||||
int pcm_returned;
|
||||
|
||||
int preextrapolate;
|
||||
int eofflag;
|
||||
|
||||
long lW;
|
||||
long W;
|
||||
long nW;
|
||||
long centerW;
|
||||
|
||||
ogg_int64_t granulepos;
|
||||
ogg_int64_t sequence;
|
||||
|
||||
ogg_int64_t glue_bits;
|
||||
ogg_int64_t time_bits;
|
||||
ogg_int64_t floor_bits;
|
||||
ogg_int64_t res_bits;
|
||||
|
||||
void *backend_state;
|
||||
} vorbis_dsp_state;
|
||||
|
||||
typedef struct vorbis_block{
|
||||
/* necessary stream state for linking to the framing abstraction */
|
||||
float **pcm; /* this is a pointer into local storage */
|
||||
oggpack_buffer opb;
|
||||
|
||||
long lW;
|
||||
long W;
|
||||
long nW;
|
||||
int pcmend;
|
||||
int mode;
|
||||
|
||||
int eofflag;
|
||||
ogg_int64_t granulepos;
|
||||
ogg_int64_t sequence;
|
||||
vorbis_dsp_state *vd; /* For read-only access of configuration */
|
||||
|
||||
/* local storage to avoid remallocing; it's up to the mapping to
|
||||
structure it */
|
||||
void *localstore;
|
||||
long localtop;
|
||||
long localalloc;
|
||||
long totaluse;
|
||||
struct alloc_chain *reap;
|
||||
|
||||
/* bitmetrics for the frame */
|
||||
long glue_bits;
|
||||
long time_bits;
|
||||
long floor_bits;
|
||||
long res_bits;
|
||||
|
||||
void *internal;
|
||||
|
||||
} vorbis_block;
|
||||
|
||||
/* vorbis_block is a single block of data to be processed as part of
|
||||
the analysis/synthesis stream; it belongs to a specific logical
|
||||
bitstream, but is independent from other vorbis_blocks belonging to
|
||||
that logical bitstream. *************************************************/
|
||||
|
||||
struct alloc_chain{
|
||||
void *ptr;
|
||||
struct alloc_chain *next;
|
||||
};
|
||||
|
||||
/* vorbis_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc). vorbis_info and substructures are in backends.h.
|
||||
*********************************************************************/
|
||||
|
||||
/* the comments are not part of vorbis_info so that vorbis_info can be
|
||||
static storage */
|
||||
typedef struct vorbis_comment{
|
||||
/* unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
whatever vendor is set to in encode */
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int comments;
|
||||
char *vendor;
|
||||
|
||||
} vorbis_comment;
|
||||
|
||||
|
||||
/* libvorbis encodes in two abstraction layers; first we perform DSP
|
||||
and produce a packet (see docs/analysis.txt). The packet is then
|
||||
coded into a framed OggSquish bitstream by the second layer (see
|
||||
docs/framing.txt). Decode is the reverse process; we sync/frame
|
||||
the bitstream and extract individual packets, then decode the
|
||||
packet back into PCM audio.
|
||||
|
||||
The extra framing/packetizing is used in streaming formats, such as
|
||||
files. Over the net (such as with UDP), the framing and
|
||||
packetization aren't necessary as they're provided by the transport
|
||||
and the streaming layer is not used */
|
||||
|
||||
/* Vorbis PRIMITIVES: general ***************************************/
|
||||
|
||||
extern void vorbis_info_init(vorbis_info *vi);
|
||||
extern void vorbis_info_clear(vorbis_info *vi);
|
||||
extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
|
||||
extern void vorbis_comment_init(vorbis_comment *vc);
|
||||
extern void vorbis_comment_add(vorbis_comment *vc, const char *comment);
|
||||
extern void vorbis_comment_add_tag(vorbis_comment *vc,
|
||||
const char *tag, const char *contents);
|
||||
extern char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count);
|
||||
extern int vorbis_comment_query_count(vorbis_comment *vc, const char *tag);
|
||||
extern void vorbis_comment_clear(vorbis_comment *vc);
|
||||
|
||||
extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
|
||||
extern int vorbis_block_clear(vorbis_block *vb);
|
||||
extern void vorbis_dsp_clear(vorbis_dsp_state *v);
|
||||
extern double vorbis_granule_time(vorbis_dsp_state *v,
|
||||
ogg_int64_t granulepos);
|
||||
|
||||
extern const char *vorbis_version_string(void);
|
||||
|
||||
/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
|
||||
|
||||
extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op);
|
||||
extern int vorbis_analysis_headerout(vorbis_dsp_state *v,
|
||||
vorbis_comment *vc,
|
||||
ogg_packet *op,
|
||||
ogg_packet *op_comm,
|
||||
ogg_packet *op_code);
|
||||
extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op);
|
||||
|
||||
extern int vorbis_bitrate_addblock(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,
|
||||
ogg_packet *op);
|
||||
|
||||
/* Vorbis PRIMITIVES: synthesis layer *******************************/
|
||||
extern int vorbis_synthesis_idheader(ogg_packet *op);
|
||||
extern int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,
|
||||
ogg_packet *op);
|
||||
|
||||
extern int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_synthesis_restart(vorbis_dsp_state *v);
|
||||
extern int vorbis_synthesis(vorbis_block *vb,ogg_packet *op);
|
||||
extern int vorbis_synthesis_trackonly(vorbis_block *vb,ogg_packet *op);
|
||||
extern int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm);
|
||||
extern int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm);
|
||||
extern int vorbis_synthesis_read(vorbis_dsp_state *v,int samples);
|
||||
extern long vorbis_packet_blocksize(vorbis_info *vi,ogg_packet *op);
|
||||
|
||||
extern int vorbis_synthesis_halfrate(vorbis_info *v,int flag);
|
||||
extern int vorbis_synthesis_halfrate_p(vorbis_info *v);
|
||||
|
||||
/* Vorbis ERRORS and return codes ***********************************/
|
||||
|
||||
#define OV_FALSE -1
|
||||
#define OV_EOF -2
|
||||
#define OV_HOLE -3
|
||||
|
||||
#define OV_EREAD -128
|
||||
#define OV_EFAULT -129
|
||||
#define OV_EIMPL -130
|
||||
#define OV_EINVAL -131
|
||||
#define OV_ENOTVORBIS -132
|
||||
#define OV_EBADHEADER -133
|
||||
#define OV_EVERSION -134
|
||||
#define OV_ENOTAUDIO -135
|
||||
#define OV_EBADPACKET -136
|
||||
#define OV_EBADLINK -137
|
||||
#define OV_ENOSEEK -138
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,14 @@
|
||||
#ifndef __CONFIG_TYPES_H__
|
||||
#define __CONFIG_TYPES_H__
|
||||
|
||||
typedef int16_t ogg_int16_t;
|
||||
typedef unsigned short ogg_uint16_t;
|
||||
typedef int32_t ogg_int32_t;
|
||||
typedef unsigned int ogg_uint32_t;
|
||||
typedef int64_t ogg_int64_t;
|
||||
|
||||
// JUCE CHANGE STARTS HERE
|
||||
typedef unsigned long long ogg_uint64_t;
|
||||
// JUCE CHANGE ENDS HERE
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,278 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE Ogg CONTAINER SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2018 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************/
|
||||
|
||||
#include "os_types.h"
|
||||
|
||||
static const ogg_uint32_t crc_lookup[8][256]={
|
||||
{0x00000000,0x04c11db7,0x09823b6e,0x0d4326d9,0x130476dc,0x17c56b6b,0x1a864db2,0x1e475005,
|
||||
0x2608edb8,0x22c9f00f,0x2f8ad6d6,0x2b4bcb61,0x350c9b64,0x31cd86d3,0x3c8ea00a,0x384fbdbd,
|
||||
0x4c11db70,0x48d0c6c7,0x4593e01e,0x4152fda9,0x5f15adac,0x5bd4b01b,0x569796c2,0x52568b75,
|
||||
0x6a1936c8,0x6ed82b7f,0x639b0da6,0x675a1011,0x791d4014,0x7ddc5da3,0x709f7b7a,0x745e66cd,
|
||||
0x9823b6e0,0x9ce2ab57,0x91a18d8e,0x95609039,0x8b27c03c,0x8fe6dd8b,0x82a5fb52,0x8664e6e5,
|
||||
0xbe2b5b58,0xbaea46ef,0xb7a96036,0xb3687d81,0xad2f2d84,0xa9ee3033,0xa4ad16ea,0xa06c0b5d,
|
||||
0xd4326d90,0xd0f37027,0xddb056fe,0xd9714b49,0xc7361b4c,0xc3f706fb,0xceb42022,0xca753d95,
|
||||
0xf23a8028,0xf6fb9d9f,0xfbb8bb46,0xff79a6f1,0xe13ef6f4,0xe5ffeb43,0xe8bccd9a,0xec7dd02d,
|
||||
0x34867077,0x30476dc0,0x3d044b19,0x39c556ae,0x278206ab,0x23431b1c,0x2e003dc5,0x2ac12072,
|
||||
0x128e9dcf,0x164f8078,0x1b0ca6a1,0x1fcdbb16,0x018aeb13,0x054bf6a4,0x0808d07d,0x0cc9cdca,
|
||||
0x7897ab07,0x7c56b6b0,0x71159069,0x75d48dde,0x6b93dddb,0x6f52c06c,0x6211e6b5,0x66d0fb02,
|
||||
0x5e9f46bf,0x5a5e5b08,0x571d7dd1,0x53dc6066,0x4d9b3063,0x495a2dd4,0x44190b0d,0x40d816ba,
|
||||
0xaca5c697,0xa864db20,0xa527fdf9,0xa1e6e04e,0xbfa1b04b,0xbb60adfc,0xb6238b25,0xb2e29692,
|
||||
0x8aad2b2f,0x8e6c3698,0x832f1041,0x87ee0df6,0x99a95df3,0x9d684044,0x902b669d,0x94ea7b2a,
|
||||
0xe0b41de7,0xe4750050,0xe9362689,0xedf73b3e,0xf3b06b3b,0xf771768c,0xfa325055,0xfef34de2,
|
||||
0xc6bcf05f,0xc27dede8,0xcf3ecb31,0xcbffd686,0xd5b88683,0xd1799b34,0xdc3abded,0xd8fba05a,
|
||||
0x690ce0ee,0x6dcdfd59,0x608edb80,0x644fc637,0x7a089632,0x7ec98b85,0x738aad5c,0x774bb0eb,
|
||||
0x4f040d56,0x4bc510e1,0x46863638,0x42472b8f,0x5c007b8a,0x58c1663d,0x558240e4,0x51435d53,
|
||||
0x251d3b9e,0x21dc2629,0x2c9f00f0,0x285e1d47,0x36194d42,0x32d850f5,0x3f9b762c,0x3b5a6b9b,
|
||||
0x0315d626,0x07d4cb91,0x0a97ed48,0x0e56f0ff,0x1011a0fa,0x14d0bd4d,0x19939b94,0x1d528623,
|
||||
0xf12f560e,0xf5ee4bb9,0xf8ad6d60,0xfc6c70d7,0xe22b20d2,0xe6ea3d65,0xeba91bbc,0xef68060b,
|
||||
0xd727bbb6,0xd3e6a601,0xdea580d8,0xda649d6f,0xc423cd6a,0xc0e2d0dd,0xcda1f604,0xc960ebb3,
|
||||
0xbd3e8d7e,0xb9ff90c9,0xb4bcb610,0xb07daba7,0xae3afba2,0xaafbe615,0xa7b8c0cc,0xa379dd7b,
|
||||
0x9b3660c6,0x9ff77d71,0x92b45ba8,0x9675461f,0x8832161a,0x8cf30bad,0x81b02d74,0x857130c3,
|
||||
0x5d8a9099,0x594b8d2e,0x5408abf7,0x50c9b640,0x4e8ee645,0x4a4ffbf2,0x470cdd2b,0x43cdc09c,
|
||||
0x7b827d21,0x7f436096,0x7200464f,0x76c15bf8,0x68860bfd,0x6c47164a,0x61043093,0x65c52d24,
|
||||
0x119b4be9,0x155a565e,0x18197087,0x1cd86d30,0x029f3d35,0x065e2082,0x0b1d065b,0x0fdc1bec,
|
||||
0x3793a651,0x3352bbe6,0x3e119d3f,0x3ad08088,0x2497d08d,0x2056cd3a,0x2d15ebe3,0x29d4f654,
|
||||
0xc5a92679,0xc1683bce,0xcc2b1d17,0xc8ea00a0,0xd6ad50a5,0xd26c4d12,0xdf2f6bcb,0xdbee767c,
|
||||
0xe3a1cbc1,0xe760d676,0xea23f0af,0xeee2ed18,0xf0a5bd1d,0xf464a0aa,0xf9278673,0xfde69bc4,
|
||||
0x89b8fd09,0x8d79e0be,0x803ac667,0x84fbdbd0,0x9abc8bd5,0x9e7d9662,0x933eb0bb,0x97ffad0c,
|
||||
0xafb010b1,0xab710d06,0xa6322bdf,0xa2f33668,0xbcb4666d,0xb8757bda,0xb5365d03,0xb1f740b4},
|
||||
|
||||
{0x00000000,0xd219c1dc,0xa0f29e0f,0x72eb5fd3,0x452421a9,0x973de075,0xe5d6bfa6,0x37cf7e7a,
|
||||
0x8a484352,0x5851828e,0x2abadd5d,0xf8a31c81,0xcf6c62fb,0x1d75a327,0x6f9efcf4,0xbd873d28,
|
||||
0x10519b13,0xc2485acf,0xb0a3051c,0x62bac4c0,0x5575baba,0x876c7b66,0xf58724b5,0x279ee569,
|
||||
0x9a19d841,0x4800199d,0x3aeb464e,0xe8f28792,0xdf3df9e8,0x0d243834,0x7fcf67e7,0xadd6a63b,
|
||||
0x20a33626,0xf2baf7fa,0x8051a829,0x524869f5,0x6587178f,0xb79ed653,0xc5758980,0x176c485c,
|
||||
0xaaeb7574,0x78f2b4a8,0x0a19eb7b,0xd8002aa7,0xefcf54dd,0x3dd69501,0x4f3dcad2,0x9d240b0e,
|
||||
0x30f2ad35,0xe2eb6ce9,0x9000333a,0x4219f2e6,0x75d68c9c,0xa7cf4d40,0xd5241293,0x073dd34f,
|
||||
0xbabaee67,0x68a32fbb,0x1a487068,0xc851b1b4,0xff9ecfce,0x2d870e12,0x5f6c51c1,0x8d75901d,
|
||||
0x41466c4c,0x935fad90,0xe1b4f243,0x33ad339f,0x04624de5,0xd67b8c39,0xa490d3ea,0x76891236,
|
||||
0xcb0e2f1e,0x1917eec2,0x6bfcb111,0xb9e570cd,0x8e2a0eb7,0x5c33cf6b,0x2ed890b8,0xfcc15164,
|
||||
0x5117f75f,0x830e3683,0xf1e56950,0x23fca88c,0x1433d6f6,0xc62a172a,0xb4c148f9,0x66d88925,
|
||||
0xdb5fb40d,0x094675d1,0x7bad2a02,0xa9b4ebde,0x9e7b95a4,0x4c625478,0x3e890bab,0xec90ca77,
|
||||
0x61e55a6a,0xb3fc9bb6,0xc117c465,0x130e05b9,0x24c17bc3,0xf6d8ba1f,0x8433e5cc,0x562a2410,
|
||||
0xebad1938,0x39b4d8e4,0x4b5f8737,0x994646eb,0xae893891,0x7c90f94d,0x0e7ba69e,0xdc626742,
|
||||
0x71b4c179,0xa3ad00a5,0xd1465f76,0x035f9eaa,0x3490e0d0,0xe689210c,0x94627edf,0x467bbf03,
|
||||
0xfbfc822b,0x29e543f7,0x5b0e1c24,0x8917ddf8,0xbed8a382,0x6cc1625e,0x1e2a3d8d,0xcc33fc51,
|
||||
0x828cd898,0x50951944,0x227e4697,0xf067874b,0xc7a8f931,0x15b138ed,0x675a673e,0xb543a6e2,
|
||||
0x08c49bca,0xdadd5a16,0xa83605c5,0x7a2fc419,0x4de0ba63,0x9ff97bbf,0xed12246c,0x3f0be5b0,
|
||||
0x92dd438b,0x40c48257,0x322fdd84,0xe0361c58,0xd7f96222,0x05e0a3fe,0x770bfc2d,0xa5123df1,
|
||||
0x189500d9,0xca8cc105,0xb8679ed6,0x6a7e5f0a,0x5db12170,0x8fa8e0ac,0xfd43bf7f,0x2f5a7ea3,
|
||||
0xa22feebe,0x70362f62,0x02dd70b1,0xd0c4b16d,0xe70bcf17,0x35120ecb,0x47f95118,0x95e090c4,
|
||||
0x2867adec,0xfa7e6c30,0x889533e3,0x5a8cf23f,0x6d438c45,0xbf5a4d99,0xcdb1124a,0x1fa8d396,
|
||||
0xb27e75ad,0x6067b471,0x128ceba2,0xc0952a7e,0xf75a5404,0x254395d8,0x57a8ca0b,0x85b10bd7,
|
||||
0x383636ff,0xea2ff723,0x98c4a8f0,0x4add692c,0x7d121756,0xaf0bd68a,0xdde08959,0x0ff94885,
|
||||
0xc3cab4d4,0x11d37508,0x63382adb,0xb121eb07,0x86ee957d,0x54f754a1,0x261c0b72,0xf405caae,
|
||||
0x4982f786,0x9b9b365a,0xe9706989,0x3b69a855,0x0ca6d62f,0xdebf17f3,0xac544820,0x7e4d89fc,
|
||||
0xd39b2fc7,0x0182ee1b,0x7369b1c8,0xa1707014,0x96bf0e6e,0x44a6cfb2,0x364d9061,0xe45451bd,
|
||||
0x59d36c95,0x8bcaad49,0xf921f29a,0x2b383346,0x1cf74d3c,0xceee8ce0,0xbc05d333,0x6e1c12ef,
|
||||
0xe36982f2,0x3170432e,0x439b1cfd,0x9182dd21,0xa64da35b,0x74546287,0x06bf3d54,0xd4a6fc88,
|
||||
0x6921c1a0,0xbb38007c,0xc9d35faf,0x1bca9e73,0x2c05e009,0xfe1c21d5,0x8cf77e06,0x5eeebfda,
|
||||
0xf33819e1,0x2121d83d,0x53ca87ee,0x81d34632,0xb61c3848,0x6405f994,0x16eea647,0xc4f7679b,
|
||||
0x79705ab3,0xab699b6f,0xd982c4bc,0x0b9b0560,0x3c547b1a,0xee4dbac6,0x9ca6e515,0x4ebf24c9},
|
||||
|
||||
{0x00000000,0x01d8ac87,0x03b1590e,0x0269f589,0x0762b21c,0x06ba1e9b,0x04d3eb12,0x050b4795,
|
||||
0x0ec56438,0x0f1dc8bf,0x0d743d36,0x0cac91b1,0x09a7d624,0x087f7aa3,0x0a168f2a,0x0bce23ad,
|
||||
0x1d8ac870,0x1c5264f7,0x1e3b917e,0x1fe33df9,0x1ae87a6c,0x1b30d6eb,0x19592362,0x18818fe5,
|
||||
0x134fac48,0x129700cf,0x10fef546,0x112659c1,0x142d1e54,0x15f5b2d3,0x179c475a,0x1644ebdd,
|
||||
0x3b1590e0,0x3acd3c67,0x38a4c9ee,0x397c6569,0x3c7722fc,0x3daf8e7b,0x3fc67bf2,0x3e1ed775,
|
||||
0x35d0f4d8,0x3408585f,0x3661add6,0x37b90151,0x32b246c4,0x336aea43,0x31031fca,0x30dbb34d,
|
||||
0x269f5890,0x2747f417,0x252e019e,0x24f6ad19,0x21fdea8c,0x2025460b,0x224cb382,0x23941f05,
|
||||
0x285a3ca8,0x2982902f,0x2beb65a6,0x2a33c921,0x2f388eb4,0x2ee02233,0x2c89d7ba,0x2d517b3d,
|
||||
0x762b21c0,0x77f38d47,0x759a78ce,0x7442d449,0x714993dc,0x70913f5b,0x72f8cad2,0x73206655,
|
||||
0x78ee45f8,0x7936e97f,0x7b5f1cf6,0x7a87b071,0x7f8cf7e4,0x7e545b63,0x7c3daeea,0x7de5026d,
|
||||
0x6ba1e9b0,0x6a794537,0x6810b0be,0x69c81c39,0x6cc35bac,0x6d1bf72b,0x6f7202a2,0x6eaaae25,
|
||||
0x65648d88,0x64bc210f,0x66d5d486,0x670d7801,0x62063f94,0x63de9313,0x61b7669a,0x606fca1d,
|
||||
0x4d3eb120,0x4ce61da7,0x4e8fe82e,0x4f5744a9,0x4a5c033c,0x4b84afbb,0x49ed5a32,0x4835f6b5,
|
||||
0x43fbd518,0x4223799f,0x404a8c16,0x41922091,0x44996704,0x4541cb83,0x47283e0a,0x46f0928d,
|
||||
0x50b47950,0x516cd5d7,0x5305205e,0x52dd8cd9,0x57d6cb4c,0x560e67cb,0x54679242,0x55bf3ec5,
|
||||
0x5e711d68,0x5fa9b1ef,0x5dc04466,0x5c18e8e1,0x5913af74,0x58cb03f3,0x5aa2f67a,0x5b7a5afd,
|
||||
0xec564380,0xed8eef07,0xefe71a8e,0xee3fb609,0xeb34f19c,0xeaec5d1b,0xe885a892,0xe95d0415,
|
||||
0xe29327b8,0xe34b8b3f,0xe1227eb6,0xe0fad231,0xe5f195a4,0xe4293923,0xe640ccaa,0xe798602d,
|
||||
0xf1dc8bf0,0xf0042777,0xf26dd2fe,0xf3b57e79,0xf6be39ec,0xf766956b,0xf50f60e2,0xf4d7cc65,
|
||||
0xff19efc8,0xfec1434f,0xfca8b6c6,0xfd701a41,0xf87b5dd4,0xf9a3f153,0xfbca04da,0xfa12a85d,
|
||||
0xd743d360,0xd69b7fe7,0xd4f28a6e,0xd52a26e9,0xd021617c,0xd1f9cdfb,0xd3903872,0xd24894f5,
|
||||
0xd986b758,0xd85e1bdf,0xda37ee56,0xdbef42d1,0xdee40544,0xdf3ca9c3,0xdd555c4a,0xdc8df0cd,
|
||||
0xcac91b10,0xcb11b797,0xc978421e,0xc8a0ee99,0xcdaba90c,0xcc73058b,0xce1af002,0xcfc25c85,
|
||||
0xc40c7f28,0xc5d4d3af,0xc7bd2626,0xc6658aa1,0xc36ecd34,0xc2b661b3,0xc0df943a,0xc10738bd,
|
||||
0x9a7d6240,0x9ba5cec7,0x99cc3b4e,0x981497c9,0x9d1fd05c,0x9cc77cdb,0x9eae8952,0x9f7625d5,
|
||||
0x94b80678,0x9560aaff,0x97095f76,0x96d1f3f1,0x93dab464,0x920218e3,0x906bed6a,0x91b341ed,
|
||||
0x87f7aa30,0x862f06b7,0x8446f33e,0x859e5fb9,0x8095182c,0x814db4ab,0x83244122,0x82fceda5,
|
||||
0x8932ce08,0x88ea628f,0x8a839706,0x8b5b3b81,0x8e507c14,0x8f88d093,0x8de1251a,0x8c39899d,
|
||||
0xa168f2a0,0xa0b05e27,0xa2d9abae,0xa3010729,0xa60a40bc,0xa7d2ec3b,0xa5bb19b2,0xa463b535,
|
||||
0xafad9698,0xae753a1f,0xac1ccf96,0xadc46311,0xa8cf2484,0xa9178803,0xab7e7d8a,0xaaa6d10d,
|
||||
0xbce23ad0,0xbd3a9657,0xbf5363de,0xbe8bcf59,0xbb8088cc,0xba58244b,0xb831d1c2,0xb9e97d45,
|
||||
0xb2275ee8,0xb3fff26f,0xb19607e6,0xb04eab61,0xb545ecf4,0xb49d4073,0xb6f4b5fa,0xb72c197d},
|
||||
|
||||
{0x00000000,0xdc6d9ab7,0xbc1a28d9,0x6077b26e,0x7cf54c05,0xa098d6b2,0xc0ef64dc,0x1c82fe6b,
|
||||
0xf9ea980a,0x258702bd,0x45f0b0d3,0x999d2a64,0x851fd40f,0x59724eb8,0x3905fcd6,0xe5686661,
|
||||
0xf7142da3,0x2b79b714,0x4b0e057a,0x97639fcd,0x8be161a6,0x578cfb11,0x37fb497f,0xeb96d3c8,
|
||||
0x0efeb5a9,0xd2932f1e,0xb2e49d70,0x6e8907c7,0x720bf9ac,0xae66631b,0xce11d175,0x127c4bc2,
|
||||
0xeae946f1,0x3684dc46,0x56f36e28,0x8a9ef49f,0x961c0af4,0x4a719043,0x2a06222d,0xf66bb89a,
|
||||
0x1303defb,0xcf6e444c,0xaf19f622,0x73746c95,0x6ff692fe,0xb39b0849,0xd3ecba27,0x0f812090,
|
||||
0x1dfd6b52,0xc190f1e5,0xa1e7438b,0x7d8ad93c,0x61082757,0xbd65bde0,0xdd120f8e,0x017f9539,
|
||||
0xe417f358,0x387a69ef,0x580ddb81,0x84604136,0x98e2bf5d,0x448f25ea,0x24f89784,0xf8950d33,
|
||||
0xd1139055,0x0d7e0ae2,0x6d09b88c,0xb164223b,0xade6dc50,0x718b46e7,0x11fcf489,0xcd916e3e,
|
||||
0x28f9085f,0xf49492e8,0x94e32086,0x488eba31,0x540c445a,0x8861deed,0xe8166c83,0x347bf634,
|
||||
0x2607bdf6,0xfa6a2741,0x9a1d952f,0x46700f98,0x5af2f1f3,0x869f6b44,0xe6e8d92a,0x3a85439d,
|
||||
0xdfed25fc,0x0380bf4b,0x63f70d25,0xbf9a9792,0xa31869f9,0x7f75f34e,0x1f024120,0xc36fdb97,
|
||||
0x3bfad6a4,0xe7974c13,0x87e0fe7d,0x5b8d64ca,0x470f9aa1,0x9b620016,0xfb15b278,0x277828cf,
|
||||
0xc2104eae,0x1e7dd419,0x7e0a6677,0xa267fcc0,0xbee502ab,0x6288981c,0x02ff2a72,0xde92b0c5,
|
||||
0xcceefb07,0x108361b0,0x70f4d3de,0xac994969,0xb01bb702,0x6c762db5,0x0c019fdb,0xd06c056c,
|
||||
0x3504630d,0xe969f9ba,0x891e4bd4,0x5573d163,0x49f12f08,0x959cb5bf,0xf5eb07d1,0x29869d66,
|
||||
0xa6e63d1d,0x7a8ba7aa,0x1afc15c4,0xc6918f73,0xda137118,0x067eebaf,0x660959c1,0xba64c376,
|
||||
0x5f0ca517,0x83613fa0,0xe3168dce,0x3f7b1779,0x23f9e912,0xff9473a5,0x9fe3c1cb,0x438e5b7c,
|
||||
0x51f210be,0x8d9f8a09,0xede83867,0x3185a2d0,0x2d075cbb,0xf16ac60c,0x911d7462,0x4d70eed5,
|
||||
0xa81888b4,0x74751203,0x1402a06d,0xc86f3ada,0xd4edc4b1,0x08805e06,0x68f7ec68,0xb49a76df,
|
||||
0x4c0f7bec,0x9062e15b,0xf0155335,0x2c78c982,0x30fa37e9,0xec97ad5e,0x8ce01f30,0x508d8587,
|
||||
0xb5e5e3e6,0x69887951,0x09ffcb3f,0xd5925188,0xc910afe3,0x157d3554,0x750a873a,0xa9671d8d,
|
||||
0xbb1b564f,0x6776ccf8,0x07017e96,0xdb6ce421,0xc7ee1a4a,0x1b8380fd,0x7bf43293,0xa799a824,
|
||||
0x42f1ce45,0x9e9c54f2,0xfeebe69c,0x22867c2b,0x3e048240,0xe26918f7,0x821eaa99,0x5e73302e,
|
||||
0x77f5ad48,0xab9837ff,0xcbef8591,0x17821f26,0x0b00e14d,0xd76d7bfa,0xb71ac994,0x6b775323,
|
||||
0x8e1f3542,0x5272aff5,0x32051d9b,0xee68872c,0xf2ea7947,0x2e87e3f0,0x4ef0519e,0x929dcb29,
|
||||
0x80e180eb,0x5c8c1a5c,0x3cfba832,0xe0963285,0xfc14ccee,0x20795659,0x400ee437,0x9c637e80,
|
||||
0x790b18e1,0xa5668256,0xc5113038,0x197caa8f,0x05fe54e4,0xd993ce53,0xb9e47c3d,0x6589e68a,
|
||||
0x9d1cebb9,0x4171710e,0x2106c360,0xfd6b59d7,0xe1e9a7bc,0x3d843d0b,0x5df38f65,0x819e15d2,
|
||||
0x64f673b3,0xb89be904,0xd8ec5b6a,0x0481c1dd,0x18033fb6,0xc46ea501,0xa419176f,0x78748dd8,
|
||||
0x6a08c61a,0xb6655cad,0xd612eec3,0x0a7f7474,0x16fd8a1f,0xca9010a8,0xaae7a2c6,0x768a3871,
|
||||
0x93e25e10,0x4f8fc4a7,0x2ff876c9,0xf395ec7e,0xef171215,0x337a88a2,0x530d3acc,0x8f60a07b},
|
||||
|
||||
{0x00000000,0x490d678d,0x921acf1a,0xdb17a897,0x20f48383,0x69f9e40e,0xb2ee4c99,0xfbe32b14,
|
||||
0x41e90706,0x08e4608b,0xd3f3c81c,0x9afeaf91,0x611d8485,0x2810e308,0xf3074b9f,0xba0a2c12,
|
||||
0x83d20e0c,0xcadf6981,0x11c8c116,0x58c5a69b,0xa3268d8f,0xea2bea02,0x313c4295,0x78312518,
|
||||
0xc23b090a,0x8b366e87,0x5021c610,0x192ca19d,0xe2cf8a89,0xabc2ed04,0x70d54593,0x39d8221e,
|
||||
0x036501af,0x4a686622,0x917fceb5,0xd872a938,0x2391822c,0x6a9ce5a1,0xb18b4d36,0xf8862abb,
|
||||
0x428c06a9,0x0b816124,0xd096c9b3,0x999bae3e,0x6278852a,0x2b75e2a7,0xf0624a30,0xb96f2dbd,
|
||||
0x80b70fa3,0xc9ba682e,0x12adc0b9,0x5ba0a734,0xa0438c20,0xe94eebad,0x3259433a,0x7b5424b7,
|
||||
0xc15e08a5,0x88536f28,0x5344c7bf,0x1a49a032,0xe1aa8b26,0xa8a7ecab,0x73b0443c,0x3abd23b1,
|
||||
0x06ca035e,0x4fc764d3,0x94d0cc44,0xddddabc9,0x263e80dd,0x6f33e750,0xb4244fc7,0xfd29284a,
|
||||
0x47230458,0x0e2e63d5,0xd539cb42,0x9c34accf,0x67d787db,0x2edae056,0xf5cd48c1,0xbcc02f4c,
|
||||
0x85180d52,0xcc156adf,0x1702c248,0x5e0fa5c5,0xa5ec8ed1,0xece1e95c,0x37f641cb,0x7efb2646,
|
||||
0xc4f10a54,0x8dfc6dd9,0x56ebc54e,0x1fe6a2c3,0xe40589d7,0xad08ee5a,0x761f46cd,0x3f122140,
|
||||
0x05af02f1,0x4ca2657c,0x97b5cdeb,0xdeb8aa66,0x255b8172,0x6c56e6ff,0xb7414e68,0xfe4c29e5,
|
||||
0x444605f7,0x0d4b627a,0xd65ccaed,0x9f51ad60,0x64b28674,0x2dbfe1f9,0xf6a8496e,0xbfa52ee3,
|
||||
0x867d0cfd,0xcf706b70,0x1467c3e7,0x5d6aa46a,0xa6898f7e,0xef84e8f3,0x34934064,0x7d9e27e9,
|
||||
0xc7940bfb,0x8e996c76,0x558ec4e1,0x1c83a36c,0xe7608878,0xae6deff5,0x757a4762,0x3c7720ef,
|
||||
0x0d9406bc,0x44996131,0x9f8ec9a6,0xd683ae2b,0x2d60853f,0x646de2b2,0xbf7a4a25,0xf6772da8,
|
||||
0x4c7d01ba,0x05706637,0xde67cea0,0x976aa92d,0x6c898239,0x2584e5b4,0xfe934d23,0xb79e2aae,
|
||||
0x8e4608b0,0xc74b6f3d,0x1c5cc7aa,0x5551a027,0xaeb28b33,0xe7bfecbe,0x3ca84429,0x75a523a4,
|
||||
0xcfaf0fb6,0x86a2683b,0x5db5c0ac,0x14b8a721,0xef5b8c35,0xa656ebb8,0x7d41432f,0x344c24a2,
|
||||
0x0ef10713,0x47fc609e,0x9cebc809,0xd5e6af84,0x2e058490,0x6708e31d,0xbc1f4b8a,0xf5122c07,
|
||||
0x4f180015,0x06156798,0xdd02cf0f,0x940fa882,0x6fec8396,0x26e1e41b,0xfdf64c8c,0xb4fb2b01,
|
||||
0x8d23091f,0xc42e6e92,0x1f39c605,0x5634a188,0xadd78a9c,0xe4daed11,0x3fcd4586,0x76c0220b,
|
||||
0xccca0e19,0x85c76994,0x5ed0c103,0x17dda68e,0xec3e8d9a,0xa533ea17,0x7e244280,0x3729250d,
|
||||
0x0b5e05e2,0x4253626f,0x9944caf8,0xd049ad75,0x2baa8661,0x62a7e1ec,0xb9b0497b,0xf0bd2ef6,
|
||||
0x4ab702e4,0x03ba6569,0xd8adcdfe,0x91a0aa73,0x6a438167,0x234ee6ea,0xf8594e7d,0xb15429f0,
|
||||
0x888c0bee,0xc1816c63,0x1a96c4f4,0x539ba379,0xa878886d,0xe175efe0,0x3a624777,0x736f20fa,
|
||||
0xc9650ce8,0x80686b65,0x5b7fc3f2,0x1272a47f,0xe9918f6b,0xa09ce8e6,0x7b8b4071,0x328627fc,
|
||||
0x083b044d,0x413663c0,0x9a21cb57,0xd32cacda,0x28cf87ce,0x61c2e043,0xbad548d4,0xf3d82f59,
|
||||
0x49d2034b,0x00df64c6,0xdbc8cc51,0x92c5abdc,0x692680c8,0x202be745,0xfb3c4fd2,0xb231285f,
|
||||
0x8be90a41,0xc2e46dcc,0x19f3c55b,0x50fea2d6,0xab1d89c2,0xe210ee4f,0x390746d8,0x700a2155,
|
||||
0xca000d47,0x830d6aca,0x581ac25d,0x1117a5d0,0xeaf48ec4,0xa3f9e949,0x78ee41de,0x31e32653},
|
||||
|
||||
{0x00000000,0x1b280d78,0x36501af0,0x2d781788,0x6ca035e0,0x77883898,0x5af02f10,0x41d82268,
|
||||
0xd9406bc0,0xc26866b8,0xef107130,0xf4387c48,0xb5e05e20,0xaec85358,0x83b044d0,0x989849a8,
|
||||
0xb641ca37,0xad69c74f,0x8011d0c7,0x9b39ddbf,0xdae1ffd7,0xc1c9f2af,0xecb1e527,0xf799e85f,
|
||||
0x6f01a1f7,0x7429ac8f,0x5951bb07,0x4279b67f,0x03a19417,0x1889996f,0x35f18ee7,0x2ed9839f,
|
||||
0x684289d9,0x736a84a1,0x5e129329,0x453a9e51,0x04e2bc39,0x1fcab141,0x32b2a6c9,0x299aabb1,
|
||||
0xb102e219,0xaa2aef61,0x8752f8e9,0x9c7af591,0xdda2d7f9,0xc68ada81,0xebf2cd09,0xf0dac071,
|
||||
0xde0343ee,0xc52b4e96,0xe853591e,0xf37b5466,0xb2a3760e,0xa98b7b76,0x84f36cfe,0x9fdb6186,
|
||||
0x0743282e,0x1c6b2556,0x311332de,0x2a3b3fa6,0x6be31dce,0x70cb10b6,0x5db3073e,0x469b0a46,
|
||||
0xd08513b2,0xcbad1eca,0xe6d50942,0xfdfd043a,0xbc252652,0xa70d2b2a,0x8a753ca2,0x915d31da,
|
||||
0x09c57872,0x12ed750a,0x3f956282,0x24bd6ffa,0x65654d92,0x7e4d40ea,0x53355762,0x481d5a1a,
|
||||
0x66c4d985,0x7decd4fd,0x5094c375,0x4bbcce0d,0x0a64ec65,0x114ce11d,0x3c34f695,0x271cfbed,
|
||||
0xbf84b245,0xa4acbf3d,0x89d4a8b5,0x92fca5cd,0xd32487a5,0xc80c8add,0xe5749d55,0xfe5c902d,
|
||||
0xb8c79a6b,0xa3ef9713,0x8e97809b,0x95bf8de3,0xd467af8b,0xcf4fa2f3,0xe237b57b,0xf91fb803,
|
||||
0x6187f1ab,0x7aaffcd3,0x57d7eb5b,0x4cffe623,0x0d27c44b,0x160fc933,0x3b77debb,0x205fd3c3,
|
||||
0x0e86505c,0x15ae5d24,0x38d64aac,0x23fe47d4,0x622665bc,0x790e68c4,0x54767f4c,0x4f5e7234,
|
||||
0xd7c63b9c,0xccee36e4,0xe196216c,0xfabe2c14,0xbb660e7c,0xa04e0304,0x8d36148c,0x961e19f4,
|
||||
0xa5cb3ad3,0xbee337ab,0x939b2023,0x88b32d5b,0xc96b0f33,0xd243024b,0xff3b15c3,0xe41318bb,
|
||||
0x7c8b5113,0x67a35c6b,0x4adb4be3,0x51f3469b,0x102b64f3,0x0b03698b,0x267b7e03,0x3d53737b,
|
||||
0x138af0e4,0x08a2fd9c,0x25daea14,0x3ef2e76c,0x7f2ac504,0x6402c87c,0x497adff4,0x5252d28c,
|
||||
0xcaca9b24,0xd1e2965c,0xfc9a81d4,0xe7b28cac,0xa66aaec4,0xbd42a3bc,0x903ab434,0x8b12b94c,
|
||||
0xcd89b30a,0xd6a1be72,0xfbd9a9fa,0xe0f1a482,0xa12986ea,0xba018b92,0x97799c1a,0x8c519162,
|
||||
0x14c9d8ca,0x0fe1d5b2,0x2299c23a,0x39b1cf42,0x7869ed2a,0x6341e052,0x4e39f7da,0x5511faa2,
|
||||
0x7bc8793d,0x60e07445,0x4d9863cd,0x56b06eb5,0x17684cdd,0x0c4041a5,0x2138562d,0x3a105b55,
|
||||
0xa28812fd,0xb9a01f85,0x94d8080d,0x8ff00575,0xce28271d,0xd5002a65,0xf8783ded,0xe3503095,
|
||||
0x754e2961,0x6e662419,0x431e3391,0x58363ee9,0x19ee1c81,0x02c611f9,0x2fbe0671,0x34960b09,
|
||||
0xac0e42a1,0xb7264fd9,0x9a5e5851,0x81765529,0xc0ae7741,0xdb867a39,0xf6fe6db1,0xedd660c9,
|
||||
0xc30fe356,0xd827ee2e,0xf55ff9a6,0xee77f4de,0xafafd6b6,0xb487dbce,0x99ffcc46,0x82d7c13e,
|
||||
0x1a4f8896,0x016785ee,0x2c1f9266,0x37379f1e,0x76efbd76,0x6dc7b00e,0x40bfa786,0x5b97aafe,
|
||||
0x1d0ca0b8,0x0624adc0,0x2b5cba48,0x3074b730,0x71ac9558,0x6a849820,0x47fc8fa8,0x5cd482d0,
|
||||
0xc44ccb78,0xdf64c600,0xf21cd188,0xe934dcf0,0xa8ecfe98,0xb3c4f3e0,0x9ebce468,0x8594e910,
|
||||
0xab4d6a8f,0xb06567f7,0x9d1d707f,0x86357d07,0xc7ed5f6f,0xdcc55217,0xf1bd459f,0xea9548e7,
|
||||
0x720d014f,0x69250c37,0x445d1bbf,0x5f7516c7,0x1ead34af,0x058539d7,0x28fd2e5f,0x33d52327},
|
||||
|
||||
{0x00000000,0x4f576811,0x9eaed022,0xd1f9b833,0x399cbdf3,0x76cbd5e2,0xa7326dd1,0xe86505c0,
|
||||
0x73397be6,0x3c6e13f7,0xed97abc4,0xa2c0c3d5,0x4aa5c615,0x05f2ae04,0xd40b1637,0x9b5c7e26,
|
||||
0xe672f7cc,0xa9259fdd,0x78dc27ee,0x378b4fff,0xdfee4a3f,0x90b9222e,0x41409a1d,0x0e17f20c,
|
||||
0x954b8c2a,0xda1ce43b,0x0be55c08,0x44b23419,0xacd731d9,0xe38059c8,0x3279e1fb,0x7d2e89ea,
|
||||
0xc824f22f,0x87739a3e,0x568a220d,0x19dd4a1c,0xf1b84fdc,0xbeef27cd,0x6f169ffe,0x2041f7ef,
|
||||
0xbb1d89c9,0xf44ae1d8,0x25b359eb,0x6ae431fa,0x8281343a,0xcdd65c2b,0x1c2fe418,0x53788c09,
|
||||
0x2e5605e3,0x61016df2,0xb0f8d5c1,0xffafbdd0,0x17cab810,0x589dd001,0x89646832,0xc6330023,
|
||||
0x5d6f7e05,0x12381614,0xc3c1ae27,0x8c96c636,0x64f3c3f6,0x2ba4abe7,0xfa5d13d4,0xb50a7bc5,
|
||||
0x9488f9e9,0xdbdf91f8,0x0a2629cb,0x457141da,0xad14441a,0xe2432c0b,0x33ba9438,0x7cedfc29,
|
||||
0xe7b1820f,0xa8e6ea1e,0x791f522d,0x36483a3c,0xde2d3ffc,0x917a57ed,0x4083efde,0x0fd487cf,
|
||||
0x72fa0e25,0x3dad6634,0xec54de07,0xa303b616,0x4b66b3d6,0x0431dbc7,0xd5c863f4,0x9a9f0be5,
|
||||
0x01c375c3,0x4e941dd2,0x9f6da5e1,0xd03acdf0,0x385fc830,0x7708a021,0xa6f11812,0xe9a67003,
|
||||
0x5cac0bc6,0x13fb63d7,0xc202dbe4,0x8d55b3f5,0x6530b635,0x2a67de24,0xfb9e6617,0xb4c90e06,
|
||||
0x2f957020,0x60c21831,0xb13ba002,0xfe6cc813,0x1609cdd3,0x595ea5c2,0x88a71df1,0xc7f075e0,
|
||||
0xbadefc0a,0xf589941b,0x24702c28,0x6b274439,0x834241f9,0xcc1529e8,0x1dec91db,0x52bbf9ca,
|
||||
0xc9e787ec,0x86b0effd,0x574957ce,0x181e3fdf,0xf07b3a1f,0xbf2c520e,0x6ed5ea3d,0x2182822c,
|
||||
0x2dd0ee65,0x62878674,0xb37e3e47,0xfc295656,0x144c5396,0x5b1b3b87,0x8ae283b4,0xc5b5eba5,
|
||||
0x5ee99583,0x11befd92,0xc04745a1,0x8f102db0,0x67752870,0x28224061,0xf9dbf852,0xb68c9043,
|
||||
0xcba219a9,0x84f571b8,0x550cc98b,0x1a5ba19a,0xf23ea45a,0xbd69cc4b,0x6c907478,0x23c71c69,
|
||||
0xb89b624f,0xf7cc0a5e,0x2635b26d,0x6962da7c,0x8107dfbc,0xce50b7ad,0x1fa90f9e,0x50fe678f,
|
||||
0xe5f41c4a,0xaaa3745b,0x7b5acc68,0x340da479,0xdc68a1b9,0x933fc9a8,0x42c6719b,0x0d91198a,
|
||||
0x96cd67ac,0xd99a0fbd,0x0863b78e,0x4734df9f,0xaf51da5f,0xe006b24e,0x31ff0a7d,0x7ea8626c,
|
||||
0x0386eb86,0x4cd18397,0x9d283ba4,0xd27f53b5,0x3a1a5675,0x754d3e64,0xa4b48657,0xebe3ee46,
|
||||
0x70bf9060,0x3fe8f871,0xee114042,0xa1462853,0x49232d93,0x06744582,0xd78dfdb1,0x98da95a0,
|
||||
0xb958178c,0xf60f7f9d,0x27f6c7ae,0x68a1afbf,0x80c4aa7f,0xcf93c26e,0x1e6a7a5d,0x513d124c,
|
||||
0xca616c6a,0x8536047b,0x54cfbc48,0x1b98d459,0xf3fdd199,0xbcaab988,0x6d5301bb,0x220469aa,
|
||||
0x5f2ae040,0x107d8851,0xc1843062,0x8ed35873,0x66b65db3,0x29e135a2,0xf8188d91,0xb74fe580,
|
||||
0x2c139ba6,0x6344f3b7,0xb2bd4b84,0xfdea2395,0x158f2655,0x5ad84e44,0x8b21f677,0xc4769e66,
|
||||
0x717ce5a3,0x3e2b8db2,0xefd23581,0xa0855d90,0x48e05850,0x07b73041,0xd64e8872,0x9919e063,
|
||||
0x02459e45,0x4d12f654,0x9ceb4e67,0xd3bc2676,0x3bd923b6,0x748e4ba7,0xa577f394,0xea209b85,
|
||||
0x970e126f,0xd8597a7e,0x09a0c24d,0x46f7aa5c,0xae92af9c,0xe1c5c78d,0x303c7fbe,0x7f6b17af,
|
||||
0xe4376989,0xab600198,0x7a99b9ab,0x35ced1ba,0xddabd47a,0x92fcbc6b,0x43050458,0x0c526c49},
|
||||
|
||||
{0x00000000,0x5ba1dcca,0xb743b994,0xece2655e,0x6a466e9f,0x31e7b255,0xdd05d70b,0x86a40bc1,
|
||||
0xd48cdd3e,0x8f2d01f4,0x63cf64aa,0x386eb860,0xbecab3a1,0xe56b6f6b,0x09890a35,0x5228d6ff,
|
||||
0xadd8a7cb,0xf6797b01,0x1a9b1e5f,0x413ac295,0xc79ec954,0x9c3f159e,0x70dd70c0,0x2b7cac0a,
|
||||
0x79547af5,0x22f5a63f,0xce17c361,0x95b61fab,0x1312146a,0x48b3c8a0,0xa451adfe,0xfff07134,
|
||||
0x5f705221,0x04d18eeb,0xe833ebb5,0xb392377f,0x35363cbe,0x6e97e074,0x8275852a,0xd9d459e0,
|
||||
0x8bfc8f1f,0xd05d53d5,0x3cbf368b,0x671eea41,0xe1bae180,0xba1b3d4a,0x56f95814,0x0d5884de,
|
||||
0xf2a8f5ea,0xa9092920,0x45eb4c7e,0x1e4a90b4,0x98ee9b75,0xc34f47bf,0x2fad22e1,0x740cfe2b,
|
||||
0x262428d4,0x7d85f41e,0x91679140,0xcac64d8a,0x4c62464b,0x17c39a81,0xfb21ffdf,0xa0802315,
|
||||
0xbee0a442,0xe5417888,0x09a31dd6,0x5202c11c,0xd4a6cadd,0x8f071617,0x63e57349,0x3844af83,
|
||||
0x6a6c797c,0x31cda5b6,0xdd2fc0e8,0x868e1c22,0x002a17e3,0x5b8bcb29,0xb769ae77,0xecc872bd,
|
||||
0x13380389,0x4899df43,0xa47bba1d,0xffda66d7,0x797e6d16,0x22dfb1dc,0xce3dd482,0x959c0848,
|
||||
0xc7b4deb7,0x9c15027d,0x70f76723,0x2b56bbe9,0xadf2b028,0xf6536ce2,0x1ab109bc,0x4110d576,
|
||||
0xe190f663,0xba312aa9,0x56d34ff7,0x0d72933d,0x8bd698fc,0xd0774436,0x3c952168,0x6734fda2,
|
||||
0x351c2b5d,0x6ebdf797,0x825f92c9,0xd9fe4e03,0x5f5a45c2,0x04fb9908,0xe819fc56,0xb3b8209c,
|
||||
0x4c4851a8,0x17e98d62,0xfb0be83c,0xa0aa34f6,0x260e3f37,0x7dafe3fd,0x914d86a3,0xcaec5a69,
|
||||
0x98c48c96,0xc365505c,0x2f873502,0x7426e9c8,0xf282e209,0xa9233ec3,0x45c15b9d,0x1e608757,
|
||||
0x79005533,0x22a189f9,0xce43eca7,0x95e2306d,0x13463bac,0x48e7e766,0xa4058238,0xffa45ef2,
|
||||
0xad8c880d,0xf62d54c7,0x1acf3199,0x416eed53,0xc7cae692,0x9c6b3a58,0x70895f06,0x2b2883cc,
|
||||
0xd4d8f2f8,0x8f792e32,0x639b4b6c,0x383a97a6,0xbe9e9c67,0xe53f40ad,0x09dd25f3,0x527cf939,
|
||||
0x00542fc6,0x5bf5f30c,0xb7179652,0xecb64a98,0x6a124159,0x31b39d93,0xdd51f8cd,0x86f02407,
|
||||
0x26700712,0x7dd1dbd8,0x9133be86,0xca92624c,0x4c36698d,0x1797b547,0xfb75d019,0xa0d40cd3,
|
||||
0xf2fcda2c,0xa95d06e6,0x45bf63b8,0x1e1ebf72,0x98bab4b3,0xc31b6879,0x2ff90d27,0x7458d1ed,
|
||||
0x8ba8a0d9,0xd0097c13,0x3ceb194d,0x674ac587,0xe1eece46,0xba4f128c,0x56ad77d2,0x0d0cab18,
|
||||
0x5f247de7,0x0485a12d,0xe867c473,0xb3c618b9,0x35621378,0x6ec3cfb2,0x8221aaec,0xd9807626,
|
||||
0xc7e0f171,0x9c412dbb,0x70a348e5,0x2b02942f,0xada69fee,0xf6074324,0x1ae5267a,0x4144fab0,
|
||||
0x136c2c4f,0x48cdf085,0xa42f95db,0xff8e4911,0x792a42d0,0x228b9e1a,0xce69fb44,0x95c8278e,
|
||||
0x6a3856ba,0x31998a70,0xdd7bef2e,0x86da33e4,0x007e3825,0x5bdfe4ef,0xb73d81b1,0xec9c5d7b,
|
||||
0xbeb48b84,0xe515574e,0x09f73210,0x5256eeda,0xd4f2e51b,0x8f5339d1,0x63b15c8f,0x38108045,
|
||||
0x9890a350,0xc3317f9a,0x2fd31ac4,0x7472c60e,0xf2d6cdcf,0xa9771105,0x4595745b,0x1e34a891,
|
||||
0x4c1c7e6e,0x17bda2a4,0xfb5fc7fa,0xa0fe1b30,0x265a10f1,0x7dfbcc3b,0x9119a965,0xcab875af,
|
||||
0x3548049b,0x6ee9d851,0x820bbd0f,0xd9aa61c5,0x5f0e6a04,0x04afb6ce,0xe84dd390,0xb3ec0f5a,
|
||||
0xe1c4d9a5,0xba65056f,0x56876031,0x0d26bcfb,0x8b82b73a,0xd0236bf0,0x3cc10eae,0x6760d264}};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,3 @@
|
||||
Monty <monty@xiph.org>
|
||||
|
||||
and the rest of the Xiph.org Foundation.
|
||||
+184
@@ -0,0 +1,184 @@
|
||||
libvorbis 1.3.7 (2020-07-04) -- "Xiph.Org libVorbis I 20200704 (Reducing Environment)"
|
||||
|
||||
* Fix CVE-2018-10393 - out-of-bounds read encoding very low sample rates.
|
||||
* Fix CVE-2017-14160 - out-of-bounds read encoding very low sample rates.
|
||||
* Fix handling invalid bytes per sample arguments.
|
||||
* Fix handling invalid channel count arguments.
|
||||
* Fix invalid free on seek failure.
|
||||
* Fix negative shift reading blocksize.
|
||||
* Fix accepting unreasonable float32 values.
|
||||
* Fix tag comparison depending on locale.
|
||||
* Fix unnecessarily linking libm.
|
||||
* Fix memory leak in test_sharedbook.
|
||||
* Update Visual Studio projects for ogg library filename change.
|
||||
* Distribute CMake build files with the source package.
|
||||
* Remove unnecessary configure --target switch.
|
||||
* Add gitlab CI support.
|
||||
* Add OSS-Fuzz support.
|
||||
* Build system and integration updates.
|
||||
|
||||
libvorbis 1.3.6 (2018-03-16) -- "Xiph.Org libVorbis I 20180316 (Now 100% fewer shells)"
|
||||
|
||||
* Fix CVE-2018-5146 - out-of-bounds write on codebook decoding.
|
||||
* Fix CVE-2017-14632 - free() on unitialized data
|
||||
* Fix CVE-2017-14633 - out-of-bounds read
|
||||
* Fix bitrate metadata parsing.
|
||||
* Fix out-of-bounds read in codebook parsing.
|
||||
* Fix residue vector size in Vorbis I spec.
|
||||
* Appveyor support
|
||||
* Travis CI support
|
||||
* Add secondary CMake build system.
|
||||
* Build system fixes
|
||||
|
||||
libvorbis 1.3.5 (2015-03-03) -- "Xiph.Org libVorbis I 20150105 (⛄⛄⛄⛄)"
|
||||
|
||||
* Tolerate single-entry codebooks.
|
||||
* Fix decoder crash with invalid input.
|
||||
* Fix encoder crash with non-positive sample rates.
|
||||
# Fix issues in vorbisfile's seek bisection code.
|
||||
* Spec errata.
|
||||
* Reject multiple headers of the same type.
|
||||
* Various build fixes and code cleanup.
|
||||
|
||||
libvorbis 1.3.4 (2014-01-22) -- "Xiph.Org libVorbis I 20140122 (Turpakäräjiin)"
|
||||
|
||||
* Reduce codebook footprint in library code.
|
||||
* Various build and documentation fixes.
|
||||
|
||||
libvorbis 1.3.3 (2012-02-03) -- "Xiph.Org libVorbis I 20120203 (Omnipresent)"
|
||||
|
||||
* vorbis: additional proofing against invalid/malicious
|
||||
streams in decode (see SVN for details).
|
||||
* vorbis: fix a memory leak in vorbis_commentheader_out().
|
||||
* updates, corrections and clarifications in the Vorbis I specification
|
||||
document
|
||||
* win32: fixed project configuration which referenced two CRT versions
|
||||
in output binaries.
|
||||
* build warning fixes
|
||||
|
||||
libvorbis 1.3.2 (2010-11-01) -- "Xiph.Org libVorbis I 20101101 (Schaufenugget)"
|
||||
|
||||
* vorbis: additional proofing against invalid/malicious
|
||||
streams in floor, residue, and bos/eos packet trimming
|
||||
code (see SVN for details).
|
||||
* vorbis: Added programming documentation tree for the
|
||||
low-level calls
|
||||
* vorbisfile: Correct handling of serial numbers array
|
||||
element [0] on non-seekable streams
|
||||
* vorbisenc: Back out an [old] AoTuV HF weighting that was
|
||||
first enabled in 1.3.0; there are a few samples where I
|
||||
really don't like the effect it causes.
|
||||
* vorbis: return correct timestamp for granule positions
|
||||
with high bit set.
|
||||
* vorbisfile: the [undocumented] half-rate decode api made no
|
||||
attempt to keep the pcm offset tracking consistent in seeks.
|
||||
Fix and add a testing mode to seeking_example.c to torture
|
||||
test seeking in halfrate mode. Also remove requirement that
|
||||
halfrate mode only work with seekable files.
|
||||
* vorbisfile: Fix a chaining bug in raw_seeks where seeking
|
||||
out of the current link would fail due to not
|
||||
reinitializing the decode machinery.
|
||||
* vorbisfile: improve seeking strategy. Reduces the
|
||||
necessary number of seek callbacks in an open or seek
|
||||
operation by well over 2/3.
|
||||
|
||||
libvorbis 1.3.1 (2010-02-26) -- "Xiph.Org libVorbis I 20100325 (Everywhere)"
|
||||
|
||||
* tweak + minor arithmetic fix in floor1 fit
|
||||
* revert noise norm to conservative 1.2.3 behavior pending
|
||||
more listening testing
|
||||
|
||||
libvorbis 1.3.0 (2010-02-25) -- unreleased staging snapshot
|
||||
|
||||
* Optimized surround support for 5.1 encoding at 44.1/48kHz
|
||||
* Added encoder control call to disable channel coupling
|
||||
* Correct an overflow bug in very low-bitrate encoding on 32 bit
|
||||
machines that caused inflated bitrates
|
||||
* Numerous API hardening, leak and build fixes
|
||||
* Correct bug in 22kHz compand setup that could cause a crash
|
||||
* Correct bug in 16kHz codebooks that could cause unstable pure
|
||||
tones at high bitrates
|
||||
|
||||
libvorbis 1.2.3 (2009-07-09) -- "Xiph.Org libVorbis I 20090709"
|
||||
|
||||
* correct a vorbisfile bug that prevented proper playback of
|
||||
Vorbis files where all audio in a logical stream is in a
|
||||
single page
|
||||
* Additional decode setup hardening against malicious streams
|
||||
* Add 'OV_EXCLUDE_STATIC_CALLBACKS' define for developers who
|
||||
wish to avoid unused symbol warnings from the static callbacks
|
||||
defined in vorbisfile.h
|
||||
|
||||
libvorbis 1.2.2 (2009-06-24) -- "Xiph.Org libVorbis I 20090624"
|
||||
|
||||
* define VENDOR and ENCODER strings
|
||||
* seek correctly in files bigger than 2 GB (Windows)
|
||||
* fix regression from CVE-2008-1420; 1.0b1 files work again
|
||||
* mark all tables as constant to reduce memory occupation
|
||||
* additional decoder hardening against malicious streams
|
||||
* substantially reduce amount of seeking performed by Vorbisfile
|
||||
* Multichannel decode bugfix
|
||||
* build system updates
|
||||
* minor specification clarifications/fixes
|
||||
|
||||
libvorbis 1.2.1 (unreleased) -- "Xiph.Org libVorbis I 20080501"
|
||||
|
||||
* Improved robustness with corrupt streams.
|
||||
* New ov_read_filter() vorbisfile call allows filtering decoded
|
||||
audio as floats before converting to integer samples.
|
||||
* Fix an encoder bug with multichannel streams.
|
||||
* Replaced RTP payload format draft with RFC 5215.
|
||||
* Bare bones self test under 'make check'.
|
||||
* Fix a problem encoding some streams between 14 and 28 kHz.
|
||||
* Fix a numerical instability in the edge extrapolation filter.
|
||||
* Build system improvements.
|
||||
* Specification correction.
|
||||
|
||||
libvorbis 1.2.0 (2007-07-25) -- "Xiph.Org libVorbis I 20070622"
|
||||
|
||||
* new ov_fopen() convenience call that avoids the common
|
||||
stdio conflicts with ov_open() and MSVC runtimes.
|
||||
* libvorbisfile now handles multiplexed streams
|
||||
* improve robustness to corrupt input streams
|
||||
* fix a minor encoder bug
|
||||
* updated RTP draft
|
||||
* build system updates
|
||||
* minor corrections to the specification
|
||||
|
||||
libvorbis 1.1.2 (2005-11-27) -- "Xiph.Org libVorbis I 20050304"
|
||||
|
||||
* fix a serious encoder bug with gcc 4 optimized builds
|
||||
* documentation and spec fixes
|
||||
* updated VS2003 and XCode builds
|
||||
* new draft RTP encapsulation spec
|
||||
|
||||
libvorbis 1.1.1 (2005-06-27) -- "Xiph.Org libVorbis I 20050304"
|
||||
|
||||
* bug fix to the bitrate management encoder interface
|
||||
* bug fix to properly set packetno field in the encoder
|
||||
* new draft RTP encapsulation spec
|
||||
* library API documentation improvements
|
||||
|
||||
libvorbis 1.1.0 (2004-09-22) -- "Xiph.Org libVorbis I 20040629"
|
||||
|
||||
* merges tuning improvements from Aoyumi's aoTuV with fixups
|
||||
* new managed bitrate (CBR) mode support
|
||||
* new vorbis_encoder_ctl() interface
|
||||
* extensive documentation updates
|
||||
* application/ogg mimetype is now official
|
||||
* autotools cleanup from Thomas Vander Stichele
|
||||
* SymbianOS build support from Colin Ward at CSIRO
|
||||
* various bugfixes
|
||||
* various packaging improvements
|
||||
|
||||
libvorbis 1.0.1 (2003-11-17) -- "Xiph.Org libVorbis I 20030909"
|
||||
|
||||
* numerous bug fixes
|
||||
* specification corrections
|
||||
* new crosslap and halfrate APIs for game use
|
||||
* packaging and build updates
|
||||
|
||||
libvorbis 1.0.0 (2002-07-19) -- "Xiph.Org libVorbis I 20020717"
|
||||
|
||||
* first stable release
|
||||
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2002-2020 Xiph.org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
+147
@@ -0,0 +1,147 @@
|
||||
# Vorbis
|
||||
|
||||
[](https://gitlab.xiph.org/xiph/vorbis/-/pipelines)
|
||||
[](https://travis-ci.org/xiph/vorbis)
|
||||
[](https://ci.appveyor.com/project/rillian/vorbis)
|
||||
|
||||
Vorbis is a general purpose audio and music encoding format
|
||||
contemporary to MPEG-4's AAC and TwinVQ, the next generation beyond
|
||||
MPEG audio layer 3. Unlike the MPEG sponsored formats (and other
|
||||
proprietary formats such as RealAudio G2 and Windows' flavor of the
|
||||
month), the Vorbis CODEC specification belongs to the public domain.
|
||||
All the technical details are published and documented, and any
|
||||
software entity may make full use of the format without license
|
||||
fee, royalty or patent concerns.
|
||||
|
||||
This package contains:
|
||||
|
||||
- libvorbis, a BSD-style license software implementation of
|
||||
the Vorbis specification by the Xiph.Org Foundation
|
||||
(https://xiph.org/)
|
||||
|
||||
- libvorbisfile, a BSD-style license convenience library
|
||||
built on Vorbis designed to simplify common uses
|
||||
|
||||
- libvorbisenc, a BSD-style license library that provides a simple,
|
||||
programmatic encoding setup interface
|
||||
|
||||
- example code making use of libogg, libvorbis, libvorbisfile and
|
||||
libvorbisenc
|
||||
|
||||
## What's here ##
|
||||
|
||||
This source distribution includes libvorbis and an example
|
||||
encoder/player to demonstrate use of libvorbis as well as
|
||||
documentation on the Ogg Vorbis audio coding format.
|
||||
|
||||
You'll need libogg (distributed separately) to compile this library.
|
||||
A more comprehensive set of utilities is available in the vorbis-tools
|
||||
package.
|
||||
|
||||
Directory:
|
||||
|
||||
- `lib` The source for the libraries, a BSD-license implementation of the public domain Ogg Vorbis audio encoding format.
|
||||
|
||||
- `include` Library API headers
|
||||
|
||||
- `debian` Rules/spec files for building Debian .deb packages
|
||||
|
||||
- `doc` Vorbis documentation
|
||||
|
||||
- `examples` Example code illustrating programmatic use of libvorbis, libvorbisfile and libvorbisenc
|
||||
|
||||
- `macosx` Project files for MacOS X.
|
||||
|
||||
- `win32` Win32 projects files and build automation
|
||||
|
||||
- `vq` Internal utilities for training/building new LSP/residue and auxiliary codebooks.
|
||||
|
||||
## Contact ##
|
||||
|
||||
The Ogg homepage is located at 'https://xiph.org/ogg/'.
|
||||
Vorbis's homepage is located at 'https://xiph.org/vorbis/'.
|
||||
Up to date technical documents, contact information, source code and
|
||||
pre-built utilities may be found there.
|
||||
|
||||
## Building ##
|
||||
|
||||
#### Building from master ####
|
||||
|
||||
Development source is under git revision control at
|
||||
https://gitlab.xiph.org/xiph/vorbis.git. You will also need the
|
||||
newest versions of autoconf, automake, libtool and pkg-config in
|
||||
order to compile Vorbis from development source. A configure script
|
||||
is provided for you in the source tarball distributions.
|
||||
|
||||
./autogen.sh
|
||||
./configure
|
||||
make
|
||||
|
||||
and as root if desired:
|
||||
|
||||
make install
|
||||
|
||||
This will install the Vorbis libraries (static and shared) into
|
||||
/usr/local/lib, includes into /usr/local/include and API manpages
|
||||
(once we write some) into /usr/local/man.
|
||||
|
||||
Documentation building requires xsltproc and pdfxmltex.
|
||||
|
||||
#### Building from tarball distributions ####
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
and optionally (as root):
|
||||
|
||||
make install
|
||||
|
||||
#### Building RPM packages ####
|
||||
|
||||
after normal configuring:
|
||||
|
||||
make dist
|
||||
rpm -ta libvorbis-<version>.tar.gz
|
||||
|
||||
## Building with CMake ##
|
||||
|
||||
Ogg supports building using [CMake](https://cmake.org/). CMake is a meta build system that generates native projects for each platform.
|
||||
To generate projects just run cmake replacing `YOUR-PROJECT-GENERATOR` with a proper generator from a list [here](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html):
|
||||
|
||||
cmake -G YOUR-PROJECT-GENERATOR .
|
||||
|
||||
Note that by default cmake generates projects that will build static libraries.
|
||||
To generate projects that will build dynamic library use `BUILD_SHARED_LIBS` option like this:
|
||||
|
||||
cmake -G YOUR-PROJECT-GENERATOR -DBUILD_SHARED_LIBS=1 .
|
||||
|
||||
After projects are generated use them as usual
|
||||
|
||||
#### Building on Windows ####
|
||||
|
||||
Use proper generator for your Visual Studio version like:
|
||||
|
||||
cmake -G "Visual Studio 12 2013" .
|
||||
|
||||
#### Building on Mac OS X ####
|
||||
|
||||
Use Xcode generator. To build framework run:
|
||||
|
||||
cmake -G Xcode -DBUILD_FRAMEWORK=1 .
|
||||
|
||||
#### Building on Linux ####
|
||||
|
||||
Use Makefile generator which is default one.
|
||||
|
||||
cmake .
|
||||
make
|
||||
|
||||
## License ##
|
||||
|
||||
THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE.
|
||||
USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS
|
||||
GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE
|
||||
IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING.
|
||||
|
||||
THE OggVorbis SOURCE CODE IS COPYRIGHT (C) 1994-2020
|
||||
by the Xiph.Org Foundation https://xiph.org/
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: single-block PCM analysis mode dispatch
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "scales.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* decides between modes, dispatches to the appropriate mapping. */
|
||||
int vorbis_analysis(vorbis_block *vb, ogg_packet *op){
|
||||
int ret,i;
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
|
||||
|
||||
vb->glue_bits=0;
|
||||
vb->time_bits=0;
|
||||
vb->floor_bits=0;
|
||||
vb->res_bits=0;
|
||||
|
||||
/* first things first. Make sure encode is ready */
|
||||
for(i=0;i<PACKETBLOBS;i++)
|
||||
oggpack_reset(vbi->packetblob[i]);
|
||||
|
||||
/* we only have one mapping type (0), and we let the mapping code
|
||||
itself figure out what soft mode to use. This allows easier
|
||||
bitrate management */
|
||||
|
||||
if((ret=_mapping_P[0]->forward(vb)))
|
||||
return(ret);
|
||||
|
||||
if(op){
|
||||
if(vorbis_bitrate_managed(vb))
|
||||
/* The app is using a bitmanaged mode... but not using the
|
||||
bitrate management interface. */
|
||||
return(OV_EINVAL);
|
||||
|
||||
op->packet=oggpack_get_buffer(&vb->opb);
|
||||
op->bytes=oggpack_bytes(&vb->opb);
|
||||
op->b_o_s=0;
|
||||
op->e_o_s=vb->eofflag;
|
||||
op->granulepos=vb->granulepos;
|
||||
op->packetno=vb->sequence; /* for sake of completeness */
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef ANALYSIS
|
||||
int analysis_noisy=1;
|
||||
|
||||
/* there was no great place to put this.... */
|
||||
void _analysis_output_always(char *base,int i,float *v,int n,int bark,int dB,ogg_int64_t off){
|
||||
int j;
|
||||
FILE *of;
|
||||
char buffer[80];
|
||||
|
||||
sprintf(buffer,"%s_%d.m",base,i);
|
||||
of=fopen(buffer,"w");
|
||||
|
||||
if(!of)perror("failed to open data dump file");
|
||||
|
||||
for(j=0;j<n;j++){
|
||||
if(bark){
|
||||
float b=toBARK((4000.f*j/n)+.25);
|
||||
fprintf(of,"%f ",b);
|
||||
}else
|
||||
if(off!=0)
|
||||
fprintf(of,"%f ",(double)(j+off)/8000.);
|
||||
else
|
||||
fprintf(of,"%f ",(double)j);
|
||||
|
||||
if(dB){
|
||||
float val;
|
||||
if(v[j]==0.)
|
||||
val=-140.;
|
||||
else
|
||||
val=todB(v+j);
|
||||
fprintf(of,"%f\n",val);
|
||||
}else{
|
||||
fprintf(of,"%f\n",v[j]);
|
||||
}
|
||||
}
|
||||
fclose(of);
|
||||
}
|
||||
|
||||
void _analysis_output(char *base,int i,float *v,int n,int bark,int dB,
|
||||
ogg_int64_t off){
|
||||
if(analysis_noisy)_analysis_output_always(base,i,v,n,bark,dB,off);
|
||||
}
|
||||
|
||||
#endif
|
||||
+143
@@ -0,0 +1,143 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis backend and mapping structures; needed for
|
||||
static mode headers
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* this is exposed up here because we need it for static modes.
|
||||
Lookups for each backend aren't exposed because there's no reason
|
||||
to do so */
|
||||
|
||||
#ifndef _vorbis_backend_h_
|
||||
#define _vorbis_backend_h_
|
||||
|
||||
#include "codec_internal.h"
|
||||
|
||||
/* this would all be simpler/shorter with templates, but.... */
|
||||
/* Floor backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info_floor *,oggpack_buffer *);
|
||||
vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_floor *);
|
||||
void (*free_info) (vorbis_info_floor *);
|
||||
void (*free_look) (vorbis_look_floor *);
|
||||
void *(*inverse1) (struct vorbis_block *,vorbis_look_floor *);
|
||||
int (*inverse2) (struct vorbis_block *,vorbis_look_floor *,
|
||||
void *buffer,float *);
|
||||
} vorbis_func_floor;
|
||||
|
||||
typedef struct{
|
||||
int order;
|
||||
long rate;
|
||||
long barkmap;
|
||||
|
||||
int ampbits;
|
||||
int ampdB;
|
||||
|
||||
int numbooks; /* <= 16 */
|
||||
int books[16];
|
||||
|
||||
float lessthan; /* encode-only config setting hacks for libvorbis */
|
||||
float greaterthan; /* encode-only config setting hacks for libvorbis */
|
||||
|
||||
} vorbis_info_floor0;
|
||||
|
||||
|
||||
#define VIF_POSIT 63
|
||||
#define VIF_CLASS 16
|
||||
#define VIF_PARTS 31
|
||||
typedef struct{
|
||||
int partitions; /* 0 to 31 */
|
||||
int partitionclass[VIF_PARTS]; /* 0 to 15 */
|
||||
|
||||
int class_dim[VIF_CLASS]; /* 1 to 8 */
|
||||
int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */
|
||||
int class_book[VIF_CLASS]; /* subs ^ dim entries */
|
||||
int class_subbook[VIF_CLASS][8]; /* [VIF_CLASS][subs] */
|
||||
|
||||
|
||||
int mult; /* 1 2 3 or 4 */
|
||||
int postlist[VIF_POSIT+2]; /* first two implicit */
|
||||
|
||||
|
||||
/* encode side analysis parameters */
|
||||
float maxover;
|
||||
float maxunder;
|
||||
float maxerr;
|
||||
|
||||
float twofitweight;
|
||||
float twofitatten;
|
||||
|
||||
int n;
|
||||
|
||||
} vorbis_info_floor1;
|
||||
|
||||
/* Residue backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info_residue *,oggpack_buffer *);
|
||||
vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
vorbis_look_residue *(*look) (vorbis_dsp_state *,
|
||||
vorbis_info_residue *);
|
||||
void (*free_info) (vorbis_info_residue *);
|
||||
void (*free_look) (vorbis_look_residue *);
|
||||
long **(*classx) (struct vorbis_block *,vorbis_look_residue *,
|
||||
int **,int *,int);
|
||||
int (*forward) (oggpack_buffer *,struct vorbis_block *,
|
||||
vorbis_look_residue *,
|
||||
int **,int *,int,long **,int);
|
||||
int (*inverse) (struct vorbis_block *,vorbis_look_residue *,
|
||||
float **,int *,int);
|
||||
} vorbis_func_residue;
|
||||
|
||||
typedef struct vorbis_info_residue0{
|
||||
/* block-partitioned VQ coded straight residue */
|
||||
long begin;
|
||||
long end;
|
||||
|
||||
/* first stage (lossless partitioning) */
|
||||
int grouping; /* group n vectors per partition */
|
||||
int partitions; /* possible codebooks for a partition */
|
||||
int partvals; /* partitions ^ groupbook dim */
|
||||
int groupbook; /* huffbook for partitioning */
|
||||
int secondstages[64]; /* expanded out to pointers in lookup */
|
||||
int booklist[512]; /* list of second stage books */
|
||||
|
||||
/*const*/ int classmetric1[64];
|
||||
/*const*/ int classmetric2[64];
|
||||
} vorbis_info_residue0;
|
||||
|
||||
/* Mapping backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info *,vorbis_info_mapping *,
|
||||
oggpack_buffer *);
|
||||
vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
void (*free_info) (vorbis_info_mapping *);
|
||||
int (*forward) (struct vorbis_block *vb);
|
||||
int (*inverse) (struct vorbis_block *vb,vorbis_info_mapping *);
|
||||
} vorbis_func_mapping;
|
||||
|
||||
typedef struct vorbis_info_mapping0{
|
||||
int submaps; /* <= 16 */
|
||||
int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */
|
||||
|
||||
int floorsubmap[16]; /* [mux] submap to floors */
|
||||
int residuesubmap[16]; /* [mux] submap to residue */
|
||||
|
||||
int coupling_steps;
|
||||
int coupling_mag[256];
|
||||
int coupling_ang[256];
|
||||
|
||||
} vorbis_info_mapping0;
|
||||
|
||||
#endif
|
||||
+252
@@ -0,0 +1,252 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
#include "bitrate.h"
|
||||
|
||||
/* compute bitrate tracking setup */
|
||||
void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bm){
|
||||
codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
|
||||
bitrate_manager_info *bi=&ci->bi;
|
||||
|
||||
memset(bm,0,sizeof(*bm));
|
||||
|
||||
if(bi && (bi->reservoir_bits>0)){
|
||||
long ratesamples=vi->rate;
|
||||
int halfsamples=ci->blocksizes[0]>>1;
|
||||
|
||||
bm->short_per_long=ci->blocksizes[1]/ci->blocksizes[0];
|
||||
bm->managed=1;
|
||||
|
||||
bm->avg_bitsper= (int) rint(1.*bi->avg_rate*halfsamples/ratesamples);
|
||||
bm->min_bitsper= (int) rint(1.*bi->min_rate*halfsamples/ratesamples);
|
||||
bm->max_bitsper= (int) rint(1.*bi->max_rate*halfsamples/ratesamples);
|
||||
|
||||
bm->avgfloat=PACKETBLOBS/2;
|
||||
|
||||
/* not a necessary fix, but one that leads to a more balanced
|
||||
typical initialization */
|
||||
{
|
||||
long desired_fill = (long) (bi->reservoir_bits*bi->reservoir_bias);
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
bm->avg_reservoir=desired_fill;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void vorbis_bitrate_clear(bitrate_manager_state *bm){
|
||||
memset(bm,0,sizeof(*bm));
|
||||
return;
|
||||
}
|
||||
|
||||
int vorbis_bitrate_managed(vorbis_block *vb){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=(private_state*)vd->backend_state;
|
||||
bitrate_manager_state *bm=&b->bms;
|
||||
|
||||
if(bm && bm->managed)return(1);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* finish taking in the block we just processed */
|
||||
int vorbis_bitrate_addblock(vorbis_block *vb){
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal;
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=(private_state*)vd->backend_state;
|
||||
bitrate_manager_state *bm=&b->bms;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
bitrate_manager_info *bi=&ci->bi;
|
||||
|
||||
int choice = (int) rint(bm->avgfloat);
|
||||
long this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper);
|
||||
long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper);
|
||||
int samples=ci->blocksizes[vb->W]>>1;
|
||||
long desired_fill = (long) (bi->reservoir_bits*bi->reservoir_bias);
|
||||
if(!bm->managed){
|
||||
/* not a bitrate managed stream, but for API simplicity, we'll
|
||||
buffer the packet to keep the code path clean */
|
||||
|
||||
if(bm->vb)return(-1); /* one has been submitted without
|
||||
being claimed */
|
||||
bm->vb=vb;
|
||||
return(0);
|
||||
}
|
||||
|
||||
bm->vb=vb;
|
||||
|
||||
/* look ahead for avg floater */
|
||||
if(bm->avg_bitsper>0){
|
||||
double slew=0.;
|
||||
long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
|
||||
double slewlimit= 15./bi->slew_damp;
|
||||
|
||||
/* choosing a new floater:
|
||||
if we're over target, we slew down
|
||||
if we're under target, we slew up
|
||||
|
||||
choose slew as follows: look through packetblobs of this frame
|
||||
and set slew as the first in the appropriate direction that
|
||||
gives us the slew we want. This may mean no slew if delta is
|
||||
already favorable.
|
||||
|
||||
Then limit slew to slew max */
|
||||
|
||||
if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
|
||||
while(choice>0 && this_bits>avg_target_bits &&
|
||||
bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
|
||||
choice--;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
|
||||
while(choice+1<PACKETBLOBS && this_bits<avg_target_bits &&
|
||||
bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
|
||||
choice++;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
|
||||
slew=rint(choice-bm->avgfloat)/samples*vi->rate;
|
||||
if(slew<-slewlimit)slew=-slewlimit;
|
||||
if(slew>slewlimit)slew=slewlimit;
|
||||
choice = (int) rint(bm->avgfloat+= slew/vi->rate*samples);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* enforce min(if used) on the current floater (if used) */
|
||||
if(bm->min_bitsper>0){
|
||||
/* do we need to force the bitrate up? */
|
||||
if(this_bits<min_target_bits){
|
||||
while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){
|
||||
choice++;
|
||||
if(choice>=PACKETBLOBS)break;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* enforce max (if used) on the current floater (if used) */
|
||||
if(bm->max_bitsper>0){
|
||||
/* do we need to force the bitrate down? */
|
||||
if(this_bits>max_target_bits){
|
||||
while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){
|
||||
choice--;
|
||||
if(choice<0)break;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Choice of packetblobs now made based on floater, and min/max
|
||||
requirements. Now boundary check extreme choices */
|
||||
|
||||
if(choice<0){
|
||||
/* choosing a smaller packetblob is insufficient to trim bitrate.
|
||||
frame will need to be truncated */
|
||||
long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8;
|
||||
bm->choice=choice=0;
|
||||
|
||||
if(oggpack_bytes(vbi->packetblob[choice])>maxsize){
|
||||
|
||||
oggpack_writetrunc(vbi->packetblob[choice],maxsize*8);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}else{
|
||||
long minsize=(min_target_bits-bm->minmax_reservoir+7)/8;
|
||||
if(choice>=PACKETBLOBS)
|
||||
choice=PACKETBLOBS-1;
|
||||
|
||||
bm->choice=choice;
|
||||
|
||||
/* prop up bitrate according to demand. pad this frame out with zeroes */
|
||||
minsize-=oggpack_bytes(vbi->packetblob[choice]);
|
||||
while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
|
||||
}
|
||||
|
||||
/* now we have the final packet and the final packet size. Update statistics */
|
||||
/* min and max reservoir */
|
||||
if(bm->min_bitsper>0 || bm->max_bitsper>0){
|
||||
|
||||
if(max_target_bits>0 && this_bits>max_target_bits){
|
||||
bm->minmax_reservoir+=(this_bits-max_target_bits);
|
||||
}else if(min_target_bits>0 && this_bits<min_target_bits){
|
||||
bm->minmax_reservoir+=(this_bits-min_target_bits);
|
||||
}else{
|
||||
/* inbetween; we want to take reservoir toward but not past desired_fill */
|
||||
if(bm->minmax_reservoir>desired_fill){
|
||||
if(max_target_bits>0){ /* logical bulletproofing against initialization state */
|
||||
bm->minmax_reservoir+=(this_bits-max_target_bits);
|
||||
if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill;
|
||||
}else{
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
}
|
||||
}else{
|
||||
if(min_target_bits>0){ /* logical bulletproofing against initialization state */
|
||||
bm->minmax_reservoir+=(this_bits-min_target_bits);
|
||||
if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill;
|
||||
}else{
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* avg reservoir */
|
||||
if(bm->avg_bitsper>0){
|
||||
long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
|
||||
bm->avg_reservoir+=this_bits-avg_target_bits;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
|
||||
private_state *b=(private_state*)vd->backend_state;
|
||||
bitrate_manager_state *bm=&b->bms;
|
||||
vorbis_block *vb=bm->vb;
|
||||
int choice=PACKETBLOBS/2;
|
||||
if(!vb)return 0;
|
||||
|
||||
if(op){
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal;
|
||||
|
||||
if(vorbis_bitrate_managed(vb))
|
||||
choice=bm->choice;
|
||||
|
||||
op->packet=oggpack_get_buffer(vbi->packetblob[choice]);
|
||||
op->bytes=oggpack_bytes(vbi->packetblob[choice]);
|
||||
op->b_o_s=0;
|
||||
op->e_o_s=vb->eofflag;
|
||||
op->granulepos=vb->granulepos;
|
||||
op->packetno=vb->sequence; /* for sake of completeness */
|
||||
}
|
||||
|
||||
bm->vb=0;
|
||||
return(1);
|
||||
}
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_BITRATE_H_
|
||||
#define _V_BITRATE_H_
|
||||
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "os.h"
|
||||
|
||||
/* encode side bitrate tracking */
|
||||
typedef struct bitrate_manager_state {
|
||||
int managed;
|
||||
|
||||
long avg_reservoir;
|
||||
long minmax_reservoir;
|
||||
long avg_bitsper;
|
||||
long min_bitsper;
|
||||
long max_bitsper;
|
||||
|
||||
long short_per_long;
|
||||
double avgfloat;
|
||||
|
||||
vorbis_block *vb;
|
||||
int choice;
|
||||
} bitrate_manager_state;
|
||||
|
||||
typedef struct bitrate_manager_info{
|
||||
long avg_rate;
|
||||
long min_rate;
|
||||
long max_rate;
|
||||
long reservoir_bits;
|
||||
double reservoir_bias;
|
||||
|
||||
double slew_damp;
|
||||
|
||||
} bitrate_manager_info;
|
||||
|
||||
extern void vorbis_bitrate_init(vorbis_info *vi,bitrate_manager_state *bs);
|
||||
extern void vorbis_bitrate_clear(bitrate_manager_state *bs);
|
||||
extern int vorbis_bitrate_managed(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_addblock(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd, ogg_packet *op);
|
||||
|
||||
#endif
|
||||
+1043
File diff suppressed because it is too large
Load Diff
+12273
File diff suppressed because it is too large
Load Diff
+15782
File diff suppressed because it is too large
Load Diff
+1546
File diff suppressed because it is too large
Load Diff
+7757
File diff suppressed because it is too large
Load Diff
+461
@@ -0,0 +1,461 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic codebook pack/unpack/code/decode operations
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codebook.h"
|
||||
#include "scales.h"
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
|
||||
/* packs the given codebook into the bitstream **************************/
|
||||
|
||||
int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *opb){
|
||||
long i,j;
|
||||
int ordered=0;
|
||||
|
||||
/* first the basic parameters */
|
||||
oggpack_write(opb,0x564342,24);
|
||||
oggpack_write(opb,c->dim,16);
|
||||
oggpack_write(opb,c->entries,24);
|
||||
|
||||
/* pack the codewords. There are two packings; length ordered and
|
||||
length random. Decide between the two now. */
|
||||
|
||||
for(i=1;i<c->entries;i++)
|
||||
if(c->lengthlist[i-1]==0 || c->lengthlist[i]<c->lengthlist[i-1])break;
|
||||
if(i==c->entries)ordered=1;
|
||||
|
||||
if(ordered){
|
||||
/* length ordered. We only need to say how many codewords of
|
||||
each length. The actual codewords are generated
|
||||
deterministically */
|
||||
|
||||
long count=0;
|
||||
oggpack_write(opb,1,1); /* ordered */
|
||||
oggpack_write(opb,c->lengthlist[0]-1,5); /* 1 to 32 */
|
||||
|
||||
for(i=1;i<c->entries;i++){
|
||||
char thisx=c->lengthlist[i];
|
||||
char last=c->lengthlist[i-1];
|
||||
if(thisx>last){
|
||||
for(j=last;j<thisx;j++){
|
||||
oggpack_write(opb,i-count,ov_ilog(c->entries-count));
|
||||
count=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write(opb,i-count,ov_ilog(c->entries-count));
|
||||
|
||||
}else{
|
||||
/* length random. Again, we don't code the codeword itself, just
|
||||
the length. This time, though, we have to encode each length */
|
||||
oggpack_write(opb,0,1); /* unordered */
|
||||
|
||||
/* algortihmic mapping has use for 'unused entries', which we tag
|
||||
here. The algorithmic mapping happens as usual, but the unused
|
||||
entry has no codeword. */
|
||||
for(i=0;i<c->entries;i++)
|
||||
if(c->lengthlist[i]==0)break;
|
||||
|
||||
if(i==c->entries){
|
||||
oggpack_write(opb,0,1); /* no unused entries */
|
||||
for(i=0;i<c->entries;i++)
|
||||
oggpack_write(opb,c->lengthlist[i]-1,5);
|
||||
}else{
|
||||
oggpack_write(opb,1,1); /* we have unused entries; thus we tag */
|
||||
for(i=0;i<c->entries;i++){
|
||||
if(c->lengthlist[i]==0){
|
||||
oggpack_write(opb,0,1);
|
||||
}else{
|
||||
oggpack_write(opb,1,1);
|
||||
oggpack_write(opb,c->lengthlist[i]-1,5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* is the entry number the desired return value, or do we have a
|
||||
mapping? If we have a mapping, what type? */
|
||||
oggpack_write(opb,c->maptype,4);
|
||||
switch(c->maptype){
|
||||
case 0:
|
||||
/* no mapping */
|
||||
break;
|
||||
case 1:case 2:
|
||||
/* implicitly populated value mapping */
|
||||
/* explicitly populated value mapping */
|
||||
|
||||
if(!c->quantlist){
|
||||
/* no quantlist? error */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* values that define the dequantization */
|
||||
oggpack_write(opb,c->q_min,32);
|
||||
oggpack_write(opb,c->q_delta,32);
|
||||
oggpack_write(opb,c->q_quant-1,4);
|
||||
oggpack_write(opb,c->q_sequencep,1);
|
||||
|
||||
{
|
||||
int quantvals;
|
||||
switch(c->maptype){
|
||||
case 1:
|
||||
/* a single column of (c->entries/c->dim) quantized values for
|
||||
building a full value list algorithmically (square lattice) */
|
||||
quantvals=_book_maptype1_quantvals(c);
|
||||
break;
|
||||
case 2:
|
||||
/* every value (c->entries*c->dim total) specified explicitly */
|
||||
quantvals=c->entries*c->dim;
|
||||
break;
|
||||
default: /* NOT_REACHABLE */
|
||||
quantvals=-1;
|
||||
}
|
||||
|
||||
/* quantized values */
|
||||
for(i=0;i<quantvals;i++)
|
||||
oggpack_write(opb,labs(c->quantlist[i]),c->q_quant);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* error case; we don't have any other map types now */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* unpacks a codebook from the packet buffer into the codebook struct,
|
||||
readies the codebook auxiliary structures for decode *************/
|
||||
static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
|
||||
long i,j;
|
||||
static_codebook *s=(static_codebook*)_ogg_calloc(1,sizeof(*s));
|
||||
s->allocedp=1;
|
||||
|
||||
/* make sure alignment is correct */
|
||||
if(oggpack_read(opb,24)!=0x564342)goto _eofout;
|
||||
|
||||
/* first the basic parameters */
|
||||
s->dim=oggpack_read(opb,16);
|
||||
s->entries=oggpack_read(opb,24);
|
||||
if(s->entries==-1)goto _eofout;
|
||||
|
||||
if(ov_ilog(s->dim)+ov_ilog(s->entries)>24)goto _eofout;
|
||||
|
||||
/* codeword ordering.... length ordered or unordered? */
|
||||
switch((int)oggpack_read(opb,1)){
|
||||
case 0:{
|
||||
long unused;
|
||||
/* allocated but unused entries? */
|
||||
unused=oggpack_read(opb,1);
|
||||
if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
|
||||
goto _eofout;
|
||||
/* unordered */
|
||||
s->lengthlist=(char*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
|
||||
|
||||
/* allocated but unused entries? */
|
||||
if(unused){
|
||||
/* yes, unused entries */
|
||||
|
||||
for(i=0;i<s->entries;i++){
|
||||
if(oggpack_read(opb,1)){
|
||||
long num=oggpack_read(opb,5);
|
||||
if(num==-1)goto _eofout;
|
||||
s->lengthlist[i]=num+1;
|
||||
}else
|
||||
s->lengthlist[i]=0;
|
||||
}
|
||||
}else{
|
||||
/* all entries used; no tagging */
|
||||
for(i=0;i<s->entries;i++){
|
||||
long num=oggpack_read(opb,5);
|
||||
if(num==-1)goto _eofout;
|
||||
s->lengthlist[i]=num+1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case 1:
|
||||
/* ordered */
|
||||
{
|
||||
long length=oggpack_read(opb,5)+1;
|
||||
if(length==0)goto _eofout;
|
||||
s->lengthlist=(char*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
|
||||
|
||||
for(i=0;i<s->entries;){
|
||||
long num=oggpack_read(opb,ov_ilog(s->entries-i));
|
||||
if(num==-1)goto _eofout;
|
||||
if(length>32 || num>s->entries-i ||
|
||||
(num>0 && (num-1)>>(length-1)>1)){
|
||||
goto _errout;
|
||||
}
|
||||
if(length>32)goto _errout;
|
||||
for(j=0;j<num;j++,i++)
|
||||
s->lengthlist[i]=length;
|
||||
length++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* EOF */
|
||||
goto _eofout;
|
||||
}
|
||||
|
||||
/* Do we have a mapping to unpack? */
|
||||
switch((s->maptype=oggpack_read(opb,4))){
|
||||
case 0:
|
||||
/* no mapping */
|
||||
break;
|
||||
case 1: case 2:
|
||||
/* implicitly populated value mapping */
|
||||
/* explicitly populated value mapping */
|
||||
|
||||
s->q_min=oggpack_read(opb,32);
|
||||
s->q_delta=oggpack_read(opb,32);
|
||||
s->q_quant=oggpack_read(opb,4)+1;
|
||||
s->q_sequencep=oggpack_read(opb,1);
|
||||
if(s->q_sequencep==-1)goto _eofout;
|
||||
|
||||
{
|
||||
int quantvals=0;
|
||||
switch(s->maptype){
|
||||
case 1:
|
||||
quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
|
||||
break;
|
||||
case 2:
|
||||
quantvals=s->entries*s->dim;
|
||||
break;
|
||||
}
|
||||
|
||||
/* quantized values */
|
||||
if(((quantvals*s->q_quant+7)>>3)>opb->storage-oggpack_bytes(opb))
|
||||
goto _eofout;
|
||||
s->quantlist=(long*)_ogg_malloc(sizeof(*s->quantlist)*quantvals);
|
||||
for(i=0;i<quantvals;i++)
|
||||
s->quantlist[i]=oggpack_read(opb,s->q_quant);
|
||||
|
||||
if(quantvals&&s->quantlist[quantvals-1]==-1)goto _eofout;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
goto _errout;
|
||||
}
|
||||
|
||||
/* all set */
|
||||
return(s);
|
||||
|
||||
_errout:
|
||||
_eofout:
|
||||
vorbis_staticbook_destroy(s);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* returns the number of bits ************************************************/
|
||||
int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){
|
||||
if(a<0 || a>=book->c->entries)return(0);
|
||||
oggpack_write(b,book->codelist[a],book->c->lengthlist[a]);
|
||||
return(book->c->lengthlist[a]);
|
||||
}
|
||||
|
||||
/* the 'eliminate the decode tree' optimization actually requires the
|
||||
codewords to be MSb first, not LSb. This is an annoying inelegancy
|
||||
(and one of the first places where carefully thought out design
|
||||
turned out to be wrong; Vorbis II and future Ogg codecs should go
|
||||
to an MSb bitpacker), but not actually the huge hit it appears to
|
||||
be. The first-stage decode table catches most words so that
|
||||
bitreverse is not in the main execution path. */
|
||||
|
||||
static ogg_uint32_t bitreverse(ogg_uint32_t x){
|
||||
x= ((x>>16)&0x0000ffff) | ((x<<16)&0xffff0000);
|
||||
x= ((x>> 8)&0x00ff00ff) | ((x<< 8)&0xff00ff00);
|
||||
x= ((x>> 4)&0x0f0f0f0f) | ((x<< 4)&0xf0f0f0f0);
|
||||
x= ((x>> 2)&0x33333333) | ((x<< 2)&0xcccccccc);
|
||||
return((x>> 1)&0x55555555) | ((x<< 1)&0xaaaaaaaa);
|
||||
}
|
||||
|
||||
STIN long decode_packed_entry_number(codebook *book, oggpack_buffer *b){
|
||||
int read=book->dec_maxlength;
|
||||
long lo,hi;
|
||||
long lok = oggpack_look(b,book->dec_firsttablen);
|
||||
|
||||
if (lok >= 0) {
|
||||
long entry = book->dec_firsttable[lok];
|
||||
if(entry&0x80000000UL){
|
||||
lo=(entry>>15)&0x7fff;
|
||||
hi=book->used_entries-(entry&0x7fff);
|
||||
}else{
|
||||
oggpack_adv(b, book->dec_codelengths[entry-1]);
|
||||
return(entry-1);
|
||||
}
|
||||
}else{
|
||||
lo=0;
|
||||
hi=book->used_entries;
|
||||
}
|
||||
|
||||
/* Single entry codebooks use a firsttablen of 1 and a
|
||||
dec_maxlength of 1. If a single-entry codebook gets here (due to
|
||||
failure to read one bit above), the next look attempt will also
|
||||
fail and we'll correctly kick out instead of trying to walk the
|
||||
underformed tree */
|
||||
|
||||
lok = oggpack_look(b, read);
|
||||
|
||||
while(lok<0 && read>1)
|
||||
lok = oggpack_look(b, --read);
|
||||
if(lok<0)return -1;
|
||||
|
||||
/* bisect search for the codeword in the ordered list */
|
||||
{
|
||||
ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
|
||||
|
||||
while(hi-lo>1){
|
||||
long p=(hi-lo)>>1;
|
||||
long test=book->codelist[lo+p]>testword;
|
||||
lo+=p&(test-1);
|
||||
hi-=p&(-test);
|
||||
}
|
||||
|
||||
if(book->dec_codelengths[lo]<=read){
|
||||
oggpack_adv(b, book->dec_codelengths[lo]);
|
||||
return(lo);
|
||||
}
|
||||
}
|
||||
|
||||
oggpack_adv(b, read);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Decode side is specced and easier, because we don't need to find
|
||||
matches using different criteria; we simply read and map. There are
|
||||
two things we need to do 'depending':
|
||||
|
||||
We may need to support interleave. We don't really, but it's
|
||||
convenient to do it here rather than rebuild the vector later.
|
||||
|
||||
Cascades may be additive or multiplicitive; this is not inherent in
|
||||
the codebook, but set in the code using the codebook. Like
|
||||
interleaving, it's easiest to do it here.
|
||||
addmul==0 -> declarative (set the value)
|
||||
addmul==1 -> additive
|
||||
addmul==2 -> multiplicitive */
|
||||
|
||||
/* returns the [original, not compacted] entry number or -1 on eof *********/
|
||||
long vorbis_book_decode(codebook *book, oggpack_buffer *b){
|
||||
if(book->used_entries>0){
|
||||
long packed_entry=decode_packed_entry_number(book,b);
|
||||
if(packed_entry>=0)
|
||||
return(book->dec_index[packed_entry]);
|
||||
}
|
||||
|
||||
/* if there's no dec_index, the codebook unpacking isn't collapsed */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* returns 0 on OK or -1 on eof *************************************/
|
||||
/* decode vector / dim granularity gaurding is done in the upper layer */
|
||||
long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
if(book->used_entries>0){
|
||||
int step=n/book->dim;
|
||||
long *entry = (long*)alloca(sizeof(*entry)*step);
|
||||
float **t = (float**)alloca(sizeof(*t)*step);
|
||||
int i,j,o;
|
||||
|
||||
for (i = 0; i < step; i++) {
|
||||
entry[i]=decode_packed_entry_number(book,b);
|
||||
if(entry[i]==-1)return(-1);
|
||||
t[i] = book->valuelist+entry[i]*book->dim;
|
||||
}
|
||||
for(i=0,o=0;i<book->dim;i++,o+=step)
|
||||
for (j=0;o+j<n && j<step;j++)
|
||||
a[o+j]+=t[j][i];
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* decode vector / dim granularity gaurding is done in the upper layer */
|
||||
long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
if(book->used_entries>0){
|
||||
int i,j,entry;
|
||||
float *t;
|
||||
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
for(j=0;i<n && j<book->dim;)
|
||||
a[i++]+=t[j++];
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* unlike the others, we guard against n not being an integer number
|
||||
of <dim> internally rather than in the upper layer (called only by
|
||||
floor0) */
|
||||
long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
if(book->used_entries>0){
|
||||
int i,j,entry;
|
||||
float *t;
|
||||
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
for (j=0;i<n && j<book->dim;){
|
||||
a[i++]=t[j++];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
int i;
|
||||
|
||||
for(i=0;i<n;){
|
||||
a[i++]=0.f;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
|
||||
oggpack_buffer *b,int n){
|
||||
|
||||
long i,j,entry;
|
||||
int chptr=0;
|
||||
if(book->used_entries>0){
|
||||
int m=(offset+n)/ch;
|
||||
for(i=offset/ch;i<m;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
{
|
||||
const float *t = book->valuelist+entry*book->dim;
|
||||
for (j=0;i<m && j<book->dim;j++){
|
||||
a[chptr++][i]+=t[j];
|
||||
if(chptr==ch){
|
||||
chptr=0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
+117
@@ -0,0 +1,117 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic shared codebook operations
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_CODEBOOK_H_
|
||||
#define _V_CODEBOOK_H_
|
||||
|
||||
#include "../../ogg.h"
|
||||
|
||||
/* This structure encapsulates huffman and VQ style encoding books; it
|
||||
doesn't do anything specific to either.
|
||||
|
||||
valuelist/quantlist are nonNULL (and q_* significant) only if
|
||||
there's entry->value mapping to be done.
|
||||
|
||||
If encode-side mapping must be done (and thus the entry needs to be
|
||||
hunted), the auxiliary encode pointer will point to a decision
|
||||
tree. This is true of both VQ and huffman, but is mostly useful
|
||||
with VQ.
|
||||
|
||||
*/
|
||||
|
||||
typedef struct static_codebook{
|
||||
long dim; /* codebook dimensions (elements per vector) */
|
||||
long entries; /* codebook entries */
|
||||
char *lengthlist; /* codeword lengths in bits */
|
||||
|
||||
/* mapping ***************************************************************/
|
||||
int maptype; /* 0=none
|
||||
1=implicitly populated values from map column
|
||||
2=listed arbitrary values */
|
||||
|
||||
/* The below does a linear, single monotonic sequence mapping. */
|
||||
long q_min; /* packed 32 bit float; quant value 0 maps to minval */
|
||||
long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */
|
||||
int q_quant; /* bits: 0 < quant <= 16 */
|
||||
int q_sequencep; /* bitflag */
|
||||
|
||||
long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map
|
||||
map == 2: list of dim*entries quantized entry vals
|
||||
*/
|
||||
int allocedp;
|
||||
} static_codebook;
|
||||
|
||||
typedef struct codebook{
|
||||
long dim; /* codebook dimensions (elements per vector) */
|
||||
long entries; /* codebook entries */
|
||||
long used_entries; /* populated codebook entries */
|
||||
const static_codebook *c;
|
||||
|
||||
/* for encode, the below are entry-ordered, fully populated */
|
||||
/* for decode, the below are ordered by bitreversed codeword and only
|
||||
used entries are populated */
|
||||
float *valuelist; /* list of dim*entries actual entry values */
|
||||
ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */
|
||||
|
||||
int *dec_index; /* only used if sparseness collapsed */
|
||||
char *dec_codelengths;
|
||||
ogg_uint32_t *dec_firsttable;
|
||||
int dec_firsttablen;
|
||||
int dec_maxlength;
|
||||
|
||||
/* The current encoder uses only centered, integer-only lattice books. */
|
||||
int quantvals;
|
||||
int minval;
|
||||
int delta;
|
||||
} codebook;
|
||||
|
||||
extern void vorbis_staticbook_destroy(static_codebook *b);
|
||||
extern int vorbis_book_init_encode(codebook *dest,const static_codebook *source);
|
||||
extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source);
|
||||
extern void vorbis_book_clear(codebook *b);
|
||||
|
||||
extern float *_book_unquantize(const static_codebook *b,int n,int *map);
|
||||
extern float *_book_logdist(const static_codebook *b,float *vals);
|
||||
extern float _float32_unpack(long val);
|
||||
extern long _float32_pack(float val);
|
||||
extern int _best(codebook *book, float *a, int step);
|
||||
extern long _book_maptype1_quantvals(const static_codebook *b);
|
||||
|
||||
extern int vorbis_book_besterror(codebook *book,float *a,int step,int addmul);
|
||||
extern long vorbis_book_codeword(codebook *book,int entry);
|
||||
extern long vorbis_book_codelen(codebook *book,int entry);
|
||||
|
||||
|
||||
|
||||
extern int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b);
|
||||
extern static_codebook *vorbis_staticbook_unpack(oggpack_buffer *b);
|
||||
|
||||
extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b);
|
||||
|
||||
extern long vorbis_book_decode(codebook *book, oggpack_buffer *b);
|
||||
extern long vorbis_book_decodevs_add(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodev_set(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodev_add(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodevv_add(codebook *book, float **a,
|
||||
long off,int ch,
|
||||
oggpack_buffer *b,int n);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_CODECI_H_
|
||||
#define _V_CODECI_H_
|
||||
|
||||
#include "envelope.h"
|
||||
#include "codebook.h"
|
||||
|
||||
#define BLOCKTYPE_IMPULSE 0
|
||||
#define BLOCKTYPE_PADDING 1
|
||||
#define BLOCKTYPE_TRANSITION 0
|
||||
#define BLOCKTYPE_LONG 1
|
||||
|
||||
#define PACKETBLOBS 15
|
||||
|
||||
typedef struct vorbis_block_internal{
|
||||
float **pcmdelay; /* this is a pointer into local storage */
|
||||
float ampmax;
|
||||
int blocktype;
|
||||
|
||||
oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed;
|
||||
blob [PACKETBLOBS/2] points to
|
||||
the oggpack_buffer in the
|
||||
main vorbis_block */
|
||||
} vorbis_block_internal;
|
||||
|
||||
typedef void vorbis_look_floor;
|
||||
typedef void vorbis_look_residue;
|
||||
typedef void vorbis_look_transform;
|
||||
|
||||
/* mode ************************************************************/
|
||||
typedef struct {
|
||||
int blockflag;
|
||||
int windowtype;
|
||||
int transformtype;
|
||||
int mapping;
|
||||
} vorbis_info_mode;
|
||||
|
||||
typedef void vorbis_info_floor;
|
||||
typedef void vorbis_info_residue;
|
||||
typedef void vorbis_info_mapping;
|
||||
|
||||
#include "psy.h"
|
||||
#include "bitrate.h"
|
||||
|
||||
typedef struct private_state {
|
||||
/* local lookup storage */
|
||||
envelope_lookup *ve; /* envelope lookup */
|
||||
int window[2];
|
||||
vorbis_look_transform **transform[2]; /* block, type */
|
||||
drft_lookup fft_look[2];
|
||||
|
||||
int modebits;
|
||||
vorbis_look_floor **flr;
|
||||
vorbis_look_residue **residue;
|
||||
vorbis_look_psy *psy;
|
||||
vorbis_look_psy_global *psy_g_look;
|
||||
|
||||
/* local storage, only used on the encoding side. This way the
|
||||
application does not need to worry about freeing some packets'
|
||||
memory and not others'; packet storage is always tracked.
|
||||
Cleared next call to a _dsp_ function */
|
||||
unsigned char *header;
|
||||
unsigned char *header1;
|
||||
unsigned char *header2;
|
||||
|
||||
bitrate_manager_state bms;
|
||||
|
||||
ogg_int64_t sample_count;
|
||||
} private_state;
|
||||
|
||||
/* codec_setup_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc).
|
||||
*********************************************************************/
|
||||
|
||||
#include "highlevel.h"
|
||||
typedef struct codec_setup_info {
|
||||
|
||||
/* Vorbis supports only short and long blocks, but allows the
|
||||
encoder to choose the sizes */
|
||||
|
||||
long blocksizes[2];
|
||||
|
||||
/* modes are the primary means of supporting on-the-fly different
|
||||
blocksizes, different channel mappings (LR or M/A),
|
||||
different residue backends, etc. Each mode consists of a
|
||||
blocksize flag and a mapping (along with the mapping setup */
|
||||
|
||||
int modes;
|
||||
int maps;
|
||||
int floors;
|
||||
int residues;
|
||||
int books;
|
||||
int psys; /* encode only */
|
||||
|
||||
vorbis_info_mode *mode_param[64];
|
||||
int map_type[64];
|
||||
vorbis_info_mapping *map_param[64];
|
||||
int floor_type[64];
|
||||
vorbis_info_floor *floor_param[64];
|
||||
int residue_type[64];
|
||||
vorbis_info_residue *residue_param[64];
|
||||
static_codebook *book_param[256];
|
||||
codebook *fullbooks;
|
||||
|
||||
vorbis_info_psy *psy_param[4]; /* encode only */
|
||||
vorbis_info_psy_global psy_g_param;
|
||||
|
||||
bitrate_manager_info bi;
|
||||
highlevel_encode_setup hi; /* used only by vorbisenc.c. It's a
|
||||
highly redundant structure, but
|
||||
improves clarity of program flow. */
|
||||
int halfrate_flag; /* painless downsample for decode */
|
||||
} codec_setup_info;
|
||||
|
||||
extern vorbis_look_psy_global *_vp_global_look(vorbis_info *vi);
|
||||
extern void _vp_global_free(vorbis_look_psy_global *look);
|
||||
|
||||
|
||||
|
||||
typedef struct {
|
||||
int sorted_index[VIF_POSIT+2];
|
||||
int forward_index[VIF_POSIT+2];
|
||||
int reverse_index[VIF_POSIT+2];
|
||||
|
||||
int hineighbor[VIF_POSIT];
|
||||
int loneighbor[VIF_POSIT];
|
||||
int posts;
|
||||
|
||||
int n;
|
||||
int quant_q;
|
||||
vorbis_info_floor1 *vi;
|
||||
|
||||
long phrasebits;
|
||||
long postbits;
|
||||
long frames;
|
||||
} vorbis_look_floor1;
|
||||
|
||||
|
||||
|
||||
extern int *floor1_fit(vorbis_block *vb,vorbis_look_floor1 *look,
|
||||
const float *logmdct, /* in */
|
||||
const float *logmask);
|
||||
extern int *floor1_interpolate_fit(vorbis_block *vb,vorbis_look_floor1 *look,
|
||||
int *A,int *B,
|
||||
int del);
|
||||
extern int floor1_encode(oggpack_buffer *opb,vorbis_block *vb,
|
||||
vorbis_look_floor1 *look,
|
||||
int *post,int *ilogmask);
|
||||
#endif
|
||||
+374
@@ -0,0 +1,374 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
|
||||
#include "os.h"
|
||||
#include "scales.h"
|
||||
#include "envelope.h"
|
||||
#include "mdct.h"
|
||||
#include "misc.h"
|
||||
|
||||
void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
vorbis_info_psy_global *gi=&ci->psy_g_param;
|
||||
int ch=vi->channels;
|
||||
int i,j;
|
||||
int n=e->winlength=128;
|
||||
e->searchstep=64; /* not random */
|
||||
|
||||
e->minenergy=gi->preecho_minenergy;
|
||||
e->ch=ch;
|
||||
e->storage=128;
|
||||
e->cursor=ci->blocksizes[1]/2;
|
||||
e->mdct_win=(float*)_ogg_calloc(n,sizeof(*e->mdct_win));
|
||||
mdct_init(&e->mdct,n);
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
e->mdct_win[i]=sin(i/(n-1.)*M_PI);
|
||||
e->mdct_win[i]*=e->mdct_win[i];
|
||||
}
|
||||
|
||||
/* magic follows */
|
||||
e->band[0].begin=2; e->band[0].end=4;
|
||||
e->band[1].begin=4; e->band[1].end=5;
|
||||
e->band[2].begin=6; e->band[2].end=6;
|
||||
e->band[3].begin=9; e->band[3].end=8;
|
||||
e->band[4].begin=13; e->band[4].end=8;
|
||||
e->band[5].begin=17; e->band[5].end=8;
|
||||
e->band[6].begin=22; e->band[6].end=8;
|
||||
|
||||
for(j=0;j<VE_BANDS;j++){
|
||||
n=e->band[j].end;
|
||||
e->band[j].window=(float*)_ogg_malloc(n*sizeof(*e->band[0].window));
|
||||
for(i=0;i<n;i++){
|
||||
e->band[j].window[i]=sin((i+.5)/n*M_PI);
|
||||
e->band[j].total+=e->band[j].window[i];
|
||||
}
|
||||
e->band[j].total=1./e->band[j].total;
|
||||
}
|
||||
|
||||
e->filter=(envelope_filter_state*)_ogg_calloc(VE_BANDS*ch,sizeof(*e->filter));
|
||||
e->mark=(int*)_ogg_calloc(e->storage,sizeof(*e->mark));
|
||||
|
||||
}
|
||||
|
||||
void _ve_envelope_clear(envelope_lookup *e){
|
||||
int i;
|
||||
mdct_clear(&e->mdct);
|
||||
for(i=0;i<VE_BANDS;i++)
|
||||
_ogg_free(e->band[i].window);
|
||||
_ogg_free(e->mdct_win);
|
||||
_ogg_free(e->filter);
|
||||
_ogg_free(e->mark);
|
||||
memset(e,0,sizeof(*e));
|
||||
}
|
||||
|
||||
/* fairly straight threshhold-by-band based until we find something
|
||||
that works better and isn't patented. */
|
||||
|
||||
static int _ve_amp(envelope_lookup *ve,
|
||||
vorbis_info_psy_global *gi,
|
||||
float *data,
|
||||
envelope_band *bands,
|
||||
envelope_filter_state *filters){
|
||||
long n=ve->winlength;
|
||||
int ret=0;
|
||||
long i,j;
|
||||
float decay;
|
||||
|
||||
/* we want to have a 'minimum bar' for energy, else we're just
|
||||
basing blocks on quantization noise that outweighs the signal
|
||||
itself (for low power signals) */
|
||||
|
||||
float minV=ve->minenergy;
|
||||
float *vec=(float*) alloca(n*sizeof(*vec));
|
||||
|
||||
/* stretch is used to gradually lengthen the number of windows
|
||||
considered prevoius-to-potential-trigger */
|
||||
int stretch=max(VE_MINSTRETCH,ve->stretch/2);
|
||||
float penalty=gi->stretch_penalty-(ve->stretch/2-VE_MINSTRETCH);
|
||||
if(penalty<0.f)penalty=0.f;
|
||||
if(penalty>gi->stretch_penalty)penalty=gi->stretch_penalty;
|
||||
|
||||
/*_analysis_output_always("lpcm",seq2,data,n,0,0,
|
||||
totalshift+pos*ve->searchstep);*/
|
||||
|
||||
/* window and transform */
|
||||
for(i=0;i<n;i++)
|
||||
vec[i]=data[i]*ve->mdct_win[i];
|
||||
mdct_forward(&ve->mdct,vec,vec);
|
||||
|
||||
/*_analysis_output_always("mdct",seq2,vec,n/2,0,1,0); */
|
||||
|
||||
/* near-DC spreading function; this has nothing to do with
|
||||
psychoacoustics, just sidelobe leakage and window size */
|
||||
{
|
||||
float temp=vec[0]*vec[0]+.7*vec[1]*vec[1]+.2*vec[2]*vec[2];
|
||||
int ptr=filters->nearptr;
|
||||
|
||||
/* the accumulation is regularly refreshed from scratch to avoid
|
||||
floating point creep */
|
||||
if(ptr==0){
|
||||
decay=filters->nearDC_acc=filters->nearDC_partialacc+temp;
|
||||
filters->nearDC_partialacc=temp;
|
||||
}else{
|
||||
decay=filters->nearDC_acc+=temp;
|
||||
filters->nearDC_partialacc+=temp;
|
||||
}
|
||||
filters->nearDC_acc-=filters->nearDC[ptr];
|
||||
filters->nearDC[ptr]=temp;
|
||||
|
||||
decay*=(1./(VE_NEARDC+1));
|
||||
filters->nearptr++;
|
||||
if(filters->nearptr>=VE_NEARDC)filters->nearptr=0;
|
||||
decay=todB(&decay)*.5-15.f;
|
||||
}
|
||||
|
||||
/* perform spreading and limiting, also smooth the spectrum. yes,
|
||||
the MDCT results in all real coefficients, but it still *behaves*
|
||||
like real/imaginary pairs */
|
||||
for(i=0;i<n/2;i+=2){
|
||||
float val=vec[i]*vec[i]+vec[i+1]*vec[i+1];
|
||||
val=todB(&val)*.5f;
|
||||
if(val<decay)val=decay;
|
||||
if(val<minV)val=minV;
|
||||
vec[i>>1]=val;
|
||||
decay-=8.;
|
||||
}
|
||||
|
||||
/*_analysis_output_always("spread",seq2++,vec,n/4,0,0,0);*/
|
||||
|
||||
/* perform preecho/postecho triggering by band */
|
||||
for(j=0;j<VE_BANDS;j++){
|
||||
float acc=0.;
|
||||
float valmax,valmin;
|
||||
|
||||
/* accumulate amplitude */
|
||||
for(i=0;i<bands[j].end;i++)
|
||||
acc+=vec[i+bands[j].begin]*bands[j].window[i];
|
||||
|
||||
acc*=bands[j].total;
|
||||
|
||||
/* convert amplitude to delta */
|
||||
{
|
||||
int p,thisx=filters[j].ampptr;
|
||||
float postmax,postmin,premax=-99999.f,premin=99999.f;
|
||||
|
||||
p=thisx;
|
||||
p--;
|
||||
if(p<0)p+=VE_AMP;
|
||||
postmax=max(acc,filters[j].ampbuf[p]);
|
||||
postmin=min(acc,filters[j].ampbuf[p]);
|
||||
|
||||
for(i=0;i<stretch;i++){
|
||||
p--;
|
||||
if(p<0)p+=VE_AMP;
|
||||
premax=max(premax,filters[j].ampbuf[p]);
|
||||
premin=min(premin,filters[j].ampbuf[p]);
|
||||
}
|
||||
|
||||
valmin=postmin-premin;
|
||||
valmax=postmax-premax;
|
||||
|
||||
/*filters[j].markers[pos]=valmax;*/
|
||||
filters[j].ampbuf[thisx]=acc;
|
||||
filters[j].ampptr++;
|
||||
if(filters[j].ampptr>=VE_AMP)filters[j].ampptr=0;
|
||||
}
|
||||
|
||||
/* look at min/max, decide trigger */
|
||||
if(valmax>gi->preecho_thresh[j]+penalty){
|
||||
ret|=1;
|
||||
ret|=4;
|
||||
}
|
||||
if(valmin<gi->postecho_thresh[j]-penalty)ret|=2;
|
||||
}
|
||||
|
||||
return(ret);
|
||||
}
|
||||
|
||||
#if 0
|
||||
static int seq=0;
|
||||
static ogg_int64_t totalshift=-1024;
|
||||
#endif
|
||||
|
||||
long _ve_envelope_search(vorbis_dsp_state *v){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
|
||||
vorbis_info_psy_global *gi=&ci->psy_g_param;
|
||||
envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
|
||||
long i,j;
|
||||
|
||||
int first=ve->current/ve->searchstep;
|
||||
int last=v->pcm_current/ve->searchstep-VE_WIN;
|
||||
if(first<0)first=0;
|
||||
|
||||
/* make sure we have enough storage to match the PCM */
|
||||
if(last+VE_WIN+VE_POST>ve->storage){
|
||||
ve->storage=last+VE_WIN+VE_POST; /* be sure */
|
||||
ve->mark=(int*)_ogg_realloc(ve->mark,ve->storage*sizeof(*ve->mark));
|
||||
}
|
||||
|
||||
for(j=first;j<last;j++){
|
||||
int ret=0;
|
||||
|
||||
ve->stretch++;
|
||||
if(ve->stretch>VE_MAXSTRETCH*2)
|
||||
ve->stretch=VE_MAXSTRETCH*2;
|
||||
|
||||
for(i=0;i<ve->ch;i++){
|
||||
float *pcm=v->pcm[i]+ve->searchstep*(j);
|
||||
ret|=_ve_amp(ve,gi,pcm,ve->band,ve->filter+i*VE_BANDS);
|
||||
}
|
||||
|
||||
ve->mark[j+VE_POST]=0;
|
||||
if(ret&1){
|
||||
ve->mark[j]=1;
|
||||
ve->mark[j+1]=1;
|
||||
}
|
||||
|
||||
if(ret&2){
|
||||
ve->mark[j]=1;
|
||||
if(j>0)ve->mark[j-1]=1;
|
||||
}
|
||||
|
||||
if(ret&4)ve->stretch=-1;
|
||||
}
|
||||
|
||||
ve->current=last*ve->searchstep;
|
||||
|
||||
{
|
||||
long centerW=v->centerW;
|
||||
long testW=
|
||||
centerW+
|
||||
ci->blocksizes[v->W]/4+
|
||||
ci->blocksizes[1]/2+
|
||||
ci->blocksizes[0]/4;
|
||||
|
||||
j=ve->cursor;
|
||||
|
||||
while(j<ve->current-(ve->searchstep)){/* account for postecho
|
||||
working back one window */
|
||||
if(j>=testW)return(1);
|
||||
|
||||
ve->cursor=j;
|
||||
|
||||
if(ve->mark[j/ve->searchstep]){
|
||||
if(j>centerW){
|
||||
|
||||
#if 0
|
||||
if(j>ve->curmark){
|
||||
float *marker=(float*)alloca(v->pcm_current*sizeof(*marker));
|
||||
int l,m;
|
||||
memset(marker,0,sizeof(*marker)*v->pcm_current);
|
||||
fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n",
|
||||
seq,
|
||||
(totalshift+ve->cursor)/44100.,
|
||||
(totalshift+j)/44100.);
|
||||
_analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift);
|
||||
_analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift);
|
||||
|
||||
_analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift);
|
||||
_analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift);
|
||||
|
||||
for(m=0;m<VE_BANDS;m++){
|
||||
char buf[80];
|
||||
sprintf(buf,"delL%d",m);
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m].markers[l]*.1;
|
||||
_analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
|
||||
}
|
||||
|
||||
for(m=0;m<VE_BANDS;m++){
|
||||
char buf[80];
|
||||
sprintf(buf,"delR%d",m);
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m+VE_BANDS].markers[l]*.1;
|
||||
_analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
|
||||
}
|
||||
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->mark[l]*.4;
|
||||
_analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift);
|
||||
|
||||
|
||||
seq++;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
ve->curmark=j;
|
||||
if(j>=testW)return(1);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
j+=ve->searchstep;
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int _ve_envelope_mark(vorbis_dsp_state *v){
|
||||
envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
long centerW=v->centerW;
|
||||
long beginW=centerW-ci->blocksizes[v->W]/4;
|
||||
long endW=centerW+ci->blocksizes[v->W]/4;
|
||||
if(v->W){
|
||||
beginW-=ci->blocksizes[v->lW]/4;
|
||||
endW+=ci->blocksizes[v->nW]/4;
|
||||
}else{
|
||||
beginW-=ci->blocksizes[0]/4;
|
||||
endW+=ci->blocksizes[0]/4;
|
||||
}
|
||||
|
||||
if(ve->curmark>=beginW && ve->curmark<endW)return(1);
|
||||
{
|
||||
long first=beginW/ve->searchstep;
|
||||
long last=endW/ve->searchstep;
|
||||
long i;
|
||||
for(i=first;i<last;i++)
|
||||
if(ve->mark[i])return(1);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
void _ve_envelope_shift(envelope_lookup *e,long shift){
|
||||
int smallsize=e->current/e->searchstep+VE_POST; /* adjust for placing marks
|
||||
ahead of ve->current */
|
||||
int smallshift=shift/e->searchstep;
|
||||
|
||||
memmove(e->mark,e->mark+smallshift,(smallsize-smallshift)*sizeof(*e->mark));
|
||||
|
||||
#if 0
|
||||
for(i=0;i<VE_BANDS*e->ch;i++)
|
||||
memmove(e->filter[i].markers,
|
||||
e->filter[i].markers+smallshift,
|
||||
(1024-smallshift)*sizeof(*(*e->filter).markers));
|
||||
totalshift+=shift;
|
||||
#endif
|
||||
|
||||
e->current-=shift;
|
||||
if(e->curmark>=0)
|
||||
e->curmark-=shift;
|
||||
e->cursor-=shift;
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis and manipulation
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_ENVELOPE_
|
||||
#define _V_ENVELOPE_
|
||||
|
||||
#include "mdct.h"
|
||||
|
||||
#define VE_PRE 16
|
||||
#define VE_WIN 4
|
||||
#define VE_POST 2
|
||||
#define VE_AMP (VE_PRE+VE_POST-1)
|
||||
|
||||
#define VE_BANDS 7
|
||||
#define VE_NEARDC 15
|
||||
|
||||
#define VE_MINSTRETCH 2 /* a bit less than short block */
|
||||
#define VE_MAXSTRETCH 12 /* one-third full block */
|
||||
|
||||
typedef struct {
|
||||
float ampbuf[VE_AMP];
|
||||
int ampptr;
|
||||
|
||||
float nearDC[VE_NEARDC];
|
||||
float nearDC_acc;
|
||||
float nearDC_partialacc;
|
||||
int nearptr;
|
||||
|
||||
} envelope_filter_state;
|
||||
|
||||
typedef struct {
|
||||
int begin;
|
||||
int end;
|
||||
float *window;
|
||||
float total;
|
||||
} envelope_band;
|
||||
|
||||
typedef struct {
|
||||
int ch;
|
||||
int winlength;
|
||||
int searchstep;
|
||||
float minenergy;
|
||||
|
||||
mdct_lookup mdct;
|
||||
float *mdct_win;
|
||||
|
||||
envelope_band band[VE_BANDS];
|
||||
envelope_filter_state *filter;
|
||||
int stretch;
|
||||
|
||||
int *mark;
|
||||
|
||||
long storage;
|
||||
long current;
|
||||
long curmark;
|
||||
long cursor;
|
||||
} envelope_lookup;
|
||||
|
||||
extern void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi);
|
||||
extern void _ve_envelope_clear(envelope_lookup *e);
|
||||
extern long _ve_envelope_search(vorbis_dsp_state *v);
|
||||
extern void _ve_envelope_shift(envelope_lookup *e,long shift);
|
||||
extern int _ve_envelope_mark(vorbis_dsp_state *v);
|
||||
|
||||
|
||||
#endif
|
||||
+220
@@ -0,0 +1,220 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: floor backend 0 implementation
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "registry.h"
|
||||
#include "lpc.h"
|
||||
#include "lsp.h"
|
||||
#include "codebook.h"
|
||||
#include "scales.h"
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
|
||||
#include "misc.h"
|
||||
#include <stdio.h>
|
||||
|
||||
typedef struct {
|
||||
int ln;
|
||||
int m;
|
||||
int **linearmap;
|
||||
int n[2];
|
||||
|
||||
vorbis_info_floor0 *vi;
|
||||
|
||||
long bits;
|
||||
long frames;
|
||||
} vorbis_look_floor0;
|
||||
|
||||
|
||||
/***********************************************/
|
||||
|
||||
static void floor0_free_info(vorbis_info_floor *i){
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
|
||||
if(info){
|
||||
memset(info,0,sizeof(*info));
|
||||
_ogg_free(info);
|
||||
}
|
||||
}
|
||||
|
||||
static void floor0_free_look(vorbis_look_floor *i){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
if(look){
|
||||
|
||||
if(look->linearmap){
|
||||
|
||||
if(look->linearmap[0])_ogg_free(look->linearmap[0]);
|
||||
if(look->linearmap[1])_ogg_free(look->linearmap[1]);
|
||||
|
||||
_ogg_free(look->linearmap);
|
||||
}
|
||||
memset(look,0,sizeof(*look));
|
||||
_ogg_free(look);
|
||||
}
|
||||
}
|
||||
|
||||
static vorbis_info_floor *floor0_unpack (vorbis_info *vi,oggpack_buffer *opb){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
int j;
|
||||
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0*)_ogg_malloc(sizeof(*info));
|
||||
info->order=oggpack_read(opb,8);
|
||||
info->rate=oggpack_read(opb,16);
|
||||
info->barkmap=oggpack_read(opb,16);
|
||||
info->ampbits=oggpack_read(opb,6);
|
||||
info->ampdB=oggpack_read(opb,8);
|
||||
info->numbooks=oggpack_read(opb,4)+1;
|
||||
|
||||
if(info->order<1)goto err_out;
|
||||
if(info->rate<1)goto err_out;
|
||||
if(info->barkmap<1)goto err_out;
|
||||
if(info->numbooks<1)goto err_out;
|
||||
|
||||
for(j=0;j<info->numbooks;j++){
|
||||
info->books[j]=oggpack_read(opb,8);
|
||||
if(info->books[j]<0 || info->books[j]>=ci->books)goto err_out;
|
||||
if(ci->book_param[info->books[j]]->maptype==0)goto err_out;
|
||||
if(ci->book_param[info->books[j]]->dim<1)goto err_out;
|
||||
}
|
||||
return(info);
|
||||
|
||||
err_out:
|
||||
floor0_free_info(info);
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
/* initialize Bark scale and normalization lookups. We could do this
|
||||
with static tables, but Vorbis allows a number of possible
|
||||
combinations, so it's best to do it computationally.
|
||||
|
||||
The below is authoritative in terms of defining scale mapping.
|
||||
Note that the scale depends on the sampling rate as well as the
|
||||
linear block and mapping sizes */
|
||||
|
||||
static void floor0_map_lazy_init(vorbis_block *vb,
|
||||
vorbis_info_floor *infoX,
|
||||
vorbis_look_floor0 *look){
|
||||
if(!look->linearmap[vb->W]){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
vorbis_info *vi=vd->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0 *)infoX;
|
||||
int W=vb->W;
|
||||
int n=ci->blocksizes[W]/2,j;
|
||||
|
||||
/* we choose a scaling constant so that:
|
||||
floor(bark(rate/2-1)*C)=mapped-1
|
||||
floor(bark(rate/2)*C)=mapped */
|
||||
float scale=look->ln/toBARK(info->rate/2.f);
|
||||
|
||||
/* the mapping from a linear scale to a smaller bark scale is
|
||||
straightforward. We do *not* make sure that the linear mapping
|
||||
does not skip bark-scale bins; the decoder simply skips them and
|
||||
the encoder may do what it wishes in filling them. They're
|
||||
necessary in some mapping combinations to keep the scale spacing
|
||||
accurate */
|
||||
look->linearmap[W]=(int*)_ogg_malloc((n+1)*sizeof(**look->linearmap));
|
||||
for(j=0;j<n;j++){
|
||||
int val=floor( toBARK((info->rate/2.f)/n*j)
|
||||
*scale); /* bark numbers represent band edges */
|
||||
if(val>=look->ln)val=look->ln-1; /* guard against the approximation */
|
||||
look->linearmap[W][j]=val;
|
||||
}
|
||||
look->linearmap[W][j]=-1;
|
||||
look->n[W]=n;
|
||||
}
|
||||
}
|
||||
|
||||
static vorbis_look_floor *floor0_look(vorbis_dsp_state* /* vd */,
|
||||
vorbis_info_floor *i){
|
||||
vorbis_info_floor0 *info=(vorbis_info_floor0 *)i;
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0*)_ogg_calloc(1,sizeof(*look));
|
||||
look->m=info->order;
|
||||
look->ln=info->barkmap;
|
||||
look->vi=info;
|
||||
|
||||
look->linearmap=(int**)_ogg_calloc(2,sizeof(*look->linearmap));
|
||||
|
||||
return look;
|
||||
}
|
||||
|
||||
static void *floor0_inverse1(vorbis_block *vb,vorbis_look_floor *i){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
vorbis_info_floor0 *info=look->vi;
|
||||
int j,k;
|
||||
|
||||
int ampraw=oggpack_read(&vb->opb,info->ampbits);
|
||||
if(ampraw>0){ /* also handles the -1 out of data case */
|
||||
long maxval=(1<<info->ampbits)-1;
|
||||
float amp=(float)ampraw/maxval*info->ampdB;
|
||||
int booknum=oggpack_read(&vb->opb,ov_ilog(info->numbooks));
|
||||
|
||||
if(booknum!=-1 && booknum<info->numbooks){ /* be paranoid */
|
||||
codec_setup_info *ci=(codec_setup_info *)vb->vd->vi->codec_setup;
|
||||
codebook *b=ci->fullbooks+info->books[booknum];
|
||||
float last=0.f;
|
||||
|
||||
/* the additional b->dim is a guard against any possible stack
|
||||
smash; b->dim is provably more than we can overflow the
|
||||
vector */
|
||||
float *lsp=(float*)_vorbis_block_alloc(vb,sizeof(*lsp)*(look->m+b->dim+1));
|
||||
|
||||
if(vorbis_book_decodev_set(b,lsp,&vb->opb,look->m)==-1)goto eop;
|
||||
for(j=0;j<look->m;){
|
||||
for(k=0;j<look->m && k<b->dim;k++,j++)lsp[j]+=last;
|
||||
last=lsp[j-1];
|
||||
}
|
||||
|
||||
lsp[look->m]=amp;
|
||||
return(lsp);
|
||||
}
|
||||
}
|
||||
eop:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
|
||||
void *memo,float *out){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
vorbis_info_floor0 *info=look->vi;
|
||||
|
||||
floor0_map_lazy_init(vb,info,look);
|
||||
|
||||
if(memo){
|
||||
float *lsp=(float *)memo;
|
||||
float amp=lsp[look->m];
|
||||
|
||||
/* take the coefficients back to a spectral envelope curve */
|
||||
vorbis_lsp_to_curve(out,
|
||||
look->linearmap[vb->W],
|
||||
look->n[vb->W],
|
||||
look->ln,
|
||||
lsp,look->m,amp,(float)info->ampdB);
|
||||
return(1);
|
||||
}
|
||||
memset(out,0,sizeof(*out)*look->n[vb->W]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* export hooks */
|
||||
const vorbis_func_floor floor0_exportbundle={
|
||||
NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
|
||||
&floor0_free_look,&floor0_inverse1,&floor0_inverse2
|
||||
};
|
||||
+1092
File diff suppressed because it is too large
Load Diff
+57
@@ -0,0 +1,57 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: highlevel encoder setup struct separated out for vorbisenc clarity
|
||||
|
||||
********************************************************************/
|
||||
|
||||
typedef struct highlevel_byblocktype {
|
||||
double tone_mask_setting;
|
||||
double tone_peaklimit_setting;
|
||||
double noise_bias_setting;
|
||||
double noise_compand_setting;
|
||||
} highlevel_byblocktype;
|
||||
|
||||
typedef struct highlevel_encode_setup {
|
||||
int set_in_stone;
|
||||
const void *setup;
|
||||
double base_setting;
|
||||
|
||||
double impulse_noisetune;
|
||||
|
||||
/* bitrate management below all settable */
|
||||
float req;
|
||||
int managed;
|
||||
long bitrate_min;
|
||||
long bitrate_av;
|
||||
double bitrate_av_damp;
|
||||
long bitrate_max;
|
||||
long bitrate_reservoir;
|
||||
double bitrate_reservoir_bias;
|
||||
|
||||
int impulse_block_p;
|
||||
int noise_normalize_p;
|
||||
int coupling_p;
|
||||
|
||||
double stereo_point_setting;
|
||||
double lowpass_kHz;
|
||||
int lowpass_altered;
|
||||
|
||||
double ath_floating_dB;
|
||||
double ath_absolute_dB;
|
||||
|
||||
double amplitude_track_dBpersec;
|
||||
double trigger_setting;
|
||||
|
||||
highlevel_byblocktype block[4]; /* padding, impulse, transition, long */
|
||||
|
||||
} highlevel_encode_setup;
|
||||
+688
@@ -0,0 +1,688 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2015 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: maintain the info structure, info <-> header packets
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* general handling of the header and the vorbis_info structure (and
|
||||
substructures) */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
#include "codebook.h"
|
||||
#include "registry.h"
|
||||
#include "window.h"
|
||||
#include "psy.h"
|
||||
#include "misc.h"
|
||||
#include "os.h"
|
||||
|
||||
#define GENERAL_VENDOR_STRING "Xiph.Org libVorbis 1.3.7"
|
||||
#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20200704 (Reducing Environment)"
|
||||
|
||||
/* helpers */
|
||||
static void _v_writestring(oggpack_buffer *o,const char *s, int bytes){
|
||||
|
||||
while(bytes--){
|
||||
oggpack_write(o,*s++,8);
|
||||
}
|
||||
}
|
||||
|
||||
static void _v_readstring(oggpack_buffer *o,char *buf,int bytes){
|
||||
while(bytes--){
|
||||
*buf++=oggpack_read(o,8);
|
||||
}
|
||||
}
|
||||
|
||||
static int _v_toupper(int c) {
|
||||
return (c >= 'a' && c <= 'z') ? (c & ~('a' - 'A')) : c;
|
||||
}
|
||||
|
||||
void vorbis_comment_init(vorbis_comment *vc){
|
||||
memset(vc,0,sizeof(*vc));
|
||||
}
|
||||
|
||||
void vorbis_comment_add(vorbis_comment *vc,const char *comment){
|
||||
vc->user_comments=(char**)_ogg_realloc(vc->user_comments,
|
||||
(vc->comments+2)*sizeof(*vc->user_comments));
|
||||
vc->comment_lengths=(int*)_ogg_realloc(vc->comment_lengths,
|
||||
(vc->comments+2)*sizeof(*vc->comment_lengths));
|
||||
vc->comment_lengths[vc->comments]=strlen(comment);
|
||||
vc->user_comments[vc->comments]=(char*)_ogg_malloc(vc->comment_lengths[vc->comments]+1);
|
||||
strcpy(vc->user_comments[vc->comments], comment);
|
||||
vc->comments++;
|
||||
vc->user_comments[vc->comments]=NULL;
|
||||
}
|
||||
|
||||
void vorbis_comment_add_tag(vorbis_comment *vc, const char *tag, const char *contents){
|
||||
/* Length for key and value +2 for = and \0 */
|
||||
char *comment=(char*)_ogg_malloc(strlen(tag)+strlen(contents)+2);
|
||||
strcpy(comment, tag);
|
||||
strcat(comment, "=");
|
||||
strcat(comment, contents);
|
||||
vorbis_comment_add(vc, comment);
|
||||
_ogg_free(comment);
|
||||
}
|
||||
|
||||
/* This is more or less the same as strncasecmp - but that doesn't exist
|
||||
* everywhere, and this is a fairly trivial function, so we include it */
|
||||
static int tagcompare(const char *s1, const char *s2, int n){
|
||||
int c=0;
|
||||
while(c < n){
|
||||
if(_v_toupper(s1[c]) != _v_toupper(s2[c]))
|
||||
return !0;
|
||||
c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){
|
||||
long i;
|
||||
int found = 0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = (char*)_ogg_malloc(taglen+1);
|
||||
|
||||
strcpy(fulltag, tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
|
||||
if(count == found) {
|
||||
/* We return a pointer to the data, not a copy */
|
||||
_ogg_free(fulltag);
|
||||
return vc->user_comments[i] + taglen;
|
||||
} else {
|
||||
found++;
|
||||
}
|
||||
}
|
||||
}
|
||||
_ogg_free(fulltag);
|
||||
return NULL; /* didn't find anything */
|
||||
}
|
||||
|
||||
int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
|
||||
int i,count=0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = (char*)_ogg_malloc(taglen+1);
|
||||
strcpy(fulltag,tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(!tagcompare(vc->user_comments[i], fulltag, taglen))
|
||||
count++;
|
||||
}
|
||||
|
||||
_ogg_free(fulltag);
|
||||
return count;
|
||||
}
|
||||
|
||||
void vorbis_comment_clear(vorbis_comment *vc){
|
||||
if(vc){
|
||||
long i;
|
||||
if(vc->user_comments){
|
||||
for(i=0;i<vc->comments;i++)
|
||||
if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
|
||||
_ogg_free(vc->user_comments);
|
||||
}
|
||||
if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
|
||||
if(vc->vendor)_ogg_free(vc->vendor);
|
||||
memset(vc,0,sizeof(*vc));
|
||||
}
|
||||
}
|
||||
|
||||
/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
|
||||
They may be equal, but short will never ge greater than long */
|
||||
int vorbis_info_blocksize(vorbis_info *vi,int zo){
|
||||
codec_setup_info *ci = (codec_setup_info*)vi->codec_setup;
|
||||
return ci ? ci->blocksizes[zo] : -1;
|
||||
}
|
||||
|
||||
/* used by synthesis, which has a full, alloced vi */
|
||||
void vorbis_info_init(vorbis_info *vi){
|
||||
memset(vi,0,sizeof(*vi));
|
||||
vi->codec_setup=_ogg_calloc(1,sizeof(codec_setup_info));
|
||||
}
|
||||
|
||||
void vorbis_info_clear(vorbis_info *vi){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
int i;
|
||||
|
||||
if(ci){
|
||||
|
||||
for(i=0;i<ci->modes;i++)
|
||||
if(ci->mode_param[i])_ogg_free(ci->mode_param[i]);
|
||||
|
||||
for(i=0;i<ci->maps;i++) /* unpack does the range checking */
|
||||
if(ci->map_param[i]) /* this may be cleaning up an aborted
|
||||
unpack, in which case the below type
|
||||
cannot be trusted */
|
||||
_mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
|
||||
|
||||
for(i=0;i<ci->floors;i++) /* unpack does the range checking */
|
||||
if(ci->floor_param[i]) /* this may be cleaning up an aborted
|
||||
unpack, in which case the below type
|
||||
cannot be trusted */
|
||||
_floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
|
||||
|
||||
for(i=0;i<ci->residues;i++) /* unpack does the range checking */
|
||||
if(ci->residue_param[i]) /* this may be cleaning up an aborted
|
||||
unpack, in which case the below type
|
||||
cannot be trusted */
|
||||
_residue_P[ci->residue_type[i]]->free_info(ci->residue_param[i]);
|
||||
|
||||
for(i=0;i<ci->books;i++){
|
||||
if(ci->book_param[i]){
|
||||
/* knows if the book was not alloced */
|
||||
vorbis_staticbook_destroy(ci->book_param[i]);
|
||||
}
|
||||
if(ci->fullbooks)
|
||||
vorbis_book_clear(ci->fullbooks+i);
|
||||
}
|
||||
if(ci->fullbooks)
|
||||
_ogg_free(ci->fullbooks);
|
||||
|
||||
for(i=0;i<ci->psys;i++)
|
||||
_vi_psy_free(ci->psy_param[i]);
|
||||
|
||||
_ogg_free(ci);
|
||||
}
|
||||
|
||||
memset(vi,0,sizeof(*vi));
|
||||
}
|
||||
|
||||
/* Header packing/unpacking ********************************************/
|
||||
|
||||
static int _vorbis_unpack_info(vorbis_info *vi,oggpack_buffer *opb){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
int bs;
|
||||
if(!ci)return(OV_EFAULT);
|
||||
|
||||
vi->version=oggpack_read(opb,32);
|
||||
if(vi->version!=0)return(OV_EVERSION);
|
||||
|
||||
vi->channels=oggpack_read(opb,8);
|
||||
vi->rate=oggpack_read(opb,32);
|
||||
|
||||
vi->bitrate_upper=(ogg_int32_t)oggpack_read(opb,32);
|
||||
vi->bitrate_nominal=(ogg_int32_t)oggpack_read(opb,32);
|
||||
vi->bitrate_lower=(ogg_int32_t)oggpack_read(opb,32);
|
||||
|
||||
bs = oggpack_read(opb,4);
|
||||
if(bs<0)goto err_out;
|
||||
ci->blocksizes[0]=1<<bs;
|
||||
bs = oggpack_read(opb,4);
|
||||
if(bs<0)goto err_out;
|
||||
ci->blocksizes[1]=1<<bs;
|
||||
|
||||
if(vi->rate<1)goto err_out;
|
||||
if(vi->channels<1)goto err_out;
|
||||
if(ci->blocksizes[0]<64)goto err_out;
|
||||
if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
|
||||
if(ci->blocksizes[1]>8192)goto err_out;
|
||||
|
||||
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_info_clear(vi);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
|
||||
int i;
|
||||
int vendorlen=oggpack_read(opb,32);
|
||||
if(vendorlen<0)goto err_out;
|
||||
if(vendorlen>opb->storage-8)goto err_out;
|
||||
vc->vendor=(char*)_ogg_calloc(vendorlen+1,1);
|
||||
_v_readstring(opb,vc->vendor,vendorlen);
|
||||
i=oggpack_read(opb,32);
|
||||
if(i<0)goto err_out;
|
||||
if(i>((opb->storage-oggpack_bytes(opb))>>2))goto err_out;
|
||||
vc->comments=i;
|
||||
vc->user_comments=(char**)_ogg_calloc(vc->comments+1,sizeof(*vc->user_comments));
|
||||
vc->comment_lengths=(int*)_ogg_calloc(vc->comments+1, sizeof(*vc->comment_lengths));
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
int len=oggpack_read(opb,32);
|
||||
if(len<0)goto err_out;
|
||||
if(len>opb->storage-oggpack_bytes(opb))goto err_out;
|
||||
vc->comment_lengths[i]=len;
|
||||
vc->user_comments[i]=(char*)_ogg_calloc(len+1,1);
|
||||
_v_readstring(opb,vc->user_comments[i],len);
|
||||
}
|
||||
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_comment_clear(vc);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
/* all of the real encoding details are here. The modes, books,
|
||||
everything */
|
||||
static int _vorbis_unpack_books(vorbis_info *vi,oggpack_buffer *opb){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
int i;
|
||||
|
||||
/* codebooks */
|
||||
ci->books=oggpack_read(opb,8)+1;
|
||||
if(ci->books<=0)goto err_out;
|
||||
for(i=0;i<ci->books;i++){
|
||||
ci->book_param[i]=vorbis_staticbook_unpack(opb);
|
||||
if(!ci->book_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* time backend settings; hooks are unused */
|
||||
{
|
||||
int times=oggpack_read(opb,6)+1;
|
||||
if(times<=0)goto err_out;
|
||||
for(i=0;i<times;i++){
|
||||
int test=oggpack_read(opb,16);
|
||||
if(test<0 || test>=VI_TIMEB)goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* floor backend settings */
|
||||
ci->floors=oggpack_read(opb,6)+1;
|
||||
if(ci->floors<=0)goto err_out;
|
||||
for(i=0;i<ci->floors;i++){
|
||||
ci->floor_type[i]=oggpack_read(opb,16);
|
||||
if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
|
||||
ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
|
||||
if(!ci->floor_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* residue backend settings */
|
||||
ci->residues=oggpack_read(opb,6)+1;
|
||||
if(ci->residues<=0)goto err_out;
|
||||
for(i=0;i<ci->residues;i++){
|
||||
ci->residue_type[i]=oggpack_read(opb,16);
|
||||
if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
|
||||
ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
|
||||
if(!ci->residue_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* map backend settings */
|
||||
ci->maps=oggpack_read(opb,6)+1;
|
||||
if(ci->maps<=0)goto err_out;
|
||||
for(i=0;i<ci->maps;i++){
|
||||
ci->map_type[i]=oggpack_read(opb,16);
|
||||
if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
|
||||
ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
|
||||
if(!ci->map_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* mode settings */
|
||||
ci->modes=oggpack_read(opb,6)+1;
|
||||
if(ci->modes<=0)goto err_out;
|
||||
for(i=0;i<ci->modes;i++){
|
||||
ci->mode_param[i]=(vorbis_info_mode*)_ogg_calloc(1,sizeof(*ci->mode_param[i]));
|
||||
ci->mode_param[i]->blockflag=oggpack_read(opb,1);
|
||||
ci->mode_param[i]->windowtype=oggpack_read(opb,16);
|
||||
ci->mode_param[i]->transformtype=oggpack_read(opb,16);
|
||||
ci->mode_param[i]->mapping=oggpack_read(opb,8);
|
||||
|
||||
if(ci->mode_param[i]->windowtype>=VI_WINDOWB)goto err_out;
|
||||
if(ci->mode_param[i]->transformtype>=VI_WINDOWB)goto err_out;
|
||||
if(ci->mode_param[i]->mapping>=ci->maps)goto err_out;
|
||||
if(ci->mode_param[i]->mapping<0)goto err_out;
|
||||
}
|
||||
|
||||
if(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_info_clear(vi);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
/* Is this packet a vorbis ID header? */
|
||||
int vorbis_synthesis_idheader(ogg_packet *op){
|
||||
oggpack_buffer opb;
|
||||
char buffer[6];
|
||||
|
||||
if(op){
|
||||
oggpack_readinit(&opb,op->packet,op->bytes);
|
||||
|
||||
if(!op->b_o_s)
|
||||
return(0); /* Not the initial packet */
|
||||
|
||||
if(oggpack_read(&opb,8) != 1)
|
||||
return 0; /* not an ID header */
|
||||
|
||||
memset(buffer,0,6);
|
||||
_v_readstring(&opb,buffer,6);
|
||||
if(memcmp(buffer,"vorbis",6))
|
||||
return 0; /* not vorbis */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The Vorbis header is in three packets; the initial small packet in
|
||||
the first page that identifies basic parameters, a second packet
|
||||
with bitstream comments and a third packet that holds the
|
||||
codebook. */
|
||||
|
||||
int vorbis_synthesis_headerin(vorbis_info *vi,vorbis_comment *vc,ogg_packet *op){
|
||||
oggpack_buffer opb;
|
||||
|
||||
if(op){
|
||||
oggpack_readinit(&opb,op->packet,op->bytes);
|
||||
|
||||
/* Which of the three types of header is this? */
|
||||
/* Also verify header-ness, vorbis */
|
||||
{
|
||||
char buffer[6];
|
||||
int packtype=oggpack_read(&opb,8);
|
||||
memset(buffer,0,6);
|
||||
_v_readstring(&opb,buffer,6);
|
||||
if(memcmp(buffer,"vorbis",6)){
|
||||
/* not a vorbis header */
|
||||
return(OV_ENOTVORBIS);
|
||||
}
|
||||
switch(packtype){
|
||||
case 0x01: /* least significant *bit* is read first */
|
||||
if(!op->b_o_s){
|
||||
/* Not the initial packet */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
if(vi->rate!=0){
|
||||
/* previously initialized info header */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
return(_vorbis_unpack_info(vi,&opb));
|
||||
|
||||
case 0x03: /* least significant *bit* is read first */
|
||||
if(vi->rate==0){
|
||||
/* um... we didn't get the initial header */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
if(vc->vendor!=NULL){
|
||||
/* previously initialized comment header */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
return(_vorbis_unpack_comment(vc,&opb));
|
||||
|
||||
case 0x05: /* least significant *bit* is read first */
|
||||
if(vi->rate==0 || vc->vendor==NULL){
|
||||
/* um... we didn;t get the initial header or comments yet */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
if(vi->codec_setup==NULL){
|
||||
/* improperly initialized vorbis_info */
|
||||
return(OV_EFAULT);
|
||||
}
|
||||
if(((codec_setup_info *)vi->codec_setup)->books>0){
|
||||
/* previously initialized setup header */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
return(_vorbis_unpack_books(vi,&opb));
|
||||
|
||||
default:
|
||||
/* Not a valid vorbis header type */
|
||||
return(OV_EBADHEADER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
/* pack side **********************************************************/
|
||||
|
||||
static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
if(!ci||
|
||||
ci->blocksizes[0]<64||
|
||||
ci->blocksizes[1]<ci->blocksizes[0]){
|
||||
return(OV_EFAULT);
|
||||
}
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(opb,0x01,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* basic information about the stream */
|
||||
oggpack_write(opb,0x00,32);
|
||||
oggpack_write(opb,vi->channels,8);
|
||||
oggpack_write(opb,vi->rate,32);
|
||||
|
||||
oggpack_write(opb,vi->bitrate_upper,32);
|
||||
oggpack_write(opb,vi->bitrate_nominal,32);
|
||||
oggpack_write(opb,vi->bitrate_lower,32);
|
||||
|
||||
oggpack_write(opb,ov_ilog(ci->blocksizes[0]-1),4);
|
||||
oggpack_write(opb,ov_ilog(ci->blocksizes[1]-1),4);
|
||||
oggpack_write(opb,1,1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
|
||||
int bytes = strlen(ENCODE_VENDOR_STRING);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(opb,0x03,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* vendor */
|
||||
oggpack_write(opb,bytes,32);
|
||||
_v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
|
||||
|
||||
/* comments */
|
||||
|
||||
oggpack_write(opb,vc->comments,32);
|
||||
if(vc->comments){
|
||||
int i;
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(vc->user_comments[i]){
|
||||
oggpack_write(opb,vc->comment_lengths[i],32);
|
||||
_v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
|
||||
}else{
|
||||
oggpack_write(opb,0,32);
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write(opb,1,1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
int i;
|
||||
if(!ci)return(OV_EFAULT);
|
||||
|
||||
oggpack_write(opb,0x05,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* books */
|
||||
oggpack_write(opb,ci->books-1,8);
|
||||
for(i=0;i<ci->books;i++)
|
||||
if(vorbis_staticbook_pack(ci->book_param[i],opb))goto err_out;
|
||||
|
||||
/* times; hook placeholders */
|
||||
oggpack_write(opb,0,6);
|
||||
oggpack_write(opb,0,16);
|
||||
|
||||
/* floors */
|
||||
oggpack_write(opb,ci->floors-1,6);
|
||||
for(i=0;i<ci->floors;i++){
|
||||
oggpack_write(opb,ci->floor_type[i],16);
|
||||
if(_floor_P[ci->floor_type[i]]->pack)
|
||||
_floor_P[ci->floor_type[i]]->pack(ci->floor_param[i],opb);
|
||||
else
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* residues */
|
||||
oggpack_write(opb,ci->residues-1,6);
|
||||
for(i=0;i<ci->residues;i++){
|
||||
oggpack_write(opb,ci->residue_type[i],16);
|
||||
_residue_P[ci->residue_type[i]]->pack(ci->residue_param[i],opb);
|
||||
}
|
||||
|
||||
/* maps */
|
||||
oggpack_write(opb,ci->maps-1,6);
|
||||
for(i=0;i<ci->maps;i++){
|
||||
oggpack_write(opb,ci->map_type[i],16);
|
||||
_mapping_P[ci->map_type[i]]->pack(vi,ci->map_param[i],opb);
|
||||
}
|
||||
|
||||
/* modes */
|
||||
oggpack_write(opb,ci->modes-1,6);
|
||||
for(i=0;i<ci->modes;i++){
|
||||
oggpack_write(opb,ci->mode_param[i]->blockflag,1);
|
||||
oggpack_write(opb,ci->mode_param[i]->windowtype,16);
|
||||
oggpack_write(opb,ci->mode_param[i]->transformtype,16);
|
||||
oggpack_write(opb,ci->mode_param[i]->mapping,8);
|
||||
}
|
||||
oggpack_write(opb,1,1);
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int vorbis_commentheader_out(vorbis_comment *vc,
|
||||
ogg_packet *op){
|
||||
|
||||
oggpack_buffer opb;
|
||||
|
||||
oggpack_writeinit(&opb);
|
||||
if(_vorbis_pack_comment(&opb,vc)){
|
||||
oggpack_writeclear(&opb);
|
||||
return OV_EIMPL;
|
||||
}
|
||||
|
||||
op->packet = (unsigned char*)_ogg_malloc(oggpack_bytes(&opb));
|
||||
memcpy(op->packet, opb.buffer, oggpack_bytes(&opb));
|
||||
|
||||
op->bytes=oggpack_bytes(&opb);
|
||||
op->b_o_s=0;
|
||||
op->e_o_s=0;
|
||||
op->granulepos=0;
|
||||
op->packetno=1;
|
||||
|
||||
oggpack_writeclear(&opb);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int vorbis_analysis_headerout(vorbis_dsp_state *v,
|
||||
vorbis_comment *vc,
|
||||
ogg_packet *op,
|
||||
ogg_packet *op_comm,
|
||||
ogg_packet *op_code){
|
||||
int ret=OV_EIMPL;
|
||||
vorbis_info *vi=v->vi;
|
||||
oggpack_buffer opb;
|
||||
private_state *b=(private_state*)v->backend_state;
|
||||
|
||||
if(!b||vi->channels<=0||vi->channels>256){
|
||||
b = NULL;
|
||||
ret=OV_EFAULT;
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
/* first header packet **********************************************/
|
||||
|
||||
oggpack_writeinit(&opb);
|
||||
if(_vorbis_pack_info(&opb,vi))goto err_out;
|
||||
|
||||
/* build the packet */
|
||||
if(b->header)_ogg_free(b->header);
|
||||
b->header=(unsigned char*) _ogg_malloc(oggpack_bytes(&opb));
|
||||
memcpy(b->header,opb.buffer,oggpack_bytes(&opb));
|
||||
op->packet=b->header;
|
||||
op->bytes=oggpack_bytes(&opb);
|
||||
op->b_o_s=1;
|
||||
op->e_o_s=0;
|
||||
op->granulepos=0;
|
||||
op->packetno=0;
|
||||
|
||||
/* second header packet (comments) **********************************/
|
||||
|
||||
oggpack_reset(&opb);
|
||||
if(_vorbis_pack_comment(&opb,vc))goto err_out;
|
||||
|
||||
if(b->header1)_ogg_free(b->header1);
|
||||
b->header1=(unsigned char*) _ogg_malloc(oggpack_bytes(&opb));
|
||||
memcpy(b->header1,opb.buffer,oggpack_bytes(&opb));
|
||||
op_comm->packet=b->header1;
|
||||
op_comm->bytes=oggpack_bytes(&opb);
|
||||
op_comm->b_o_s=0;
|
||||
op_comm->e_o_s=0;
|
||||
op_comm->granulepos=0;
|
||||
op_comm->packetno=1;
|
||||
|
||||
/* third header packet (modes/codebooks) ****************************/
|
||||
|
||||
oggpack_reset(&opb);
|
||||
if(_vorbis_pack_books(&opb,vi))goto err_out;
|
||||
|
||||
if(b->header2)_ogg_free(b->header2);
|
||||
b->header2=(unsigned char*) _ogg_malloc(oggpack_bytes(&opb));
|
||||
memcpy(b->header2,opb.buffer,oggpack_bytes(&opb));
|
||||
op_code->packet=b->header2;
|
||||
op_code->bytes=oggpack_bytes(&opb);
|
||||
op_code->b_o_s=0;
|
||||
op_code->e_o_s=0;
|
||||
op_code->granulepos=0;
|
||||
op_code->packetno=2;
|
||||
|
||||
oggpack_writeclear(&opb);
|
||||
return(0);
|
||||
err_out:
|
||||
memset(op,0,sizeof(*op));
|
||||
memset(op_comm,0,sizeof(*op_comm));
|
||||
memset(op_code,0,sizeof(*op_code));
|
||||
|
||||
if(b){
|
||||
if(vi->channels>0)oggpack_writeclear(&opb);
|
||||
if(b->header)_ogg_free(b->header);
|
||||
if(b->header1)_ogg_free(b->header1);
|
||||
if(b->header2)_ogg_free(b->header2);
|
||||
b->header=NULL;
|
||||
b->header1=NULL;
|
||||
b->header2=NULL;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
|
||||
if(granulepos == -1) return -1;
|
||||
|
||||
/* We're not guaranteed a 64 bit unsigned type everywhere, so we
|
||||
have to put the unsigned granpo in a signed type. */
|
||||
if(granulepos>=0){
|
||||
return((double)granulepos/v->vi->rate);
|
||||
}else{
|
||||
ogg_int64_t granuleoff=0xffffffff;
|
||||
granuleoff<<=31;
|
||||
granuleoff|=0x7ffffffff;
|
||||
return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate);
|
||||
}
|
||||
}
|
||||
|
||||
const char *vorbis_version_string(void){
|
||||
return GENERAL_VENDOR_STRING;
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include "lookup.h"
|
||||
#include "lookup_data.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
float vorbis_coslook(float a){
|
||||
double d=a*(.31830989*(float)COS_LOOKUP_SZ);
|
||||
int i=vorbis_ftoi(d-.5);
|
||||
|
||||
return COS_LOOKUP[i]+ (d-i)*(COS_LOOKUP[i+1]-COS_LOOKUP[i]);
|
||||
}
|
||||
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
float vorbis_invsqlook(float a){
|
||||
double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
|
||||
int i=vorbis_ftoi(d-.5f);
|
||||
return INVSQ_LOOKUP[i]+ (d-i)*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]);
|
||||
}
|
||||
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
float vorbis_invsq2explook(int a){
|
||||
return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN];
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
float vorbis_fromdBlook(float a){
|
||||
int i=vorbis_ftoi(a*((float)(-(1<<FROMdB2_SHIFT)))-.5f);
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
|
||||
16.16 format
|
||||
|
||||
returns in m.8 format */
|
||||
long vorbis_invsqlook_i(long a,long e){
|
||||
long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
|
||||
long d=(a&INVSQ_LOOKUP_I_MASK)<<(16-INVSQ_LOOKUP_I_SHIFT); /* 0.16 */
|
||||
long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
|
||||
(((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */
|
||||
d)>>16); /* result 1.16 */
|
||||
|
||||
e+=32;
|
||||
if(e&1)val=(val*5792)>>13; /* multiply val by 1/sqrt(2) */
|
||||
e=(e>>1)-8;
|
||||
|
||||
return(val>>e);
|
||||
}
|
||||
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
/* a is in n.12 format */
|
||||
float vorbis_fromdBlook_i(long a){
|
||||
int i=(-a)>>(12-FROMdB2_SHIFT);
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
|
||||
long vorbis_coslook_i(long a){
|
||||
int i=a>>COS_LOOKUP_I_SHIFT;
|
||||
int d=a&COS_LOOKUP_I_MASK;
|
||||
return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
|
||||
COS_LOOKUP_I_SHIFT);
|
||||
}
|
||||
|
||||
#endif
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
extern float vorbis_coslook(float a);
|
||||
extern float vorbis_invsqlook(float a);
|
||||
extern float vorbis_invsq2explook(int a);
|
||||
extern float vorbis_fromdBlook(float a);
|
||||
#endif
|
||||
#ifdef INT_LOOKUP
|
||||
extern long vorbis_invsqlook_i(long a,long e);
|
||||
extern long vorbis_coslook_i(long a);
|
||||
extern float vorbis_fromdBlook_i(long a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+191
@@ -0,0 +1,191 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup data; generated by lookups.pl; edit there
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_DATA_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
#define COS_LOOKUP_SZ 128
|
||||
static const float COS_LOOKUP[COS_LOOKUP_SZ+1]={
|
||||
+1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f,
|
||||
+0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f,
|
||||
+0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f,
|
||||
+0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f,
|
||||
+0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f,
|
||||
+0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f,
|
||||
+0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f,
|
||||
+0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f,
|
||||
+0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f,
|
||||
+0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f,
|
||||
+0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f,
|
||||
+0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f,
|
||||
+0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f,
|
||||
+0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f,
|
||||
+0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f,
|
||||
+0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f,
|
||||
+0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f,
|
||||
-0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f,
|
||||
-0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f,
|
||||
-0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f,
|
||||
-0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f,
|
||||
-0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f,
|
||||
-0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f,
|
||||
-0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f,
|
||||
-0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f,
|
||||
-0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f,
|
||||
-0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f,
|
||||
-0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f,
|
||||
-0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f,
|
||||
-0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f,
|
||||
-0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f,
|
||||
-0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f,
|
||||
-1.0000000000000f,
|
||||
};
|
||||
|
||||
#define INVSQ_LOOKUP_SZ 32
|
||||
static const float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={
|
||||
1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f,
|
||||
1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f,
|
||||
1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f,
|
||||
1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f,
|
||||
1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f,
|
||||
1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f,
|
||||
1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f,
|
||||
1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f,
|
||||
1.000000000000f,
|
||||
};
|
||||
|
||||
#define INVSQ2EXP_LOOKUP_MIN (-32)
|
||||
#define INVSQ2EXP_LOOKUP_MAX 32
|
||||
static const float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\
|
||||
INVSQ2EXP_LOOKUP_MIN+1]={
|
||||
65536.f, 46340.95001f, 32768.f, 23170.47501f,
|
||||
16384.f, 11585.2375f, 8192.f, 5792.618751f,
|
||||
4096.f, 2896.309376f, 2048.f, 1448.154688f,
|
||||
1024.f, 724.0773439f, 512.f, 362.038672f,
|
||||
256.f, 181.019336f, 128.f, 90.50966799f,
|
||||
64.f, 45.254834f, 32.f, 22.627417f,
|
||||
16.f, 11.3137085f, 8.f, 5.656854249f,
|
||||
4.f, 2.828427125f, 2.f, 1.414213562f,
|
||||
1.f, 0.7071067812f, 0.5f, 0.3535533906f,
|
||||
0.25f, 0.1767766953f, 0.125f, 0.08838834765f,
|
||||
0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f,
|
||||
0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f,
|
||||
0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f,
|
||||
0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f,
|
||||
0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f,
|
||||
6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f,
|
||||
1.525878906e-05f,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#define FROMdB_LOOKUP_SZ 35
|
||||
#define FROMdB2_LOOKUP_SZ 32
|
||||
#define FROMdB_SHIFT 5
|
||||
#define FROMdB2_SHIFT 3
|
||||
#define FROMdB2_MASK 31
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
static const float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={
|
||||
1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f,
|
||||
0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f,
|
||||
0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f,
|
||||
0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f,
|
||||
0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f,
|
||||
0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f,
|
||||
1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f,
|
||||
2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f,
|
||||
3.981071706e-07f,2.511886432e-07f,1.584893192e-07f,
|
||||
};
|
||||
|
||||
static const float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={
|
||||
0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f,
|
||||
0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f,
|
||||
0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f,
|
||||
0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f,
|
||||
0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f,
|
||||
0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f,
|
||||
0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f,
|
||||
0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f,
|
||||
};
|
||||
#endif
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
|
||||
#define INVSQ_LOOKUP_I_SHIFT 10
|
||||
#define INVSQ_LOOKUP_I_MASK 1023
|
||||
static const long INVSQ_LOOKUP_I[64+1]={
|
||||
92682l, 91966l, 91267l, 90583l,
|
||||
89915l, 89261l, 88621l, 87995l,
|
||||
87381l, 86781l, 86192l, 85616l,
|
||||
85051l, 84497l, 83953l, 83420l,
|
||||
82897l, 82384l, 81880l, 81385l,
|
||||
80899l, 80422l, 79953l, 79492l,
|
||||
79039l, 78594l, 78156l, 77726l,
|
||||
77302l, 76885l, 76475l, 76072l,
|
||||
75674l, 75283l, 74898l, 74519l,
|
||||
74146l, 73778l, 73415l, 73058l,
|
||||
72706l, 72359l, 72016l, 71679l,
|
||||
71347l, 71019l, 70695l, 70376l,
|
||||
70061l, 69750l, 69444l, 69141l,
|
||||
68842l, 68548l, 68256l, 67969l,
|
||||
67685l, 67405l, 67128l, 66855l,
|
||||
66585l, 66318l, 66054l, 65794l,
|
||||
65536l,
|
||||
};
|
||||
|
||||
#define COS_LOOKUP_I_SHIFT 9
|
||||
#define COS_LOOKUP_I_MASK 511
|
||||
#define COS_LOOKUP_I_SZ 128
|
||||
static const long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={
|
||||
16384l, 16379l, 16364l, 16340l,
|
||||
16305l, 16261l, 16207l, 16143l,
|
||||
16069l, 15986l, 15893l, 15791l,
|
||||
15679l, 15557l, 15426l, 15286l,
|
||||
15137l, 14978l, 14811l, 14635l,
|
||||
14449l, 14256l, 14053l, 13842l,
|
||||
13623l, 13395l, 13160l, 12916l,
|
||||
12665l, 12406l, 12140l, 11866l,
|
||||
11585l, 11297l, 11003l, 10702l,
|
||||
10394l, 10080l, 9760l, 9434l,
|
||||
9102l, 8765l, 8423l, 8076l,
|
||||
7723l, 7366l, 7005l, 6639l,
|
||||
6270l, 5897l, 5520l, 5139l,
|
||||
4756l, 4370l, 3981l, 3590l,
|
||||
3196l, 2801l, 2404l, 2006l,
|
||||
1606l, 1205l, 804l, 402l,
|
||||
0l, -401l, -803l, -1204l,
|
||||
-1605l, -2005l, -2403l, -2800l,
|
||||
-3195l, -3589l, -3980l, -4369l,
|
||||
-4755l, -5138l, -5519l, -5896l,
|
||||
-6269l, -6638l, -7004l, -7365l,
|
||||
-7722l, -8075l, -8422l, -8764l,
|
||||
-9101l, -9433l, -9759l, -10079l,
|
||||
-10393l, -10701l, -11002l, -11296l,
|
||||
-11584l, -11865l, -12139l, -12405l,
|
||||
-12664l, -12915l, -13159l, -13394l,
|
||||
-13622l, -13841l, -14052l, -14255l,
|
||||
-14448l, -14634l, -14810l, -14977l,
|
||||
-15136l, -15285l, -15425l, -15556l,
|
||||
-15678l, -15790l, -15892l, -15985l,
|
||||
-16068l, -16142l, -16206l, -16260l,
|
||||
-16304l, -16339l, -16363l, -16378l,
|
||||
-16383l,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+159
@@ -0,0 +1,159 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Some of these routines (autocorrelator, LPC coefficient estimator)
|
||||
are derived from code written by Jutta Degener and Carsten Bormann;
|
||||
thus we include their copyright below. The entirety of this file
|
||||
is freely redistributable on the condition that both of these
|
||||
copyright notices are preserved without modification. */
|
||||
|
||||
/* Preserved Copyright: *********************************************/
|
||||
|
||||
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universita"t Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universita"t
|
||||
Berlin are deemed to have made any representations as to the
|
||||
suitability of this software for any purpose nor are held responsible
|
||||
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
|
||||
THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "os.h"
|
||||
#include "smallft.h"
|
||||
#include "lpc.h"
|
||||
#include "scales.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* Autocorrelation LPC coeff generation algorithm invented by
|
||||
N. Levinson in 1947, modified by J. Durbin in 1959. */
|
||||
|
||||
/* Input : n elements of time doamin data
|
||||
Output: m lpc coefficients, excitation energy */
|
||||
|
||||
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
|
||||
double *aut=(double*)alloca(sizeof(*aut)*(m+1));
|
||||
double *lpc=(double*)alloca(sizeof(*lpc)*(m));
|
||||
double error;
|
||||
double epsilon;
|
||||
int i,j;
|
||||
|
||||
/* autocorrelation, p+1 lag coefficients */
|
||||
j=m+1;
|
||||
while(j--){
|
||||
double d=0; /* double needed for accumulator depth */
|
||||
for(i=j;i<n;i++)d+=(double)data[i]*data[i-j];
|
||||
aut[j]=d;
|
||||
}
|
||||
|
||||
/* Generate lpc coefficients from autocorr values */
|
||||
|
||||
/* set our noise floor to about -100dB */
|
||||
error=aut[0] * (1. + 1e-10);
|
||||
epsilon=1e-9*aut[0]+1e-10;
|
||||
|
||||
for(i=0;i<m;i++){
|
||||
double r= -aut[i+1];
|
||||
|
||||
if(error<epsilon){
|
||||
memset(lpc+i,0,(m-i)*sizeof(*lpc));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Sum up this iteration's reflection coefficient; note that in
|
||||
Vorbis we don't save it. If anyone wants to recycle this code
|
||||
and needs reflection coefficients, save the results of 'r' from
|
||||
each iteration. */
|
||||
|
||||
for(j=0;j<i;j++)r-=lpc[j]*aut[i-j];
|
||||
r/=error;
|
||||
|
||||
/* Update LPC coefficients and total error */
|
||||
|
||||
lpc[i]=r;
|
||||
for(j=0;j<i/2;j++){
|
||||
double tmp=lpc[j];
|
||||
|
||||
lpc[j]+=r*lpc[i-1-j];
|
||||
lpc[i-1-j]+=r*tmp;
|
||||
}
|
||||
if(i&1)lpc[j]+=lpc[j]*r;
|
||||
|
||||
error*=1.-r*r;
|
||||
|
||||
}
|
||||
|
||||
done:
|
||||
|
||||
/* slightly damp the filter */
|
||||
{
|
||||
double g = .99;
|
||||
double damp = g;
|
||||
for(j=0;j<m;j++){
|
||||
lpc[j]*=damp;
|
||||
damp*=g;
|
||||
}
|
||||
}
|
||||
|
||||
for(j=0;j<m;j++)lpci[j]=(float)lpc[j];
|
||||
|
||||
/* we need the error value to know how big an impulse to hit the
|
||||
filter with later */
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||
float *data,long n){
|
||||
|
||||
/* in: coeff[0...m-1] LPC coefficients
|
||||
prime[0...m-1] initial values (allocated size of n+m-1)
|
||||
out: data[0...n-1] data samples */
|
||||
|
||||
long i,j,o,p;
|
||||
float y;
|
||||
float *work=(float*)alloca(sizeof(*work)*(m+n));
|
||||
|
||||
if(!prime)
|
||||
for(i=0;i<m;i++)
|
||||
work[i]=0.f;
|
||||
else
|
||||
for(i=0;i<m;i++)
|
||||
work[i]=prime[i];
|
||||
|
||||
for(i=0;i<n;i++){
|
||||
y=0;
|
||||
o=i;
|
||||
p=m;
|
||||
for(j=0;j<m;j++)
|
||||
y-=work[o++]*coeff[--p];
|
||||
|
||||
data[i]=work[o]=y;
|
||||
}
|
||||
}
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LPC_H_
|
||||
#define _V_LPC_H_
|
||||
|
||||
#include "../../codec.h"
|
||||
|
||||
/* simple linear scale LPC code */
|
||||
extern float vorbis_lpc_from_data(float *data,float *lpc,int n,int m);
|
||||
|
||||
extern void vorbis_lpc_predict(float *coeff,float *prime,int m,
|
||||
float *data,long n);
|
||||
|
||||
#endif
|
||||
+454
@@ -0,0 +1,454 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation https://xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LSP (also called LSF) conversion routines
|
||||
|
||||
The LSP generation code is taken (with minimal modification and a
|
||||
few bugfixes) from "On the Computation of the LSP Frequencies" by
|
||||
Joseph Rothweiler (see http://www.rothweiler.us for contact info).
|
||||
|
||||
The paper is available at:
|
||||
|
||||
https://web.archive.org/web/20110810174000/http://home.myfairpoint.net/vzenxj75/myown1/joe/lsf/index.html
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Note that the lpc-lsp conversion finds the roots of polynomial with
|
||||
an iterative root polisher (CACM algorithm 283). It *is* possible
|
||||
to confuse this algorithm into not converging; that should only
|
||||
happen with absurdly closely spaced roots (very sharp peaks in the
|
||||
LPC f response) which in turn should be impossible in our use of
|
||||
the code. If this *does* happen anyway, it's a bug in the floor
|
||||
finder; find the cause of the confusion (probably a single bin
|
||||
spike or accidental near-float-limit resolution problems) and
|
||||
correct it. */
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lsp.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
#include "lookup.h"
|
||||
#include "scales.h"
|
||||
|
||||
/* three possible LSP to f curve functions; the exact computation
|
||||
(float), a lookup based float implementation, and an integer
|
||||
implementation. The float lookup is likely the optimal choice on
|
||||
any machine with an FPU. The integer implementation is *not* fixed
|
||||
point (due to the need for a large dynamic range and thus a
|
||||
separately tracked exponent) and thus much more complex than the
|
||||
relatively simple float implementations. It's mostly for future
|
||||
work on a fully fixed point implementation for processors like the
|
||||
ARM family. */
|
||||
|
||||
/* define either of these (preferably FLOAT_LOOKUP) to have faster
|
||||
but less precise implementation. */
|
||||
#undef FLOAT_LOOKUP
|
||||
#undef INT_LOOKUP
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
#include "lookup.c" /* catch this in the build system; we #include for
|
||||
compilers (like gcc) that can't inline across
|
||||
modules */
|
||||
|
||||
/* side effect: changes *lsp to cosines of lsp */
|
||||
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
|
||||
float amp,float ampoffset){
|
||||
int i;
|
||||
float wdel=M_PI/ln;
|
||||
vorbis_fpu_control fpu;
|
||||
|
||||
vorbis_fpu_setround(&fpu);
|
||||
for(i=0;i<m;i++)lsp[i]=vorbis_coslook(lsp[i]);
|
||||
|
||||
i=0;
|
||||
while(i<n){
|
||||
int k=map[i];
|
||||
int qexp;
|
||||
float p=.7071067812f;
|
||||
float q=.7071067812f;
|
||||
float w=vorbis_coslook(wdel*k);
|
||||
float *ftmp=lsp;
|
||||
int c=m>>1;
|
||||
|
||||
while(c--){
|
||||
q*=ftmp[0]-w;
|
||||
p*=ftmp[1]-w;
|
||||
ftmp+=2;
|
||||
}
|
||||
|
||||
if(m&1){
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
q*=ftmp[0]-w;
|
||||
q*=q;
|
||||
p*=p*(1.f-w*w);
|
||||
}else{
|
||||
/* even order filter; still symmetric */
|
||||
q*=q*(1.f+w);
|
||||
p*=p*(1.f-w);
|
||||
}
|
||||
|
||||
q=frexp(p+q,&qexp);
|
||||
q=vorbis_fromdBlook(amp*
|
||||
vorbis_invsqlook(q)*
|
||||
vorbis_invsq2explook(qexp+m)-
|
||||
ampoffset);
|
||||
|
||||
do{
|
||||
curve[i++]*=q;
|
||||
}while(map[i]==k);
|
||||
}
|
||||
vorbis_fpu_restore(fpu);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
#include "lookup.c" /* catch this in the build system; we #include for
|
||||
compilers (like gcc) that can't inline across
|
||||
modules */
|
||||
|
||||
static const int MLOOP_1[64]={
|
||||
0,10,11,11, 12,12,12,12, 13,13,13,13, 13,13,13,13,
|
||||
14,14,14,14, 14,14,14,14, 14,14,14,14, 14,14,14,14,
|
||||
15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
|
||||
15,15,15,15, 15,15,15,15, 15,15,15,15, 15,15,15,15,
|
||||
};
|
||||
|
||||
static const int MLOOP_2[64]={
|
||||
0,4,5,5, 6,6,6,6, 7,7,7,7, 7,7,7,7,
|
||||
8,8,8,8, 8,8,8,8, 8,8,8,8, 8,8,8,8,
|
||||
9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
|
||||
9,9,9,9, 9,9,9,9, 9,9,9,9, 9,9,9,9,
|
||||
};
|
||||
|
||||
static const int MLOOP_3[8]={0,1,2,2,3,3,3,3};
|
||||
|
||||
|
||||
/* side effect: changes *lsp to cosines of lsp */
|
||||
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
|
||||
float amp,float ampoffset){
|
||||
|
||||
/* 0 <= m < 256 */
|
||||
|
||||
/* set up for using all int later */
|
||||
int i;
|
||||
int ampoffseti=rint(ampoffset*4096.f);
|
||||
int ampi=rint(amp*16.f);
|
||||
long *ilsp=(long*)alloca(m*sizeof(*ilsp));
|
||||
for(i=0;i<m;i++)ilsp[i]=vorbis_coslook_i(lsp[i]/M_PI*65536.f+.5f);
|
||||
|
||||
i=0;
|
||||
while(i<n){
|
||||
int j,k=map[i];
|
||||
unsigned long pi=46341; /* 2**-.5 in 0.16 */
|
||||
unsigned long qi=46341;
|
||||
int qexp=0,shift;
|
||||
long wi=vorbis_coslook_i(k*65536/ln);
|
||||
|
||||
qi*=labs(ilsp[0]-wi);
|
||||
pi*=labs(ilsp[1]-wi);
|
||||
|
||||
for(j=3;j<m;j+=2){
|
||||
if(!(shift=MLOOP_1[(pi|qi)>>25]))
|
||||
if(!(shift=MLOOP_2[(pi|qi)>>19]))
|
||||
shift=MLOOP_3[(pi|qi)>>16];
|
||||
qi=(qi>>shift)*labs(ilsp[j-1]-wi);
|
||||
pi=(pi>>shift)*labs(ilsp[j]-wi);
|
||||
qexp+=shift;
|
||||
}
|
||||
if(!(shift=MLOOP_1[(pi|qi)>>25]))
|
||||
if(!(shift=MLOOP_2[(pi|qi)>>19]))
|
||||
shift=MLOOP_3[(pi|qi)>>16];
|
||||
|
||||
/* pi,qi normalized collectively, both tracked using qexp */
|
||||
|
||||
if(m&1){
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
qi=(qi>>shift)*labs(ilsp[j-1]-wi);
|
||||
pi=(pi>>shift)<<14;
|
||||
qexp+=shift;
|
||||
|
||||
if(!(shift=MLOOP_1[(pi|qi)>>25]))
|
||||
if(!(shift=MLOOP_2[(pi|qi)>>19]))
|
||||
shift=MLOOP_3[(pi|qi)>>16];
|
||||
|
||||
pi>>=shift;
|
||||
qi>>=shift;
|
||||
qexp+=shift-14*((m+1)>>1);
|
||||
|
||||
pi=((pi*pi)>>16);
|
||||
qi=((qi*qi)>>16);
|
||||
qexp=qexp*2+m;
|
||||
|
||||
pi*=(1<<14)-((wi*wi)>>14);
|
||||
qi+=pi>>14;
|
||||
|
||||
}else{
|
||||
/* even order filter; still symmetric */
|
||||
|
||||
/* p*=p(1-w), q*=q(1+w), let normalization drift because it isn't
|
||||
worth tracking step by step */
|
||||
|
||||
pi>>=shift;
|
||||
qi>>=shift;
|
||||
qexp+=shift-7*m;
|
||||
|
||||
pi=((pi*pi)>>16);
|
||||
qi=((qi*qi)>>16);
|
||||
qexp=qexp*2+m;
|
||||
|
||||
pi*=(1<<14)-wi;
|
||||
qi*=(1<<14)+wi;
|
||||
qi=(qi+pi)>>14;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* we've let the normalization drift because it wasn't important;
|
||||
however, for the lookup, things must be normalized again. We
|
||||
need at most one right shift or a number of left shifts */
|
||||
|
||||
if(qi&0xffff0000){ /* checks for 1.xxxxxxxxxxxxxxxx */
|
||||
qi>>=1; qexp++;
|
||||
}else
|
||||
while(qi && !(qi&0x8000)){ /* checks for 0.0xxxxxxxxxxxxxxx or less*/
|
||||
qi<<=1; qexp--;
|
||||
}
|
||||
|
||||
amp=vorbis_fromdBlook_i(ampi* /* n.4 */
|
||||
vorbis_invsqlook_i(qi,qexp)-
|
||||
/* m.8, m+n<=8 */
|
||||
ampoffseti); /* 8.12[0] */
|
||||
|
||||
curve[i]*=amp;
|
||||
while(map[++i]==k)curve[i]*=amp;
|
||||
}
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* old, nonoptimized but simple version for any poor sap who needs to
|
||||
figure out what the hell this code does, or wants the other
|
||||
fraction of a dB precision */
|
||||
|
||||
/* side effect: changes *lsp to cosines of lsp */
|
||||
void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,float *lsp,int m,
|
||||
float amp,float ampoffset){
|
||||
int i;
|
||||
float wdel=M_PI/ln;
|
||||
for(i=0;i<m;i++)lsp[i]=2.f*cos(lsp[i]);
|
||||
|
||||
i=0;
|
||||
while(i<n){
|
||||
int j,k=map[i];
|
||||
float p=.5f;
|
||||
float q=.5f;
|
||||
float w=2.f*cos(wdel*k);
|
||||
for(j=1;j<m;j+=2){
|
||||
q *= w-lsp[j-1];
|
||||
p *= w-lsp[j];
|
||||
}
|
||||
if(j==m){
|
||||
/* odd order filter; slightly assymetric */
|
||||
/* the last coefficient */
|
||||
q*=w-lsp[j-1];
|
||||
p*=p*(4.f-w*w);
|
||||
q*=q;
|
||||
}else{
|
||||
/* even order filter; still symmetric */
|
||||
p*=p*(2.f-w);
|
||||
q*=q*(2.f+w);
|
||||
}
|
||||
|
||||
q=fromdB(amp/sqrt(p+q)-ampoffset);
|
||||
|
||||
curve[i]*=q;
|
||||
while(map[++i]==k)curve[i]*=q;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static void cheby(float *g, int ord) {
|
||||
int i, j;
|
||||
|
||||
g[0] *= .5f;
|
||||
for(i=2; i<= ord; i++) {
|
||||
for(j=ord; j >= i; j--) {
|
||||
g[j-2] -= g[j];
|
||||
g[j] += g[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static int JUCE_CDECL comp(const void *a,const void *b){
|
||||
return (*(float *)a<*(float *)b)-(*(float *)a>*(float *)b);
|
||||
}
|
||||
|
||||
/* Newton-Raphson-Maehly actually functioned as a decent root finder,
|
||||
but there are root sets for which it gets into limit cycles
|
||||
(exacerbated by zero suppression) and fails. We can't afford to
|
||||
fail, even if the failure is 1 in 100,000,000, so we now use
|
||||
Laguerre and later polish with Newton-Raphson (which can then
|
||||
afford to fail) */
|
||||
|
||||
#define EPSILON 10e-7
|
||||
static int Laguerre_With_Deflation(float *a,int ord,float *r){
|
||||
int i,m;
|
||||
double *defl=(double*)alloca(sizeof(*defl)*(ord+1));
|
||||
for(i=0;i<=ord;i++)defl[i]=a[i];
|
||||
|
||||
for(m=ord;m>0;m--){
|
||||
double newx=0.f,delta;
|
||||
|
||||
/* iterate a root */
|
||||
while(1){
|
||||
double p=defl[m],pp=0.f,ppp=0.f,denom;
|
||||
|
||||
/* eval the polynomial and its first two derivatives */
|
||||
for(i=m;i>0;i--){
|
||||
ppp = newx*ppp + pp;
|
||||
pp = newx*pp + p;
|
||||
p = newx*p + defl[i-1];
|
||||
}
|
||||
|
||||
/* Laguerre's method */
|
||||
denom=(m-1) * ((m-1)*pp*pp - m*p*ppp);
|
||||
if(denom<0)
|
||||
return(-1); /* complex root! The LPC generator handed us a bad filter */
|
||||
|
||||
if(pp>0){
|
||||
denom = pp + sqrt(denom);
|
||||
if(denom<EPSILON)denom=EPSILON;
|
||||
}else{
|
||||
denom = pp - sqrt(denom);
|
||||
if(denom>-(EPSILON))denom=-(EPSILON);
|
||||
}
|
||||
|
||||
delta = m*p/denom;
|
||||
newx -= delta;
|
||||
|
||||
if(delta<0.f)delta*=-1;
|
||||
|
||||
if(fabs(delta/newx)<10e-12)break;
|
||||
}
|
||||
|
||||
r[m-1]=newx;
|
||||
|
||||
/* forward deflation */
|
||||
|
||||
for(i=m;i>0;i--)
|
||||
defl[i-1]+=newx*defl[i];
|
||||
defl++;
|
||||
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* for spit-and-polish only */
|
||||
static int Newton_Raphson(float *a,int ord,float *r){
|
||||
int i, k, count=0;
|
||||
double error=1.f;
|
||||
double *root=(double*)alloca(ord*sizeof(*root));
|
||||
|
||||
for(i=0; i<ord;i++) root[i] = r[i];
|
||||
|
||||
while(error>1e-20){
|
||||
error=0;
|
||||
|
||||
for(i=0; i<ord; i++) { /* Update each point. */
|
||||
double pp=0.,delta;
|
||||
double rooti=root[i];
|
||||
double p=a[ord];
|
||||
for(k=ord-1; k>= 0; k--) {
|
||||
|
||||
pp= pp* rooti + p;
|
||||
p = p * rooti + a[k];
|
||||
}
|
||||
|
||||
delta = p/pp;
|
||||
root[i] -= delta;
|
||||
error+= delta*delta;
|
||||
}
|
||||
|
||||
if(count>40)return(-1);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
/* Replaced the original bubble sort with a real sort. With your
|
||||
help, we can eliminate the bubble sort in our lifetime. --Monty */
|
||||
|
||||
for(i=0; i<ord;i++) r[i] = root[i];
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Convert lpc coefficients to lsp coefficients */
|
||||
int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m){
|
||||
int order2=(m+1)>>1;
|
||||
int g1_order,g2_order;
|
||||
float *g1=(float*)alloca(sizeof(*g1)*(order2+1));
|
||||
float *g2=(float*)alloca(sizeof(*g2)*(order2+1));
|
||||
float *g1r=(float*)alloca(sizeof(*g1r)*(order2+1));
|
||||
float *g2r=(float*)alloca(sizeof(*g2r)*(order2+1));
|
||||
int i;
|
||||
|
||||
/* even and odd are slightly different base cases */
|
||||
g1_order=(m+1)>>1;
|
||||
g2_order=(m) >>1;
|
||||
|
||||
/* Compute the lengths of the x polynomials. */
|
||||
/* Compute the first half of K & R F1 & F2 polynomials. */
|
||||
/* Compute half of the symmetric and antisymmetric polynomials. */
|
||||
/* Remove the roots at +1 and -1. */
|
||||
|
||||
g1[g1_order] = 1.f;
|
||||
for(i=1;i<=g1_order;i++) g1[g1_order-i] = lpc[i-1]+lpc[m-i];
|
||||
g2[g2_order] = 1.f;
|
||||
for(i=1;i<=g2_order;i++) g2[g2_order-i] = lpc[i-1]-lpc[m-i];
|
||||
|
||||
if(g1_order>g2_order){
|
||||
for(i=2; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+2];
|
||||
}else{
|
||||
for(i=1; i<=g1_order;i++) g1[g1_order-i] -= g1[g1_order-i+1];
|
||||
for(i=1; i<=g2_order;i++) g2[g2_order-i] += g2[g2_order-i+1];
|
||||
}
|
||||
|
||||
/* Convert into polynomials in cos(alpha) */
|
||||
cheby(g1,g1_order);
|
||||
cheby(g2,g2_order);
|
||||
|
||||
/* Find the roots of the 2 even polynomials.*/
|
||||
if(Laguerre_With_Deflation(g1,g1_order,g1r) ||
|
||||
Laguerre_With_Deflation(g2,g2_order,g2r))
|
||||
return(-1);
|
||||
|
||||
Newton_Raphson(g1,g1_order,g1r); /* if it fails, it leaves g1r alone */
|
||||
Newton_Raphson(g2,g2_order,g2r); /* if it fails, it leaves g2r alone */
|
||||
|
||||
qsort(g1r,g1_order,sizeof(*g1r),comp);
|
||||
qsort(g2r,g2_order,sizeof(*g2r),comp);
|
||||
|
||||
for(i=0;i<g1_order;i++)
|
||||
lsp[i*2] = acos(g1r[i]);
|
||||
|
||||
for(i=0;i<g2_order;i++)
|
||||
lsp[i*2+1] = acos(g2r[i]);
|
||||
return(0);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user