- port to minGw
git-svn-id: http://moon:8086/svn/software/trunk/projects/JaySynth@235 b431acfa-c32f-4a4a-93f1-934dc6c82436
This commit is contained in:
@@ -0,0 +1,49 @@
|
||||
|
||||
=====================================================================
|
||||
|
||||
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: flac.sourceforge.net
|
||||
|
||||
=====================================================================
|
||||
|
||||
Copyright (C) 2000,2001,2002,2003,2004,2005,2006 Josh Coalson
|
||||
|
||||
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,371 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
|
||||
#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="../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="../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="../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="../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 \c #defines in \c export.h of each
|
||||
* library's includes (e.g. \c include/FLAC/export.h). The
|
||||
* \c #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 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 unsigned.
|
||||
*/
|
||||
|
||||
/** \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 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,209 @@
|
||||
/* alloc - Convenience routines for safely allocating memory
|
||||
* Copyright (C) 2007-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
*/
|
||||
|
||||
#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 0xffffffffffffffffui64
|
||||
# else
|
||||
# define SIZE_T_MAX 0xffffffff
|
||||
# endif
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
# endif
|
||||
# define SIZE_MAX SIZE_T_MAX
|
||||
#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)
|
||||
{
|
||||
/* malloc(0) is undefined; FLAC src convention is to always allocate */
|
||||
if(!size)
|
||||
size++;
|
||||
return malloc(size);
|
||||
}
|
||||
|
||||
static inline void *safe_calloc_(size_t nmemb, size_t size)
|
||||
{
|
||||
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_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)
|
||||
return 0;
|
||||
size3 += size2;
|
||||
if(size3 < size2)
|
||||
return 0;
|
||||
return realloc(ptr, size3);
|
||||
}
|
||||
|
||||
static inline void *safe_realloc_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)
|
||||
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)
|
||||
return 0;
|
||||
return safe_realloc_mul_2op_(ptr, size1, size2);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,46 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 DEBUG
|
||||
#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
|
||||
@@ -0,0 +1,185 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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.
|
||||
*
|
||||
* \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 sorce is not seekable by setting the \a seek field to \c NULL.
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__IOCallback_Read read;
|
||||
FLAC__IOCallback_Write write;
|
||||
FLAC__IOCallback_Seek seek;
|
||||
FLAC__IOCallback_Tell tell;
|
||||
FLAC__IOCallback_Eof eof;
|
||||
FLAC__IOCallback_Close close;
|
||||
} FLAC__IOCallbacks;
|
||||
|
||||
/* \} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,200 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2012-2014 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 prefered 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
|
||||
|
||||
#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 */
|
||||
#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
|
||||
#endif
|
||||
|
||||
#if 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)
|
||||
#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 __BORLANDC__ || defined __MINGW32__
|
||||
#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 __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
|
||||
/* 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
|
||||
typedef unsigned __int64 uint64_t;
|
||||
typedef unsigned __int32 uint32_t;
|
||||
typedef unsigned __int16 uint16_t;
|
||||
typedef unsigned __int8 uint8_t;
|
||||
typedef __int64 int64_t;
|
||||
typedef __int32 int32_t;
|
||||
typedef __int16 int16_t;
|
||||
typedef __int8 int8_t;
|
||||
# define PRIu64 "I64u"
|
||||
# define PRId64 "I64d"
|
||||
# define PRIx64 "I64x"
|
||||
# endif
|
||||
#endif /* defined _MSC_VER */
|
||||
|
||||
#ifdef _WIN32
|
||||
/* All char* strings are in UTF-8 format. Added to support Unicode files on Windows */
|
||||
#include "win_utf8_io.h"
|
||||
|
||||
#define flac_printf printf_utf8
|
||||
#define flac_fprintf fprintf_utf8
|
||||
#define flac_vfprintf vfprintf_utf8
|
||||
#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_utime utime
|
||||
#define flac_unlink unlink
|
||||
#define flac_rename rename
|
||||
#define flac_stat stat
|
||||
|
||||
#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
|
||||
|
||||
#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 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,78 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2012-2014 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". */
|
||||
|
||||
#if HAVE_BSWAP32 /* GCC and Clang */
|
||||
|
||||
/* GCC prior to 4.8 didn't provide bswap16 on x86_64 */
|
||||
#if ! 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))
|
||||
|
||||
#elif defined _MSC_VER /* Windows. Apparently in <stdlib.h>. */
|
||||
|
||||
#define ENDSWAP_16(x) (_byteswap_ushort (x))
|
||||
#define ENDSWAP_32(x) (_byteswap_ulong (x))
|
||||
|
||||
#elif defined HAVE_BYTESWAP_H /* Linux */
|
||||
|
||||
#include <byteswap.h>
|
||||
|
||||
#define ENDSWAP_16(x) (bswap_16 (x))
|
||||
#define ENDSWAP_32(x) (bswap_32 (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))
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
/* Host to little-endian byte swapping. */
|
||||
#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,97 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 with MSVC 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.
|
||||
*
|
||||
* \{
|
||||
*/
|
||||
|
||||
#if defined(FLAC__NO_DLL)
|
||||
#define FLAC_API
|
||||
|
||||
#elif defined(_MSC_VER)
|
||||
#ifdef FLAC_API_EXPORTS
|
||||
#define FLAC_API __declspec(dllexport)
|
||||
#else
|
||||
#define FLAC_API __declspec(dllimport)
|
||||
#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 11
|
||||
#define FLAC_API_VERSION_REVISION 0 /**< see above */
|
||||
#define FLAC_API_VERSION_AGE 3 /**< 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,109 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
*/
|
||||
unsigned FLAC__bitmath_silog2(int v)
|
||||
{
|
||||
while(1) {
|
||||
if(v == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if(v > 0) {
|
||||
unsigned l = 0;
|
||||
while(v) {
|
||||
l++;
|
||||
v >>= 1;
|
||||
}
|
||||
return l+1;
|
||||
}
|
||||
else if(v == -1) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
v++;
|
||||
v = -v;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v)
|
||||
{
|
||||
while(1) {
|
||||
if(v == 0) {
|
||||
return 0;
|
||||
}
|
||||
else if(v > 0) {
|
||||
unsigned l = 0;
|
||||
while(v) {
|
||||
l++;
|
||||
v >>= 1;
|
||||
}
|
||||
return l+1;
|
||||
}
|
||||
else if(v == -1) {
|
||||
return 2;
|
||||
}
|
||||
else {
|
||||
v++;
|
||||
v = -v;
|
||||
}
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,842 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 "../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 uint32_t is >= 32 bits wide */
|
||||
#define FLAC__BYTES_PER_WORD 4
|
||||
#define FLAC__BITS_PER_WORD (8 * FLAC__BYTES_PER_WORD)
|
||||
#define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff)
|
||||
/* SWAP_BE_WORD_TO_HOST swaps bytes in a uint32_t (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
|
||||
|
||||
/*
|
||||
* 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 unsigned FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(uint32_t); /* size in words */
|
||||
/* When growing, increment 4K at a time */
|
||||
static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(uint32_t); /* 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 {
|
||||
uint32_t *buffer;
|
||||
uint32_t accum; /* accumulator; bits are right-justified; when full, accum is appended to buffer */
|
||||
unsigned capacity; /* capacity of buffer in words */
|
||||
unsigned words; /* # of complete words in buffer */
|
||||
unsigned 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, unsigned bits_to_add)
|
||||
{
|
||||
unsigned new_capacity;
|
||||
uint32_t *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;
|
||||
|
||||
/* 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 = (uint32_t*) safe_realloc_mul_2op_(bw->buffer, sizeof(uint32_t), /*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 = (uint32_t*) malloc(sizeof(uint32_t) * 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;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out)
|
||||
{
|
||||
unsigned i, j;
|
||||
if(bw == 0) {
|
||||
fprintf(out, "bitwriter is NULL\n");
|
||||
}
|
||||
else {
|
||||
fprintf(out, "bitwriter: capacity=%u words=%u bits=%u total_bits=%u\n", bw->capacity, bw->words, bw->bits, FLAC__TOTAL_BITS(bw));
|
||||
|
||||
for(i = 0; i < bw->words; i++) {
|
||||
fprintf(out, "%08X: ", i);
|
||||
for(j = 0; j < FLAC__BITS_PER_WORD; j++)
|
||||
fprintf(out, "%01u", bw->buffer[i] & (1 << (FLAC__BITS_PER_WORD-j-1)) ? 1:0);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
if(bw->bits > 0) {
|
||||
fprintf(out, "%08X: ", i);
|
||||
for(j = 0; j < bw->bits; j++)
|
||||
fprintf(out, "%01u", bw->accum & (1 << (bw->bits-j-1)) ? 1:0);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
unsigned 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, unsigned bits)
|
||||
{
|
||||
unsigned 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;
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits)
|
||||
{
|
||||
register unsigned 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);
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
FLAC__ASSERT(bits <= 32);
|
||||
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;
|
||||
|
||||
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;
|
||||
}
|
||||
else {
|
||||
bw->accum = val;
|
||||
bw->bits = 0;
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(val);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits)
|
||||
{
|
||||
/* zero-out unused bits */
|
||||
if(bits < 32)
|
||||
val &= (~(0xffffffff << bits));
|
||||
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, bits);
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned 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(bw, (FLAC__uint32)val, 32);
|
||||
}
|
||||
else
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 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(bw, val & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>8) & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, (val>>16) & 0xff, 8))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, val>>24, 8))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
inline FLAC__bool FLAC__bitwriter_write_byte_block(FLAC__BitWriter *bw, const FLAC__byte vals[], unsigned nvals)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
/* 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(bw, (FLAC__uint32)(vals[i]), 8))
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, unsigned val)
|
||||
{
|
||||
if(val < 32)
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, 1, ++val);
|
||||
else
|
||||
return
|
||||
FLAC__bitwriter_write_zeroes(bw, val) &&
|
||||
FLAC__bitwriter_write_raw_uint32(bw, 1, 1);
|
||||
}
|
||||
|
||||
unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter)
|
||||
{
|
||||
FLAC__uint32 uval;
|
||||
|
||||
FLAC__ASSERT(parameter < sizeof(unsigned)*8);
|
||||
|
||||
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = (val<<1) ^ (val>>31);
|
||||
|
||||
return 1 + parameter + (uval >> parameter);
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter)
|
||||
{
|
||||
unsigned bits, msbs, uval;
|
||||
unsigned k;
|
||||
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
/* fold signed to unsigned */
|
||||
if(val < 0)
|
||||
uval = (unsigned)(((-(++val)) << 1) + 1);
|
||||
else
|
||||
uval = (unsigned)(val << 1);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
FLAC__ASSERT(k <= 30);
|
||||
|
||||
msbs = uval >> k;
|
||||
bits = 1 + k + msbs;
|
||||
}
|
||||
else {
|
||||
unsigned 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;
|
||||
}
|
||||
|
||||
unsigned FLAC__bitwriter_golomb_bits_unsigned(unsigned uval, unsigned parameter)
|
||||
{
|
||||
unsigned bits, msbs;
|
||||
unsigned 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 {
|
||||
unsigned 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;
|
||||
}
|
||||
#endif /* UNUSED */
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, unsigned parameter)
|
||||
{
|
||||
unsigned total_bits, interesting_bits, msbs;
|
||||
FLAC__uint32 uval, pattern;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter < 8*sizeof(uval));
|
||||
|
||||
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = (val<<1) ^ (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 */
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, unsigned nvals, unsigned parameter)
|
||||
{
|
||||
const FLAC__uint32 mask1 = FLAC__WORD_ALL_ONES << parameter; /* we val|=mask1 to set the stop bit above it... */
|
||||
const FLAC__uint32 mask2 = FLAC__WORD_ALL_ONES >> (31-parameter); /* ...then mask off the bits above the stop bit with val&=mask2*/
|
||||
FLAC__uint32 uval;
|
||||
unsigned left;
|
||||
const unsigned lsbits = 1 + parameter;
|
||||
unsigned msbits;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter < 8*sizeof(uint32_t)-1);
|
||||
/* WATCHOUT: code does not work with <32bit words; we can make things much faster with this assertion */
|
||||
FLAC__ASSERT(FLAC__BITS_PER_WORD >= 32);
|
||||
|
||||
while(nvals) {
|
||||
/* fold signed to unsigned; actual formula is: negative(v)? -2v-1 : 2v */
|
||||
uval = (*vals<<1) ^ (*vals>>31);
|
||||
|
||||
msbits = uval >> parameter;
|
||||
|
||||
if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current uint32_t */
|
||||
/* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free uint32_t to work in */
|
||||
bw->bits = bw->bits + msbits + lsbits;
|
||||
uval |= mask1; /* set stop bit */
|
||||
uval &= mask2; /* mask off unused top bits */
|
||||
bw->accum <<= msbits + lsbits;
|
||||
bw->accum |= uval;
|
||||
}
|
||||
else {
|
||||
/* slightly pessimistic size check but faster than "<= bw->words + (bw->bits+msbits+lsbits+FLAC__BITS_PER_WORD-1)/FLAC__BITS_PER_WORD" */
|
||||
/* OPT: pessimism may cause flurry of false calls to grow_ which eat up all savings before it */
|
||||
if(bw->capacity <= bw->words + bw->bits + msbits + 1/*lsbits always fit in 1 uint32_t*/ && !bitwriter_grow_(bw, msbits+lsbits))
|
||||
return false;
|
||||
|
||||
if(msbits) {
|
||||
/* first part gets to word alignment */
|
||||
if(bw->bits) {
|
||||
left = FLAC__BITS_PER_WORD - bw->bits;
|
||||
if(msbits < left) {
|
||||
bw->accum <<= msbits;
|
||||
bw->bits += msbits;
|
||||
goto break1;
|
||||
}
|
||||
else {
|
||||
bw->accum <<= left;
|
||||
msbits -= left;
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->bits = 0;
|
||||
}
|
||||
}
|
||||
/* do whole words */
|
||||
while(msbits >= FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = 0;
|
||||
msbits -= FLAC__BITS_PER_WORD;
|
||||
}
|
||||
/* do any leftovers */
|
||||
if(msbits > 0) {
|
||||
bw->accum = 0;
|
||||
bw->bits = msbits;
|
||||
}
|
||||
}
|
||||
break1:
|
||||
uval |= mask1; /* set stop bit */
|
||||
uval &= mask2; /* mask off unused top bits */
|
||||
|
||||
left = FLAC__BITS_PER_WORD - bw->bits;
|
||||
if(lsbits < left) {
|
||||
bw->accum <<= lsbits;
|
||||
bw->accum |= uval;
|
||||
bw->bits += lsbits;
|
||||
}
|
||||
else {
|
||||
/* if bw->bits == 0, left==FLAC__BITS_PER_WORD which will always
|
||||
* be > lsbits (because of previous assertions) so it would have
|
||||
* triggered the (lsbits<left) case above.
|
||||
*/
|
||||
FLAC__ASSERT(bw->bits);
|
||||
FLAC__ASSERT(left < FLAC__BITS_PER_WORD);
|
||||
bw->accum <<= left;
|
||||
bw->accum |= uval >> (bw->bits = lsbits - left);
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->accum = uval;
|
||||
}
|
||||
}
|
||||
vals++;
|
||||
nvals--;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, unsigned parameter)
|
||||
{
|
||||
unsigned total_bits, msbs, uval;
|
||||
unsigned k;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
/* fold signed to unsigned */
|
||||
if(val < 0)
|
||||
uval = (unsigned)(((-(++val)) << 1) + 1);
|
||||
else
|
||||
uval = (unsigned)(val << 1);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
unsigned 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 {
|
||||
unsigned 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, unsigned uval, unsigned parameter)
|
||||
{
|
||||
unsigned total_bits, msbs;
|
||||
unsigned k;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
FLAC__ASSERT(parameter > 0);
|
||||
|
||||
k = FLAC__bitmath_ilog2(parameter);
|
||||
if(parameter == 1u<<k) {
|
||||
unsigned 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 {
|
||||
unsigned 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);
|
||||
|
||||
FLAC__ASSERT(!(val & 0x80000000)); /* this version only handles 31 bits */
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (val>>6), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (val>>12), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (val>>18), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (val>>24), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (val>>30), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(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);
|
||||
|
||||
FLAC__ASSERT(!(val & FLAC__U64L(0xFFFFFFF000000000))); /* this version only handles 36 bits */
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitwriter_write_raw_uint32(bw, (FLAC__uint32)val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xC0 | (FLAC__uint32)(val>>6), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xE0 | (FLAC__uint32)(val>>12), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF0 | (FLAC__uint32)(val>>18), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xF8 | (FLAC__uint32)(val>>24), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x80000000) {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFC | (FLAC__uint32)(val>>30), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)(val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0xFE, 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>30)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(bw, 0x80 | (FLAC__uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitwriter_write_raw_uint32(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, unsigned bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits);
|
||||
extern FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned 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[], unsigned nvals);
|
||||
@@ -0,0 +1,490 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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"
|
||||
|
||||
#if 0
|
||||
#include <stdlib.h>
|
||||
#include <memory.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#if defined FLAC__CPU_IA32
|
||||
# include <signal.h>
|
||||
|
||||
static void disable_sse(FLAC__CPUInfo *info)
|
||||
{
|
||||
info->ia32.sse = false;
|
||||
info->ia32.sse2 = false;
|
||||
info->ia32.sse3 = false;
|
||||
info->ia32.ssse3 = false;
|
||||
info->ia32.sse41 = false;
|
||||
info->ia32.sse42 = false;
|
||||
}
|
||||
|
||||
static void disable_avx(FLAC__CPUInfo *info)
|
||||
{
|
||||
info->ia32.avx = false;
|
||||
info->ia32.avx2 = false;
|
||||
info->ia32.fma = false;
|
||||
}
|
||||
|
||||
#elif defined FLAC__CPU_X86_64
|
||||
|
||||
static void disable_avx(FLAC__CPUInfo *info)
|
||||
{
|
||||
info->x86.avx = false;
|
||||
info->x86.avx2 = false;
|
||||
info->x86.fma = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined (__NetBSD__) || defined(__OpenBSD__)
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
#include <machine/cpu.h>
|
||||
#endif
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__)
|
||||
#include <sys/types.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
#if defined(__APPLE__)
|
||||
/* how to get sysctlbyname()? */
|
||||
#endif
|
||||
|
||||
#ifdef FLAC__CPU_IA32
|
||||
/* these are flags in EDX of CPUID AX=00000001 */
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_CMOV = 0x00008000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_MMX = 0x00800000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_FXSR = 0x01000000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE = 0x02000000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE2 = 0x04000000;
|
||||
#endif
|
||||
|
||||
/* these are flags in ECX of CPUID AX=00000001 */
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE3 = 0x00000001;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSSE3 = 0x00000200;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE41 = 0x00080000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_SSE42 = 0x00100000;
|
||||
|
||||
#if defined FLAC__AVX_SUPPORTED
|
||||
/* these are flags in ECX of CPUID AX=00000001 */
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_OSXSAVE = 0x08000000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX = 0x10000000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_FMA = 0x00001000;
|
||||
/* these are flags in EBX of CPUID AX=00000007 */
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_AVX2 = 0x00000020;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Extra stuff needed for detection of OS support for SSE on IA-32
|
||||
*/
|
||||
#if defined(FLAC__CPU_IA32) && !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN) && !defined FLAC__NO_SSE_OS && !defined FLAC__SSE_OS
|
||||
# if defined(__linux__)
|
||||
/*
|
||||
* If the OS doesn't support SSE, we will get here with a SIGILL. We
|
||||
* modify the return address to jump over the offending SSE instruction
|
||||
* and also the operation following it that indicates the instruction
|
||||
* executed successfully. In this way we use no global variables and
|
||||
* stay thread-safe.
|
||||
*
|
||||
* 3 + 3 + 6:
|
||||
* 3 bytes for "xorps xmm0,xmm0"
|
||||
* 3 bytes for estimate of how long the follwing "inc var" instruction is
|
||||
* 6 bytes extra in case our estimate is wrong
|
||||
* 12 bytes puts us in the NOP "landing zone"
|
||||
*/
|
||||
# include <sys/ucontext.h>
|
||||
static void sigill_handler_sse_os(int signal, siginfo_t *si, void *uc)
|
||||
{
|
||||
(void)signal, (void)si;
|
||||
((ucontext_t*)uc)->uc_mcontext.gregs[14/*REG_EIP*/] += 3 + 3 + 6;
|
||||
}
|
||||
# elif defined(_MSC_VER)
|
||||
# include <windows.h>
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
void FLAC__cpu_info(FLAC__CPUInfo *info)
|
||||
{
|
||||
/*
|
||||
* IA32-specific
|
||||
*/
|
||||
#ifdef FLAC__CPU_IA32
|
||||
FLAC__bool ia32_fxsr = false;
|
||||
FLAC__bool ia32_osxsave = false;
|
||||
(void) ia32_fxsr; (void) ia32_osxsave; /* to avoid warnings about unused variables */
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->type = FLAC__CPUINFO_TYPE_IA32;
|
||||
#if !defined FLAC__NO_ASM && (defined FLAC__HAS_NASM || defined FLAC__HAS_X86INTRIN)
|
||||
info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */
|
||||
#ifdef FLAC__HAS_X86INTRIN
|
||||
if(!FLAC__cpu_have_cpuid_x86())
|
||||
return;
|
||||
#else
|
||||
if(!FLAC__cpu_have_cpuid_asm_ia32())
|
||||
return;
|
||||
#endif
|
||||
{
|
||||
/* http://www.sandpile.org/x86/cpuid.htm */
|
||||
#ifdef FLAC__HAS_X86INTRIN
|
||||
FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
|
||||
FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
#else
|
||||
FLAC__uint32 flags_ecx, flags_edx;
|
||||
FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx);
|
||||
#endif
|
||||
info->ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false;
|
||||
info->ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false;
|
||||
ia32_fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false;
|
||||
info->ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false;
|
||||
info->ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false;
|
||||
info->ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
|
||||
info->ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
|
||||
info->ia32.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false;
|
||||
info->ia32.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false;
|
||||
#if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED
|
||||
ia32_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false;
|
||||
info->ia32.avx = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX )? true : false;
|
||||
info->ia32.fma = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA )? true : false;
|
||||
FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
info->ia32.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 )? true : false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "CPU info (IA-32):\n");
|
||||
fprintf(stderr, " CMOV ....... %c\n", info->ia32.cmov ? 'Y' : 'n');
|
||||
fprintf(stderr, " MMX ........ %c\n", info->ia32.mmx ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE ........ %c\n", info->ia32.sse ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE2 ....... %c\n", info->ia32.sse2 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE3 ....... %c\n", info->ia32.sse3 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSSE3 ...... %c\n", info->ia32.ssse3 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE41 ...... %c\n", info->ia32.sse41 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE42 ...... %c\n", info->ia32.sse42 ? 'Y' : 'n');
|
||||
# if defined FLAC__HAS_X86INTRIN && defined FLAC__AVX_SUPPORTED
|
||||
fprintf(stderr, " AVX ........ %c\n", info->ia32.avx ? 'Y' : 'n');
|
||||
fprintf(stderr, " FMA ........ %c\n", info->ia32.fma ? 'Y' : 'n');
|
||||
fprintf(stderr, " AVX2 ....... %c\n", info->ia32.avx2 ? 'Y' : 'n');
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now have to check for OS support of SSE instructions
|
||||
*/
|
||||
if(info->ia32.sse) {
|
||||
#if defined FLAC__NO_SSE_OS
|
||||
/* assume user knows better than us; turn it off */
|
||||
disable_sse(info);
|
||||
#elif defined FLAC__SSE_OS
|
||||
/* assume user knows better than us; leave as detected above */
|
||||
#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) || defined(__DragonFly__) || defined(__APPLE__)
|
||||
int sse = 0;
|
||||
size_t len;
|
||||
/* at least one of these must work: */
|
||||
len = sizeof(sse); sse = sse || (sysctlbyname("hw.instruction_sse", &sse, &len, NULL, 0) == 0 && sse);
|
||||
len = sizeof(sse); sse = sse || (sysctlbyname("hw.optional.sse" , &sse, &len, NULL, 0) == 0 && sse); /* __APPLE__ ? */
|
||||
if(!sse)
|
||||
disable_sse(info);
|
||||
#elif defined(__NetBSD__) || defined (__OpenBSD__)
|
||||
# if __NetBSD_Version__ >= 105250000 || (defined __OpenBSD__)
|
||||
int val = 0, mib[2] = { CTL_MACHDEP, CPU_SSE };
|
||||
size_t len = sizeof(val);
|
||||
if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val)
|
||||
disable_sse(info);
|
||||
else { /* double-check SSE2 */
|
||||
mib[1] = CPU_SSE2;
|
||||
len = sizeof(val);
|
||||
if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val) {
|
||||
disable_sse(info);
|
||||
info->ia32.sse = true;
|
||||
}
|
||||
}
|
||||
# else
|
||||
disable_sse(info);
|
||||
# endif
|
||||
#elif defined(__linux__)
|
||||
int sse = 0;
|
||||
struct sigaction sigill_save;
|
||||
struct sigaction sigill_sse;
|
||||
sigill_sse.sa_sigaction = sigill_handler_sse_os;
|
||||
__sigemptyset(&sigill_sse.sa_mask);
|
||||
sigill_sse.sa_flags = SA_SIGINFO | SA_RESETHAND; /* SA_RESETHAND just in case our SIGILL return jump breaks, so we don't get stuck in a loop */
|
||||
if(0 == sigaction(SIGILL, &sigill_sse, &sigill_save))
|
||||
{
|
||||
/* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */
|
||||
/* see sigill_handler_sse_os() for an explanation of the following: */
|
||||
asm volatile (
|
||||
"xorps %%xmm0,%%xmm0\n\t" /* will cause SIGILL if unsupported by OS */
|
||||
"incl %0\n\t" /* SIGILL handler will jump over this */
|
||||
/* landing zone */
|
||||
"nop\n\t" /* SIGILL jump lands here if "inc" is 9 bytes */
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t"
|
||||
"nop\n\t" /* SIGILL jump lands here if "inc" is 3 bytes (expected) */
|
||||
"nop\n\t"
|
||||
"nop" /* SIGILL jump lands here if "inc" is 1 byte */
|
||||
: "=r"(sse)
|
||||
: "0"(sse)
|
||||
);
|
||||
|
||||
sigaction(SIGILL, &sigill_save, NULL);
|
||||
}
|
||||
|
||||
if(!sse)
|
||||
disable_sse(info);
|
||||
#elif defined(_MSC_VER)
|
||||
__try {
|
||||
__asm {
|
||||
xorps xmm0,xmm0
|
||||
}
|
||||
}
|
||||
__except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
|
||||
disable_sse(info);
|
||||
}
|
||||
#elif defined(__GNUC__) /* MinGW goes here */
|
||||
int sse = 0;
|
||||
/* Based on the idea described in Agner Fog's manual "Optimizing subroutines in assembly language" */
|
||||
/* In theory, not guaranteed to detect lack of OS SSE support on some future Intel CPUs, but in practice works (see the aforementioned manual) */
|
||||
if (ia32_fxsr) {
|
||||
struct {
|
||||
FLAC__uint32 buff[128];
|
||||
} __attribute__((aligned(16))) fxsr;
|
||||
FLAC__uint32 old_val, new_val;
|
||||
|
||||
asm volatile ("fxsave %0" : "=m" (fxsr) : "m" (fxsr));
|
||||
old_val = fxsr.buff[50];
|
||||
fxsr.buff[50] ^= 0x0013c0de; /* change value in the buffer */
|
||||
asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr)); /* try to change SSE register */
|
||||
fxsr.buff[50] = old_val; /* restore old value in the buffer */
|
||||
asm volatile ("fxsave %0 " : "=m" (fxsr) : "m" (fxsr)); /* old value will be overwritten if SSE register was changed */
|
||||
new_val = fxsr.buff[50]; /* == old_val if FXRSTOR didn't change SSE register and (old_val ^ 0x0013c0de) otherwise */
|
||||
fxsr.buff[50] = old_val; /* again restore old value in the buffer */
|
||||
asm volatile ("fxrstor %0" : "=m" (fxsr) : "m" (fxsr)); /* restore old values of registers */
|
||||
|
||||
if ((old_val^new_val) == 0x0013c0de)
|
||||
sse = 1;
|
||||
}
|
||||
if(!sse)
|
||||
disable_sse(info);
|
||||
#else
|
||||
/* no way to test, disable to be safe */
|
||||
disable_sse(info);
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " SSE OS sup . %c\n", info->ia32.sse ? 'Y' : 'n');
|
||||
#endif
|
||||
}
|
||||
else /* info->ia32.sse == false */
|
||||
disable_sse(info);
|
||||
|
||||
/*
|
||||
* now have to check for OS support of AVX instructions
|
||||
*/
|
||||
if(info->ia32.avx && ia32_osxsave) {
|
||||
FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86();
|
||||
if ((ecr & 0x6) != 0x6)
|
||||
disable_avx(info);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " AVX OS sup . %c\n", info->ia32.avx ? 'Y' : 'n');
|
||||
#endif
|
||||
}
|
||||
else /* no OS AVX support*/
|
||||
disable_avx(info);
|
||||
#else
|
||||
info->use_asm = false;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* x86-64-specific
|
||||
*/
|
||||
#elif defined FLAC__CPU_X86_64
|
||||
FLAC__bool x86_osxsave = false;
|
||||
(void) x86_osxsave; /* to avoid warnings about unused variables */
|
||||
memset(info, 0, sizeof(*info));
|
||||
info->type = FLAC__CPUINFO_TYPE_X86_64;
|
||||
#if !defined FLAC__NO_ASM && defined FLAC__HAS_X86INTRIN
|
||||
info->use_asm = true;
|
||||
{
|
||||
/* http://www.sandpile.org/x86/cpuid.htm */
|
||||
FLAC__uint32 flags_eax, flags_ebx, flags_ecx, flags_edx;
|
||||
FLAC__cpu_info_x86(1, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
info->x86.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
|
||||
info->x86.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
|
||||
info->x86.sse41 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE41)? true : false;
|
||||
info->x86.sse42 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE42)? true : false;
|
||||
#if defined FLAC__AVX_SUPPORTED
|
||||
x86_osxsave = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_OSXSAVE)? true : false;
|
||||
info->x86.avx = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_AVX )? true : false;
|
||||
info->x86.fma = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_FMA )? true : false;
|
||||
FLAC__cpu_info_x86(7, &flags_eax, &flags_ebx, &flags_ecx, &flags_edx);
|
||||
info->x86.avx2 = (flags_ebx & FLAC__CPUINFO_IA32_CPUID_AVX2 )? true : false;
|
||||
#endif
|
||||
}
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "CPU info (x86-64):\n");
|
||||
fprintf(stderr, " SSE3 ....... %c\n", info->x86.sse3 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSSE3 ...... %c\n", info->x86.ssse3 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE41 ...... %c\n", info->x86.sse41 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE42 ...... %c\n", info->x86.sse42 ? 'Y' : 'n');
|
||||
# if defined FLAC__AVX_SUPPORTED
|
||||
fprintf(stderr, " AVX ........ %c\n", info->x86.avx ? 'Y' : 'n');
|
||||
fprintf(stderr, " FMA ........ %c\n", info->x86.fma ? 'Y' : 'n');
|
||||
fprintf(stderr, " AVX2 ....... %c\n", info->x86.avx2 ? 'Y' : 'n');
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now have to check for OS support of AVX instructions
|
||||
*/
|
||||
if(info->x86.avx && x86_osxsave) {
|
||||
FLAC__uint32 ecr = FLAC__cpu_xgetbv_x86();
|
||||
if ((ecr & 0x6) != 0x6)
|
||||
disable_avx(info);
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " AVX OS sup . %c\n", info->x86.avx ? 'Y' : 'n');
|
||||
#endif
|
||||
}
|
||||
else /* no OS AVX support*/
|
||||
disable_avx(info);
|
||||
#else
|
||||
info->use_asm = false;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* unknown CPU
|
||||
*/
|
||||
#else
|
||||
info->type = FLAC__CPUINFO_TYPE_UNKNOWN;
|
||||
info->use_asm = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
|
||||
#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
|
||||
|
||||
FLAC__uint32 FLAC__cpu_have_cpuid_x86(void)
|
||||
{
|
||||
#ifdef FLAC__CPU_X86_64
|
||||
return 1;
|
||||
#else
|
||||
# if defined _MSC_VER || defined __INTEL_COMPILER /* Do they support CPUs w/o CPUID support (or OSes that work on those CPUs)? */
|
||||
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;
|
||||
# elif defined __GNUC__ && defined HAVE_CPUID_H
|
||||
if (__get_cpuid_max(0, 0) != 0)
|
||||
return 1;
|
||||
else
|
||||
return 0;
|
||||
# else
|
||||
return 0;
|
||||
# endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void FLAC__cpu_info_x86(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx)
|
||||
{
|
||||
(void) level;
|
||||
|
||||
#if defined _MSC_VER || defined __INTEL_COMPILER
|
||||
int cpuinfo[4];
|
||||
int ext = level & 0x80000000;
|
||||
__cpuid(cpuinfo, ext);
|
||||
if((unsigned)cpuinfo[0] < level) {
|
||||
*eax = *ebx = *ecx = *edx = 0;
|
||||
return;
|
||||
}
|
||||
#if defined 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];
|
||||
#elif defined __GNUC__ && defined HAVE_CPUID_H
|
||||
FLAC__uint32 ext = level & 0x80000000;
|
||||
__cpuid(ext, *eax, *ebx, *ecx, *edx);
|
||||
if (*eax < level) {
|
||||
*eax = *ebx = *ecx = *edx = 0;
|
||||
return;
|
||||
}
|
||||
__cpuid_count(level, 0, *eax, *ebx, *ecx, *edx);
|
||||
#else
|
||||
*eax = *ebx = *ecx = *edx = 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
FLAC__uint32 FLAC__cpu_xgetbv_x86(void)
|
||||
{
|
||||
#if (defined _MSC_VER || defined __INTEL_COMPILER) && defined FLAC__AVX_SUPPORTED
|
||||
return (FLAC__uint32)_xgetbv(0);
|
||||
#elif defined __GNUC__
|
||||
FLAC__uint32 lo, hi;
|
||||
asm volatile (".byte 0x0f, 0x01, 0xd0" : "=a"(lo), "=d"(hi) : "c" (0));
|
||||
return lo;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* (FLAC__CPU_IA32 || FLAC__CPU_X86_64) && FLAC__HAS_X86INTRIN */
|
||||
@@ -0,0 +1,143 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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__byte 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 */
|
||||
|
||||
unsigned const FLAC__crc16_table[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
|
||||
};
|
||||
|
||||
|
||||
void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc)
|
||||
{
|
||||
*crc = FLAC__crc8_table[*crc ^ data];
|
||||
}
|
||||
|
||||
void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc)
|
||||
{
|
||||
while(len--)
|
||||
*crc = FLAC__crc8_table[*crc ^ *data++];
|
||||
}
|
||||
|
||||
FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len)
|
||||
{
|
||||
FLAC__uint8 crc = 0;
|
||||
|
||||
while(len--)
|
||||
crc = FLAC__crc8_table[crc ^ *data++];
|
||||
|
||||
return crc;
|
||||
}
|
||||
|
||||
unsigned FLAC__crc16(const FLAC__byte *data, unsigned len)
|
||||
{
|
||||
unsigned crc = 0;
|
||||
|
||||
while(len--)
|
||||
crc = ((crc<<8) ^ FLAC__crc16_table[(crc>>8) ^ *data++]) & 0xffff;
|
||||
|
||||
return crc;
|
||||
}
|
||||
@@ -0,0 +1,418 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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) ((unsigned)((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;
|
||||
unsigned 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, (unsigned)(-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;
|
||||
unsigned 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, (unsigned)(-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
|
||||
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#else
|
||||
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
FLAC__uint32 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
|
||||
unsigned i, order;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__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
|
||||
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#else
|
||||
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
#endif
|
||||
{
|
||||
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;
|
||||
/* total_error_* are 64-bits to avoid overflow when encoding
|
||||
* erratic signals when the bits-per-sample and blocksize are
|
||||
* large.
|
||||
*/
|
||||
FLAC__uint64 total_error_0 = 0, total_error_1 = 0, total_error_2 = 0, total_error_3 = 0, total_error_4 = 0;
|
||||
unsigned i, order;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)total_error_0 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[1] = (FLAC__float)((total_error_1 > 0) ? log(M_LN2 * (FLAC__double)total_error_1 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[2] = (FLAC__float)((total_error_2 > 0) ? log(M_LN2 * (FLAC__double)total_error_2 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[3] = (FLAC__float)((total_error_3 > 0) ? log(M_LN2 * (FLAC__double)total_error_3 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[4] = (FLAC__float)((total_error_4 > 0) ? log(M_LN2 * (FLAC__double)total_error_4 / (FLAC__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;
|
||||
}
|
||||
|
||||
void FLAC__fixed_compute_residual(const FLAC__int32 data[], unsigned data_len, unsigned 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++)
|
||||
#if 1 /* OPT: may be faster with some compilers on some systems */
|
||||
residual[i] = data[i] - (data[i-1] << 1) + data[i-2];
|
||||
#else
|
||||
residual[i] = data[i] - 2*data[i-1] + data[i-2];
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
#if 1 /* OPT: may be faster with some compilers on some systems */
|
||||
residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3];
|
||||
#else
|
||||
residual[i] = data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3];
|
||||
#endif
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
#if 1 /* OPT: may be faster with some compilers on some systems */
|
||||
residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4];
|
||||
#else
|
||||
residual[i] = data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4];
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__fixed_restore_signal(const FLAC__int32 residual[], unsigned data_len, unsigned 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++)
|
||||
#if 1 /* OPT: may be faster with some compilers on some systems */
|
||||
data[i] = residual[i] + (data[i-1]<<1) - data[i-2];
|
||||
#else
|
||||
data[i] = residual[i] + 2*data[i-1] - data[i-2];
|
||||
#endif
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
#if 1 /* OPT: may be faster with some compilers on some systems */
|
||||
data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3];
|
||||
#else
|
||||
data[i] = residual[i] + 3*data[i-1] - 3*data[i-2] + data[i-3];
|
||||
#endif
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < idata_len; i++)
|
||||
#if 1 /* OPT: may be faster with some compilers on some systems */
|
||||
data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4];
|
||||
#else
|
||||
data[i] = residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4];
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
FLAC__ASSERT(0);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,302 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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, unsigned fracbits, unsigned 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,584 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 "../compat.h"
|
||||
#include "include/private/format.h"
|
||||
|
||||
/* VERSION should come from configure */
|
||||
FLAC_API const char *FLAC__VERSION_STRING = VERSION;
|
||||
|
||||
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20141125";
|
||||
|
||||
FLAC_API const FLAC__byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
|
||||
FLAC_API const unsigned FLAC__STREAM_SYNC = 0x664C6143;
|
||||
FLAC_API const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_BLOCK_SIZE_LEN = 16; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_BLOCK_SIZE_LEN = 16; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MIN_FRAME_SIZE_LEN = 24; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MAX_FRAME_SIZE_LEN = 24; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_SAMPLE_RATE_LEN = 20; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_CHANNELS_LEN = 3; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_BITS_PER_SAMPLE_LEN = 5; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_TOTAL_SAMPLES_LEN = 36; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_STREAMINFO_MD5SUM_LEN = 128; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_APPLICATION_ID_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_SAMPLE_NUMBER_LEN = 64; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_SEEKPOINT_STREAM_OFFSET_LEN = 64; /* bits */
|
||||
FLAC_API const unsigned 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 unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_ENTRY_LENGTH_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_VORBIS_COMMENT_NUM_COMMENTS_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN = 64; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_NUMBER_LEN = 8; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_INDEX_RESERVED_LEN = 3*8; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_OFFSET_LEN = 64; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUMBER_LEN = 8; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_ISRC_LEN = 12*8; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_TYPE_LEN = 1; /* bit */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_PRE_EMPHASIS_LEN = 1; /* bit */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_RESERVED_LEN = 6+13*8; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_TRACK_NUM_INDICES_LEN = 8; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_MEDIA_CATALOG_NUMBER_LEN = 128*8; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_LEAD_IN_LEN = 64; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_IS_CD_LEN = 1; /* bit */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_RESERVED_LEN = 7+258*8; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_CUESHEET_NUM_TRACKS_LEN = 8; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_TYPE_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_MIME_TYPE_LENGTH_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DESCRIPTION_LENGTH_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_WIDTH_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_HEIGHT_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DEPTH_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_COLORS_LEN = 32; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_PICTURE_DATA_LENGTH_LEN = 32; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
|
||||
FLAC_API const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC = 0x3ffe;
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 14; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_RESERVED_LEN = 1; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCKING_STRATEGY_LEN = 1; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 4; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
|
||||
FLAC_API const unsigned FLAC__FRAME_HEADER_CRC_LEN = 8; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__FRAME_FOOTER_CRC_LEN = 16; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
|
||||
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
|
||||
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
|
||||
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN = 5; /* bits */
|
||||
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_RAW_LEN = 5; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER = 15; /* == (1<<FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN)-1 */
|
||||
FLAC_API const unsigned 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 unsigned FLAC__SUBFRAME_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_LPC_QLP_SHIFT_LEN = 5; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_ZERO_PAD_LEN = 1; /* bits */
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_LEN = 6; /* bits */
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_WASTED_BITS_FLAG_LEN = 1; /* bits */
|
||||
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_CONSTANT_BYTE_ALIGNED_MASK = 0x00;
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_VERBATIM_BYTE_ALIGNED_MASK = 0x02;
|
||||
FLAC_API const unsigned FLAC__SUBFRAME_TYPE_FIXED_BYTE_ALIGNED_MASK = 0x10;
|
||||
FLAC_API const unsigned 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(unsigned sample_rate)
|
||||
{
|
||||
if(sample_rate == 0 || sample_rate > FLAC__MAX_SAMPLE_RATE) {
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC_API FLAC__bool FLAC__format_blocksize_is_subset(unsigned blocksize, unsigned 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(unsigned sample_rate)
|
||||
{
|
||||
if(
|
||||
!FLAC__format_sample_rate_is_valid(sample_rate) ||
|
||||
(
|
||||
sample_rate >= (1u << 16) &&
|
||||
!(sample_rate % 1000 == 0 || sample_rate % 10 == 0)
|
||||
)
|
||||
) {
|
||||
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)
|
||||
{
|
||||
unsigned i;
|
||||
FLAC__uint64 prev_sample_number = 0;
|
||||
FLAC__bool got_prev = false;
|
||||
|
||||
FLAC__ASSERT(0 != seek_table);
|
||||
|
||||
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 unsigned FLAC__format_seektable_sort(FLAC__StreamMetadata_SeekTable *seek_table)
|
||||
{
|
||||
unsigned i, j;
|
||||
FLAC__bool first;
|
||||
|
||||
FLAC__ASSERT(0 != seek_table);
|
||||
|
||||
/* 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 unsigned 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, unsigned length)
|
||||
{
|
||||
if(length == (unsigned)(-1)) {
|
||||
while(*value) {
|
||||
unsigned n = utf8len_(value);
|
||||
if(n == 0)
|
||||
return false;
|
||||
value += n;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const FLAC__byte *end = value + length;
|
||||
while(value < end) {
|
||||
unsigned 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, unsigned 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) {
|
||||
unsigned 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)
|
||||
{
|
||||
unsigned 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; ) {
|
||||
unsigned 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
|
||||
*/
|
||||
unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned 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
|
||||
);
|
||||
}
|
||||
|
||||
unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize)
|
||||
{
|
||||
unsigned 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);
|
||||
}
|
||||
|
||||
unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned predictor_order)
|
||||
{
|
||||
unsigned 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);
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__format_entropy_coding_method_partitioned_rice_contents_ensure_size(FLAC__EntropyCodingMethod_PartitionedRiceContents *object, unsigned max_partition_order)
|
||||
{
|
||||
FLAC__ASSERT(0 != object);
|
||||
|
||||
FLAC__ASSERT(object->capacity_by_order > 0 || (0 == object->parameters && 0 == object->raw_bits));
|
||||
|
||||
if(object->capacity_by_order < max_partition_order) {
|
||||
if(0 == (object->parameters = (unsigned int*) realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order))))
|
||||
return false;
|
||||
if(0 == (object->raw_bits = (unsigned int*) realloc(object->raw_bits, sizeof(unsigned)*(1 << max_partition_order))))
|
||||
return false;
|
||||
memset(object->raw_bits, 0, sizeof(unsigned)*(1 << max_partition_order));
|
||||
object->capacity_by_order = max_partition_order;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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__ALL_H
|
||||
#define FLAC__PRIVATE__ALL_H
|
||||
|
||||
#include "bitmath.h"
|
||||
#include "bitreader.h"
|
||||
#include "bitwriter.h"
|
||||
#include "cpu.h"
|
||||
#include "crc.h"
|
||||
#include "fixed.h"
|
||||
#include "float.h"
|
||||
#include "format.h"
|
||||
#include "lpc.h"
|
||||
#include "md5.h"
|
||||
#include "memory.h"
|
||||
#include "metadata.h"
|
||||
#include "stream_encoder_framing.h"
|
||||
|
||||
#endif
|
||||
+186
@@ -0,0 +1,186 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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"
|
||||
|
||||
/* for CHAR_BIT */
|
||||
#include <limits.h>
|
||||
#include "../../../compat.h"
|
||||
|
||||
#if defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
#include <intrin.h> /* for _BitScanReverse* */
|
||||
#endif
|
||||
|
||||
/* Will never be emitted for MSVC, GCC, Intel compilers */
|
||||
static inline unsigned int FLAC__clz_soft_uint32(unsigned int word)
|
||||
{
|
||||
static const unsigned char 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 unsigned int 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) && (_MSC_VER >= 1400)
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanReverse(&idx, v);
|
||||
return idx ^ 31U;
|
||||
}
|
||||
#else
|
||||
return FLAC__clz_soft_uint32(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* This one works with input 0 */
|
||||
static inline unsigned int FLAC__clz2_uint32(FLAC__uint32 v)
|
||||
{
|
||||
if (!v)
|
||||
return 32;
|
||||
return FLAC__clz_uint32(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 unsigned FLAC__bitmath_ilog2(FLAC__uint32 v)
|
||||
{
|
||||
FLAC__ASSERT(v > 0);
|
||||
#if defined(__INTEL_COMPILER)
|
||||
return _bit_scan_reverse(v);
|
||||
#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanReverse(&idx, v);
|
||||
return idx;
|
||||
}
|
||||
#else
|
||||
return sizeof(FLAC__uint32) * CHAR_BIT - 1 - FLAC__clz_uint32(v);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef FLAC__INTEGER_ONLY_LIBRARY /* Unused otherwise */
|
||||
|
||||
static inline unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v)
|
||||
{
|
||||
FLAC__ASSERT(v > 0);
|
||||
#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
|
||||
return sizeof(FLAC__uint64) * CHAR_BIT - 1 - __builtin_clzll(v);
|
||||
/* Sorry, only supported in x64/Itanium.. and both have fast FPU which makes integer-only encoder pointless */
|
||||
#elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && (defined(_M_IA64) || defined(_M_X64))
|
||||
{
|
||||
unsigned long idx;
|
||||
_BitScanReverse64(&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 unsigned char 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*0x218A392CD3D5DBF>>58&0x3F];
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
unsigned FLAC__bitmath_silog2(int v);
|
||||
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v);
|
||||
|
||||
#endif
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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_dump(const FLAC__BitReader *br, FILE *out);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
unsigned FLAC__bitreader_bits_left_for_byte_alignment(const FLAC__BitReader *br);
|
||||
unsigned FLAC__bitreader_get_input_bits_unconsumed(const FLAC__BitReader *br);
|
||||
|
||||
/*
|
||||
* read functions
|
||||
*/
|
||||
|
||||
FLAC__bool FLAC__bitreader_read_raw_uint32(FLAC__BitReader *br, FLAC__uint32 *val, unsigned bits);
|
||||
FLAC__bool FLAC__bitreader_read_raw_int32(FLAC__BitReader *br, FLAC__int32 *val, unsigned bits);
|
||||
FLAC__bool FLAC__bitreader_read_raw_uint64(FLAC__BitReader *br, FLAC__uint64 *val, unsigned 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, unsigned 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, unsigned nvals); /* WATCHOUT: does not CRC the read data! */
|
||||
FLAC__bool FLAC__bitreader_read_byte_block_aligned_no_crc(FLAC__BitReader *br, FLAC__byte *val, unsigned nvals); /* WATCHOUT: does not CRC the read data! */
|
||||
FLAC__bool FLAC__bitreader_read_unary_unsigned(FLAC__BitReader *br, unsigned *val);
|
||||
FLAC__bool FLAC__bitreader_read_rice_signed(FLAC__BitReader *br, int *val, unsigned parameter);
|
||||
FLAC__bool FLAC__bitreader_read_rice_signed_block(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter);
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitreader_read_golomb_signed(FLAC__BitReader *br, int *val, unsigned parameter);
|
||||
FLAC__bool FLAC__bitreader_read_golomb_unsigned(FLAC__BitReader *br, unsigned *val, unsigned parameter);
|
||||
#endif
|
||||
FLAC__bool FLAC__bitreader_read_utf8_uint32(FLAC__BitReader *br, FLAC__uint32 *val, FLAC__byte *raw, unsigned *rawlen);
|
||||
FLAC__bool FLAC__bitreader_read_utf8_uint64(FLAC__BitReader *br, FLAC__uint64 *val, FLAC__byte *raw, unsigned *rawlen);
|
||||
#endif
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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);
|
||||
void FLAC__bitwriter_dump(const FLAC__BitWriter *bw, FILE *out);
|
||||
|
||||
/*
|
||||
* 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);
|
||||
unsigned 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, unsigned bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint32(FLAC__BitWriter *bw, FLAC__uint32 val, unsigned bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_int32(FLAC__BitWriter *bw, FLAC__int32 val, unsigned bits);
|
||||
FLAC__bool FLAC__bitwriter_write_raw_uint64(FLAC__BitWriter *bw, FLAC__uint64 val, unsigned 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[], unsigned nvals);
|
||||
FLAC__bool FLAC__bitwriter_write_unary_unsigned(FLAC__BitWriter *bw, unsigned val);
|
||||
unsigned FLAC__bitwriter_rice_bits(FLAC__int32 val, unsigned parameter);
|
||||
#if 0 /* UNUSED */
|
||||
unsigned FLAC__bitwriter_golomb_bits_signed(int val, unsigned parameter);
|
||||
unsigned FLAC__bitwriter_golomb_bits_unsigned(unsigned val, unsigned parameter);
|
||||
#endif
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed(FLAC__BitWriter *bw, FLAC__int32 val, unsigned parameter);
|
||||
FLAC__bool FLAC__bitwriter_write_rice_signed_block(FLAC__BitWriter *bw, const FLAC__int32 *vals, unsigned nvals, unsigned parameter);
|
||||
#if 0 /* UNUSED */
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_signed(FLAC__BitWriter *bw, int val, unsigned parameter);
|
||||
FLAC__bool FLAC__bitwriter_write_golomb_unsigned(FLAC__BitWriter *bw, unsigned val, unsigned 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
|
||||
@@ -0,0 +1,99 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
|
||||
typedef enum {
|
||||
FLAC__CPUINFO_TYPE_IA32,
|
||||
FLAC__CPUINFO_TYPE_X86_64,
|
||||
FLAC__CPUINFO_TYPE_UNKNOWN
|
||||
} FLAC__CPUInfo_Type;
|
||||
|
||||
#if defined FLAC__CPU_IA32
|
||||
typedef struct {
|
||||
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__CPUInfo_IA32;
|
||||
#elif defined FLAC__CPU_X86_64
|
||||
typedef struct {
|
||||
FLAC__bool sse3;
|
||||
FLAC__bool ssse3;
|
||||
FLAC__bool sse41;
|
||||
FLAC__bool sse42;
|
||||
FLAC__bool avx;
|
||||
FLAC__bool avx2;
|
||||
FLAC__bool fma;
|
||||
} FLAC__CPUInfo_x86;
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
FLAC__bool use_asm;
|
||||
FLAC__CPUInfo_Type type;
|
||||
#if defined FLAC__CPU_IA32
|
||||
FLAC__CPUInfo_IA32 ia32;
|
||||
#elif defined FLAC__CPU_X86_64
|
||||
FLAC__CPUInfo_x86 x86;
|
||||
#endif
|
||||
} FLAC__CPUInfo;
|
||||
|
||||
void FLAC__cpu_info(FLAC__CPUInfo *info);
|
||||
|
||||
#ifndef FLAC__NO_ASM
|
||||
# if defined FLAC__CPU_IA32 && defined FLAC__HAS_NASM
|
||||
FLAC__uint32 FLAC__cpu_have_cpuid_asm_ia32(void);
|
||||
void FLAC__cpu_info_asm_ia32(FLAC__uint32 *flags_edx, FLAC__uint32 *flags_ecx);
|
||||
# endif
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
FLAC__uint32 FLAC__cpu_have_cpuid_x86(void);
|
||||
void FLAC__cpu_info_x86(FLAC__uint32 level, FLAC__uint32 *eax, FLAC__uint32 *ebx, FLAC__uint32 *ecx, FLAC__uint32 *edx);
|
||||
FLAC__uint32 FLAC__cpu_xgetbv_x86(void);
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,62 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
*/
|
||||
extern FLAC__byte const FLAC__crc8_table[256];
|
||||
#define FLAC__CRC8_UPDATE(data, crc) (crc) = FLAC__crc8_table[(crc) ^ (data)];
|
||||
void FLAC__crc8_update(const FLAC__byte data, FLAC__uint8 *crc);
|
||||
void FLAC__crc8_update_block(const FLAC__byte *data, unsigned len, FLAC__uint8 *crc);
|
||||
FLAC__uint8 FLAC__crc8(const FLAC__byte *data, unsigned len);
|
||||
|
||||
/* 16 bit CRC generator, MSB shifted first
|
||||
** polynomial = x^16 + x^15 + x^2 + x^0
|
||||
** init = 0
|
||||
*/
|
||||
extern unsigned const FLAC__crc16_table[256];
|
||||
|
||||
#define FLAC__CRC16_UPDATE(data, crc) ((((crc)<<8) & 0xffff) ^ FLAC__crc16_table[((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[((crc)>>8) ^ (data)]) & 0xffff)
|
||||
#endif
|
||||
|
||||
unsigned FLAC__crc16(const FLAC__byte *data, unsigned len);
|
||||
|
||||
#endif
|
||||
+107
@@ -0,0 +1,107 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
# ifndef FLAC__NO_ASM
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE2_SUPPORTED
|
||||
unsigned FLAC__fixed_compute_best_predictor_intrin_sse2(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]);
|
||||
unsigned FLAC__fixed_compute_best_predictor_wide_intrin_sse2(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]);
|
||||
# endif
|
||||
# ifdef FLAC__SSSE3_SUPPORTED
|
||||
unsigned FLAC__fixed_compute_best_predictor_intrin_ssse3(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
unsigned FLAC__fixed_compute_best_predictor_wide_intrin_ssse3(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER + 1]);
|
||||
# endif
|
||||
# endif
|
||||
# if defined FLAC__CPU_IA32 && defined FLAC__HAS_NASM
|
||||
unsigned FLAC__fixed_compute_best_predictor_asm_ia32_mmx_cmov(const FLAC__int32 data[], unsigned data_len, FLAC__float residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
# endif
|
||||
# endif
|
||||
#else
|
||||
unsigned FLAC__fixed_compute_best_predictor(const FLAC__int32 data[], unsigned data_len, FLAC__fixedpoint residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
unsigned FLAC__fixed_compute_best_predictor_wide(const FLAC__int32 data[], unsigned 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[], unsigned data_len, unsigned 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[], unsigned data_len, unsigned order, FLAC__int32 data[]);
|
||||
|
||||
#endif
|
||||
+98
@@ -0,0 +1,98 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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"
|
||||
|
||||
/*
|
||||
* These typedefs make it easier to ensure that integer versions of
|
||||
* the library really only contain integer operations. All the code
|
||||
* in libFLAC should use FLAC__float and FLAC__double in place of
|
||||
* float and double, and be protected by checks of the macro
|
||||
* FLAC__INTEGER_ONLY_LIBRARY.
|
||||
*
|
||||
* FLAC__real is the basic floating point type used in LPC analysis.
|
||||
*/
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
typedef double FLAC__double;
|
||||
typedef float FLAC__float;
|
||||
/*
|
||||
* 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 (unsigned)(-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, unsigned fracbits, unsigned precision);
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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"
|
||||
|
||||
unsigned FLAC__format_get_max_rice_partition_order(unsigned blocksize, unsigned predictor_order);
|
||||
unsigned FLAC__format_get_max_rice_partition_order_from_blocksize(unsigned blocksize);
|
||||
unsigned FLAC__format_get_max_rice_partition_order_from_blocksize_limited_max_and_predictor_order(unsigned limit, unsigned blocksize, unsigned 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, unsigned max_partition_order);
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,246 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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[], unsigned data_len);
|
||||
|
||||
/*
|
||||
* 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[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
#ifndef FLAC__NO_ASM
|
||||
# ifdef FLAC__CPU_IA32
|
||||
# ifdef FLAC__HAS_NASM
|
||||
void FLAC__lpc_compute_autocorrelation_asm_ia32(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_asm_ia32_sse_lag_16(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
# endif
|
||||
# endif
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE_SUPPORTED
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_4(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_8(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_12(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
void FLAC__lpc_compute_autocorrelation_intrin_sse_lag_16(const FLAC__real data[], unsigned data_len, unsigned lag, FLAC__real autoc[]);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 FLAC__real autoc[], unsigned *max_order, FLAC__real lp_coeff[][FLAC__MAX_LPC_ORDER], FLAC__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[], unsigned order, unsigned 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, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
#ifndef FLAC__NO_ASM
|
||||
# ifdef FLAC__CPU_IA32
|
||||
# ifdef FLAC__HAS_NASM
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_asm_ia32_mmx(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_asm_ia32(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
# endif
|
||||
# endif
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE2_SUPPORTED
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_16_intrin_sse2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_sse2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned 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, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_sse41(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned 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, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_intrin_avx2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients_wide_intrin_avx2(const FLAC__int32 *data, unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 residual[]);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
|
||||
/*
|
||||
* 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[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
void FLAC__lpc_restore_signal_wide(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
#ifndef FLAC__NO_ASM
|
||||
# ifdef FLAC__CPU_IA32
|
||||
# ifdef FLAC__HAS_NASM
|
||||
void FLAC__lpc_restore_signal_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
void FLAC__lpc_restore_signal_asm_ia32_mmx(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
void FLAC__lpc_restore_signal_wide_asm_ia32(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
# endif /* FLAC__HAS_NASM */
|
||||
# endif /* FLAC__CPU_IA32 */
|
||||
# if (defined FLAC__CPU_IA32 || defined FLAC__CPU_X86_64) && defined FLAC__HAS_X86INTRIN
|
||||
# ifdef FLAC__SSE2_SUPPORTED
|
||||
void FLAC__lpc_restore_signal_16_intrin_sse2(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
# endif
|
||||
# ifdef FLAC__SSE4_1_SUPPORTED
|
||||
void FLAC__lpc_restore_signal_wide_intrin_sse41(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
# endif
|
||||
# endif
|
||||
#endif /* FLAC__NO_ASM */
|
||||
|
||||
#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
|
||||
*/
|
||||
FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample(FLAC__double lpc_error, unsigned total_samples);
|
||||
FLAC__double FLAC__lpc_compute_expected_bits_per_residual_sample_with_error_scale(FLAC__double lpc_error, FLAC__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
|
||||
*/
|
||||
unsigned FLAC__lpc_compute_best_order(const FLAC__double lpc_error[], unsigned max_order, unsigned total_samples, unsigned overhead_bits_per_order);
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
|
||||
#endif
|
||||
@@ -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[], unsigned channels, unsigned samples, unsigned bytes_per_sample);
|
||||
|
||||
#endif
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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_uint64_array(size_t elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(size_t elements, unsigned **unaligned_pointer, unsigned **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
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2002-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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__METADATA_H
|
||||
#define FLAC__PRIVATE__METADATA_H
|
||||
|
||||
#include "FLAC/metadata.h"
|
||||
|
||||
/* WATCHOUT: all malloc()ed data in the block is free()ed; this may not
|
||||
* be a consistent state (e.g. PICTURE) or equivalent to the initial
|
||||
* state after FLAC__metadata_object_new()
|
||||
*/
|
||||
void FLAC__metadata_object_delete_data(FLAC__StreamMetadata *object);
|
||||
|
||||
void FLAC__metadata_object_cuesheet_track_delete_data(FLAC__StreamMetadata_CueSheet_Track *object);
|
||||
|
||||
#endif
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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[],
|
||||
unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned 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[],
|
||||
unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned 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[],
|
||||
unsigned residual_samples, unsigned predictor_order, unsigned min_partition_order, unsigned max_partition_order, unsigned bps);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_constant(const FLAC__Subframe_Constant *subframe, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_lpc(const FLAC__Subframe_LPC *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw);
|
||||
FLAC__bool FLAC__subframe_add_verbatim(const FLAC__Subframe_Verbatim *subframe, unsigned samples, unsigned subframe_bps, unsigned 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-2014 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
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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__ALL_H
|
||||
#define FLAC__PROTECTED__ALL_H
|
||||
|
||||
#include "stream_decoder.h"
|
||||
#include "stream_encoder.h"
|
||||
|
||||
#endif
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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;
|
||||
unsigned channels;
|
||||
FLAC__ChannelAssignment channel_assignment;
|
||||
unsigned bits_per_sample;
|
||||
unsigned sample_rate; /* in Hz */
|
||||
unsigned 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
|
||||
*/
|
||||
unsigned FLAC__stream_decoder_get_input_bytes_unconsumed(const FLAC__StreamDecoder *decoder);
|
||||
|
||||
#endif
|
||||
+118
@@ -0,0 +1,118 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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_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;
|
||||
} 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;
|
||||
unsigned channels;
|
||||
unsigned bits_per_sample;
|
||||
unsigned sample_rate;
|
||||
unsigned blocksize;
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
unsigned num_apodizations;
|
||||
FLAC__ApodizationSpecification apodizations[FLAC__MAX_APODIZATION_FUNCTIONS];
|
||||
#endif
|
||||
unsigned max_lpc_order;
|
||||
unsigned qlp_coeff_precision;
|
||||
FLAC__bool do_qlp_coeff_prec_search;
|
||||
FLAC__bool do_exhaustive_model_search;
|
||||
FLAC__bool do_escape_coding;
|
||||
unsigned min_residual_partition_order;
|
||||
unsigned max_residual_partition_order;
|
||||
unsigned rice_parameter_search_dist;
|
||||
FLAC__uint64 total_samples_estimate;
|
||||
FLAC__StreamMetadata **metadata;
|
||||
unsigned 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
@@ -0,0 +1,518 @@
|
||||
#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 "../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])
|
||||
{
|
||||
register 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, unsigned 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, unsigned 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[], unsigned channels, unsigned samples, unsigned bytes_per_sample)
|
||||
{
|
||||
FLAC__byte *buf_ = mbuf->p8;
|
||||
FLAC__int16 *buf16 = mbuf->p16;
|
||||
FLAC__int32 *buf32 = mbuf->p32;
|
||||
FLAC__int32 a_word;
|
||||
unsigned 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[], unsigned channels, unsigned samples, unsigned 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) {
|
||||
FLAC__byte *tmp = (FLAC__byte*) realloc(ctx->internal_buf.p8, bytes_needed);
|
||||
if (0 == tmp) {
|
||||
free(ctx->internal_buf.p8);
|
||||
if (0 == (ctx->internal_buf.p8= (FLAC__byte*) safe_malloc_(bytes_needed)))
|
||||
return false;
|
||||
}
|
||||
else
|
||||
ctx->internal_buf.p8= tmp;
|
||||
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,218 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 "../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_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;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(size_t elements, unsigned **unaligned_pointer, unsigned **aligned_pointer)
|
||||
{
|
||||
unsigned *pu; /* unaligned pointer */
|
||||
union { /* union needed to comply with C99 pointer aliasing rules */
|
||||
unsigned *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 = (unsigned int*) 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
+549
@@ -0,0 +1,549 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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"
|
||||
|
||||
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 unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned raw_bits[], const unsigned partition_order, const FLAC__bool is_extended);
|
||||
|
||||
FLAC__bool FLAC__add_metadata_block(const FLAC__StreamMetadata *metadata, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned i, j;
|
||||
const unsigned vendor_string_length = (unsigned)strlen(FLAC__VENDOR_STRING);
|
||||
|
||||
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
|
||||
*/
|
||||
i = metadata->length;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT) {
|
||||
FLAC__ASSERT(metadata->data.vorbis_comment.vendor_string.length == 0 || 0 != metadata->data.vorbis_comment.vendor_string.entry);
|
||||
i -= metadata->data.vorbis_comment.vendor_string.length;
|
||||
i += vendor_string_length;
|
||||
}
|
||||
FLAC__ASSERT(i < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, i, 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(!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(!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;
|
||||
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;
|
||||
}
|
||||
|
||||
FLAC__ASSERT(FLAC__bitwriter_is_byte_aligned(bw));
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__frame_add_header(const FLAC__FrameHeader *header, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned 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 % 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;
|
||||
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, unsigned subframe_bps, unsigned 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_int32(bw, subframe->value, subframe_bps)
|
||||
;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__subframe_add_fixed(const FLAC__Subframe_Fixed *subframe, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned 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_int32(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, unsigned residual_samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned 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_int32(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, unsigned samples, unsigned subframe_bps, unsigned wasted_bits, FLAC__BitWriter *bw)
|
||||
{
|
||||
unsigned i;
|
||||
const FLAC__int32 *signal = subframe->data;
|
||||
|
||||
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;
|
||||
|
||||
for(i = 0; i < samples; i++)
|
||||
if(!FLAC__bitwriter_write_raw_int32(bw, 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 unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned raw_bits[], const unsigned partition_order, const FLAC__bool is_extended)
|
||||
{
|
||||
const unsigned plen = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_PARAMETER_LEN : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
|
||||
const unsigned pesc = is_extended? FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE2_ESCAPE_PARAMETER : FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ESCAPE_PARAMETER;
|
||||
|
||||
if(partition_order == 0) {
|
||||
unsigned 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 {
|
||||
unsigned i, j, k = 0, k_last = 0;
|
||||
unsigned partition_samples;
|
||||
const unsigned 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,281 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2006-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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 "../assert.h"
|
||||
#include "../format.h"
|
||||
#include "include/private/window.h"
|
||||
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
|
||||
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 * fabs((float)n/(float)N-0.5f) - 0.38f * cos(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 * cos(2.0f * M_PI * n / N) + 0.08f * cos(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 * cos(2.0f * M_PI * n / N) + 0.14128f * cos(4.0f * M_PI * n / N) - 0.01168f * cos(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)(1.0f - 1.93f * cos(2.0f * M_PI * n / N) + 1.29f * cos(4.0f * M_PI * n / N) - 0.388f * cos(6.0f * M_PI * n / N) + 0.0322f * cos(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;
|
||||
|
||||
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 * cos(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 * cos(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 * cos(2.0f * M_PI * n / N) + 0.098f * cos(4.0f * M_PI * n / N) - 0.001f * cos(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*cos(2.0f*M_PI*n/N) + 0.1365995f*cos(4.0f*M_PI*n/N) - 0.0106411f*cos(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 {
|
||||
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 * cos(M_PI * n / Np));
|
||||
window[L-Np-1+n] = (FLAC__real)(0.5f - 0.5f * cos(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 {
|
||||
|
||||
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 * cos(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 * cos(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 {
|
||||
|
||||
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 * cos(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 * cos(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 * cos(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 * cos(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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,86 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000-2009 Josh Coalson
|
||||
* Copyright (C) 2011-2014 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
|
||||
|
||||
#if defined(_MSC_VER) && _MSC_VER < 1600
|
||||
|
||||
/* Microsoft Visual Studio earlier than the 2010 version did not provide
|
||||
* the 1999 ISO C Standard header file <stdint.h>.
|
||||
*/
|
||||
|
||||
typedef __int8 FLAC__int8;
|
||||
typedef unsigned __int8 FLAC__uint8;
|
||||
|
||||
typedef __int16 FLAC__int16;
|
||||
typedef __int32 FLAC__int32;
|
||||
typedef __int64 FLAC__int64;
|
||||
typedef unsigned __int16 FLAC__uint16;
|
||||
typedef unsigned __int32 FLAC__uint32;
|
||||
typedef unsigned __int64 FLAC__uint64;
|
||||
|
||||
#else
|
||||
|
||||
/* For MSVC 2010 and everything else which provides <stdint.h>. */
|
||||
|
||||
#include <stdint.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;
|
||||
|
||||
#endif
|
||||
|
||||
typedef int FLAC__bool;
|
||||
|
||||
typedef FLAC__uint8 FLAC__byte;
|
||||
|
||||
|
||||
#ifdef true
|
||||
#undef true
|
||||
#endif
|
||||
#ifdef false
|
||||
#undef false
|
||||
#endif
|
||||
#ifndef __cplusplus
|
||||
#define true 1
|
||||
#define false 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,69 @@
|
||||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2013-2014 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 _WIN32
|
||||
|
||||
#ifndef flac__win_utf8_io_h
|
||||
#define flac__win_utf8_io_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdarg.h>
|
||||
#include <windows.h>
|
||||
|
||||
int get_utf8_argv(int *argc, char ***argv);
|
||||
|
||||
int printf_utf8(const char *format, ...);
|
||||
int fprintf_utf8(FILE *stream, const char *format, ...);
|
||||
int vfprintf_utf8(FILE *stream, const char *format, va_list argptr);
|
||||
|
||||
FILE *fopen_utf8(const char *filename, const char *mode);
|
||||
int stat_utf8(const char *path, struct stat *buffer);
|
||||
int _stat64_utf8(const char *path, struct __stat64 *buffer);
|
||||
int chmod_utf8(const char *filename, int pmode);
|
||||
int utime_utf8(const char *filename, struct utimbuf *times);
|
||||
int unlink_utf8(const char *filename);
|
||||
int rename_utf8(const char *oldname, const char *newname);
|
||||
size_t strlen_utf8(const char *str);
|
||||
int win_get_console_width(void);
|
||||
int print_console(FILE *stream, const wchar_t *text, size_t len);
|
||||
HANDLE WINAPI CreateFile_utf8(const char *lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPSECURITY_ATTRIBUTES lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, HANDLE hTemplateFile);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,954 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
static const char* const aiffFormatName = "AIFF file";
|
||||
|
||||
//==============================================================================
|
||||
const char* const AiffAudioFormat::appleOneShot = "apple one shot";
|
||||
const char* const AiffAudioFormat::appleRootSet = "apple root set";
|
||||
const char* const AiffAudioFormat::appleRootNote = "apple root note";
|
||||
const char* const AiffAudioFormat::appleBeats = "apple beats";
|
||||
const char* const AiffAudioFormat::appleDenominator = "apple denominator";
|
||||
const char* const AiffAudioFormat::appleNumerator = "apple numerator";
|
||||
const char* const AiffAudioFormat::appleTag = "apple tag";
|
||||
const char* const AiffAudioFormat::appleKey = "apple key";
|
||||
|
||||
//==============================================================================
|
||||
namespace AiffFileHelpers
|
||||
{
|
||||
inline int chunkName (const char* name) noexcept { return (int) ByteOrder::littleEndianInt (name); }
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma pack (push, 1)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
struct InstChunk
|
||||
{
|
||||
struct Loop
|
||||
{
|
||||
uint16 type; // these are different in AIFF and WAV
|
||||
uint16 startIdentifier;
|
||||
uint16 endIdentifier;
|
||||
} JUCE_PACKED;
|
||||
|
||||
int8 baseNote;
|
||||
int8 detune;
|
||||
int8 lowNote;
|
||||
int8 highNote;
|
||||
int8 lowVelocity;
|
||||
int8 highVelocity;
|
||||
int16 gain;
|
||||
Loop sustainLoop;
|
||||
Loop releaseLoop;
|
||||
|
||||
void copyTo (StringPairArray& values) const
|
||||
{
|
||||
values.set ("MidiUnityNote", String (baseNote));
|
||||
values.set ("Detune", String (detune));
|
||||
|
||||
values.set ("LowNote", String (lowNote));
|
||||
values.set ("HighNote", String (highNote));
|
||||
values.set ("LowVelocity", String (lowVelocity));
|
||||
values.set ("HighVelocity", String (highVelocity));
|
||||
|
||||
values.set ("Gain", String ((int16) ByteOrder::swapIfLittleEndian ((uint16) gain)));
|
||||
|
||||
values.set ("NumSampleLoops", String (2)); // always 2 with AIFF, WAV can have more
|
||||
values.set ("Loop0Type", String (ByteOrder::swapIfLittleEndian (sustainLoop.type)));
|
||||
values.set ("Loop0StartIdentifier", String (ByteOrder::swapIfLittleEndian (sustainLoop.startIdentifier)));
|
||||
values.set ("Loop0EndIdentifier", String (ByteOrder::swapIfLittleEndian (sustainLoop.endIdentifier)));
|
||||
values.set ("Loop1Type", String (ByteOrder::swapIfLittleEndian (releaseLoop.type)));
|
||||
values.set ("Loop1StartIdentifier", String (ByteOrder::swapIfLittleEndian (releaseLoop.startIdentifier)));
|
||||
values.set ("Loop1EndIdentifier", String (ByteOrder::swapIfLittleEndian (releaseLoop.endIdentifier)));
|
||||
}
|
||||
|
||||
static uint16 getValue16 (const StringPairArray& values, const char* name, const char* def)
|
||||
{
|
||||
return ByteOrder::swapIfLittleEndian ((uint16) values.getValue (name, def).getIntValue());
|
||||
}
|
||||
|
||||
static int8 getValue8 (const StringPairArray& values, const char* name, const char* def)
|
||||
{
|
||||
return (int8) values.getValue (name, def).getIntValue();
|
||||
}
|
||||
|
||||
static void create (MemoryBlock& block, const StringPairArray& values)
|
||||
{
|
||||
if (values.getAllKeys().contains ("MidiUnityNote", true))
|
||||
{
|
||||
block.setSize ((sizeof (InstChunk) + 3) & ~(size_t) 3, true);
|
||||
InstChunk& inst = *static_cast<InstChunk*> (block.getData());
|
||||
|
||||
inst.baseNote = getValue8 (values, "MidiUnityNote", "60");
|
||||
inst.detune = getValue8 (values, "Detune", "0");
|
||||
inst.lowNote = getValue8 (values, "LowNote", "0");
|
||||
inst.highNote = getValue8 (values, "HighNote", "127");
|
||||
inst.lowVelocity = getValue8 (values, "LowVelocity", "1");
|
||||
inst.highVelocity = getValue8 (values, "HighVelocity", "127");
|
||||
inst.gain = (int16) getValue16 (values, "Gain", "0");
|
||||
|
||||
inst.sustainLoop.type = getValue16 (values, "Loop0Type", "0");
|
||||
inst.sustainLoop.startIdentifier = getValue16 (values, "Loop0StartIdentifier", "0");
|
||||
inst.sustainLoop.endIdentifier = getValue16 (values, "Loop0EndIdentifier", "0");
|
||||
inst.releaseLoop.type = getValue16 (values, "Loop1Type", "0");
|
||||
inst.releaseLoop.startIdentifier = getValue16 (values, "Loop1StartIdentifier", "0");
|
||||
inst.releaseLoop.endIdentifier = getValue16 (values, "Loop1EndIdentifier", "0");
|
||||
}
|
||||
}
|
||||
|
||||
} JUCE_PACKED;
|
||||
|
||||
//==============================================================================
|
||||
struct BASCChunk
|
||||
{
|
||||
enum Key
|
||||
{
|
||||
minor = 1,
|
||||
major = 2,
|
||||
neither = 3,
|
||||
both = 4
|
||||
};
|
||||
|
||||
BASCChunk (InputStream& input)
|
||||
{
|
||||
zerostruct (*this);
|
||||
|
||||
flags = (uint32) input.readIntBigEndian();
|
||||
numBeats = (uint32) input.readIntBigEndian();
|
||||
rootNote = (uint16) input.readShortBigEndian();
|
||||
key = (uint16) input.readShortBigEndian();
|
||||
timeSigNum = (uint16) input.readShortBigEndian();
|
||||
timeSigDen = (uint16) input.readShortBigEndian();
|
||||
oneShot = (uint16) input.readShortBigEndian();
|
||||
input.read (unknown, sizeof (unknown));
|
||||
}
|
||||
|
||||
void addToMetadata (StringPairArray& metadata) const
|
||||
{
|
||||
const bool rootNoteSet = rootNote != 0;
|
||||
|
||||
setBoolFlag (metadata, AiffAudioFormat::appleOneShot, oneShot == 2);
|
||||
setBoolFlag (metadata, AiffAudioFormat::appleRootSet, rootNoteSet);
|
||||
|
||||
if (rootNoteSet)
|
||||
metadata.set (AiffAudioFormat::appleRootNote, String (rootNote));
|
||||
|
||||
metadata.set (AiffAudioFormat::appleBeats, String (numBeats));
|
||||
metadata.set (AiffAudioFormat::appleDenominator, String (timeSigDen));
|
||||
metadata.set (AiffAudioFormat::appleNumerator, String (timeSigNum));
|
||||
|
||||
const char* keyString = nullptr;
|
||||
|
||||
switch (key)
|
||||
{
|
||||
case minor: keyString = "major"; break;
|
||||
case major: keyString = "major"; break;
|
||||
case neither: keyString = "neither"; break;
|
||||
case both: keyString = "both"; break;
|
||||
}
|
||||
|
||||
if (keyString != nullptr)
|
||||
metadata.set (AiffAudioFormat::appleKey, keyString);
|
||||
}
|
||||
|
||||
void setBoolFlag (StringPairArray& values, const char* name, bool shouldBeSet) const
|
||||
{
|
||||
values.set (name, shouldBeSet ? "1" : "0");
|
||||
}
|
||||
|
||||
uint32 flags;
|
||||
uint32 numBeats;
|
||||
uint16 rootNote;
|
||||
uint16 key;
|
||||
uint16 timeSigNum;
|
||||
uint16 timeSigDen;
|
||||
uint16 oneShot;
|
||||
uint8 unknown[66];
|
||||
} JUCE_PACKED;
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma pack (pop)
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
static String readCATEChunk (InputStream& input, const uint32 length)
|
||||
{
|
||||
MemoryBlock mb;
|
||||
input.skipNextBytes (4);
|
||||
input.readIntoMemoryBlock (mb, (ssize_t) length - 4);
|
||||
|
||||
static const char* appleGenres[] =
|
||||
{
|
||||
"Rock/Blues",
|
||||
"Electronic/Dance",
|
||||
"Jazz",
|
||||
"Urban",
|
||||
"World/Ethnic",
|
||||
"Cinematic/New Age",
|
||||
"Orchestral",
|
||||
"Country/Folk",
|
||||
"Experimental",
|
||||
"Other Genre",
|
||||
nullptr
|
||||
};
|
||||
|
||||
const StringArray genres (appleGenres);
|
||||
StringArray tagsArray;
|
||||
|
||||
int bytesLeft = (int) mb.getSize();
|
||||
const char* data = static_cast<const char*> (mb.getData());
|
||||
|
||||
while (bytesLeft > 0)
|
||||
{
|
||||
const String tag (CharPointer_UTF8 (data),
|
||||
CharPointer_UTF8 (data + bytesLeft));
|
||||
|
||||
if (tag.isNotEmpty())
|
||||
tagsArray.add (data);
|
||||
|
||||
const int numBytesInTag = genres.contains (tag) ? 118 : 50;
|
||||
data += numBytesInTag;
|
||||
bytesLeft -= numBytesInTag;
|
||||
}
|
||||
|
||||
return tagsArray.joinIntoString (";");
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
namespace MarkChunk
|
||||
{
|
||||
static bool metaDataContainsZeroIdentifiers (const StringPairArray& values)
|
||||
{
|
||||
// (zero cue identifiers are valid for WAV but not for AIFF)
|
||||
const String cueString ("Cue");
|
||||
const String noteString ("CueNote");
|
||||
const String identifierString ("Identifier");
|
||||
|
||||
const StringArray& keys = values.getAllKeys();
|
||||
|
||||
for (int i = 0; i < keys.size(); ++i)
|
||||
{
|
||||
const String key (keys[i]);
|
||||
|
||||
if (key.startsWith (noteString))
|
||||
continue; // zero identifier IS valid in a COMT chunk
|
||||
|
||||
if (key.startsWith (cueString) && key.contains (identifierString))
|
||||
{
|
||||
const int value = values.getValue (key, "-1").getIntValue();
|
||||
|
||||
if (value == 0)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void create (MemoryBlock& block, const StringPairArray& values)
|
||||
{
|
||||
const int numCues = values.getValue ("NumCuePoints", "0").getIntValue();
|
||||
|
||||
if (numCues > 0)
|
||||
{
|
||||
MemoryOutputStream out (block, false);
|
||||
|
||||
out.writeShortBigEndian ((short) numCues);
|
||||
|
||||
const int numCueLabels = values.getValue ("NumCueLabels", "0").getIntValue();
|
||||
const int idOffset = metaDataContainsZeroIdentifiers (values) ? 1 : 0; // can't have zero IDs in AIFF
|
||||
|
||||
#if JUCE_DEBUG
|
||||
Array<int> identifiers;
|
||||
#endif
|
||||
|
||||
for (int i = 0; i < numCues; ++i)
|
||||
{
|
||||
const String prefixCue ("Cue" + String (i));
|
||||
const int identifier = idOffset + values.getValue (prefixCue + "Identifier", "1").getIntValue();
|
||||
|
||||
#if JUCE_DEBUG
|
||||
jassert (! identifiers.contains (identifier));
|
||||
identifiers.add (identifier);
|
||||
#endif
|
||||
|
||||
const int offset = values.getValue (prefixCue + "Offset", "0").getIntValue();
|
||||
String label ("CueLabel" + String (i));
|
||||
|
||||
for (int labelIndex = 0; labelIndex < numCueLabels; ++labelIndex)
|
||||
{
|
||||
const String prefixLabel ("CueLabel" + String (labelIndex));
|
||||
const int labelIdentifier = idOffset + values.getValue (prefixLabel + "Identifier", "1").getIntValue();
|
||||
|
||||
if (labelIdentifier == identifier)
|
||||
{
|
||||
label = values.getValue (prefixLabel + "Text", label);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
out.writeShortBigEndian ((short) identifier);
|
||||
out.writeIntBigEndian (offset);
|
||||
|
||||
const size_t labelLength = jmin ((size_t) 254, label.getNumBytesAsUTF8()); // seems to need null terminator even though it's a pstring
|
||||
out.writeByte ((char) labelLength + 1);
|
||||
out.write (label.toUTF8(), labelLength);
|
||||
out.writeByte (0);
|
||||
}
|
||||
|
||||
if ((out.getDataSize() & 1) != 0)
|
||||
out.writeByte (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
namespace COMTChunk
|
||||
{
|
||||
static void create (MemoryBlock& block, const StringPairArray& values)
|
||||
{
|
||||
const int numNotes = values.getValue ("NumCueNotes", "0").getIntValue();
|
||||
|
||||
if (numNotes > 0)
|
||||
{
|
||||
MemoryOutputStream out (block, false);
|
||||
out.writeShortBigEndian ((short) numNotes);
|
||||
|
||||
for (int i = 0; i < numNotes; ++i)
|
||||
{
|
||||
const String prefix ("CueNote" + String (i));
|
||||
|
||||
out.writeIntBigEndian (values.getValue (prefix + "TimeStamp", "0").getIntValue());
|
||||
out.writeShortBigEndian ((short) values.getValue (prefix + "Identifier", "0").getIntValue());
|
||||
|
||||
const String comment (values.getValue (prefix + "Text", String()));
|
||||
|
||||
const size_t commentLength = jmin (comment.getNumBytesAsUTF8(), (size_t) 65534);
|
||||
out.writeShortBigEndian ((short) commentLength + 1);
|
||||
out.write (comment.toUTF8(), commentLength);
|
||||
out.writeByte (0);
|
||||
|
||||
if ((out.getDataSize() & 1) != 0)
|
||||
out.writeByte (0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
class AiffAudioFormatReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
AiffAudioFormatReader (InputStream* in)
|
||||
: AudioFormatReader (in, aiffFormatName)
|
||||
{
|
||||
using namespace AiffFileHelpers;
|
||||
|
||||
if (input->readInt() == chunkName ("FORM"))
|
||||
{
|
||||
const int len = input->readIntBigEndian();
|
||||
const int64 end = input->getPosition() + len;
|
||||
|
||||
const int nextType = input->readInt();
|
||||
if (nextType == chunkName ("AIFF") || nextType == chunkName ("AIFC"))
|
||||
{
|
||||
bool hasGotVer = false;
|
||||
bool hasGotData = false;
|
||||
bool hasGotType = false;
|
||||
|
||||
while (input->getPosition() < end)
|
||||
{
|
||||
const int type = input->readInt();
|
||||
const uint32 length = (uint32) input->readIntBigEndian();
|
||||
const int64 chunkEnd = input->getPosition() + length;
|
||||
|
||||
if (type == chunkName ("FVER"))
|
||||
{
|
||||
hasGotVer = true;
|
||||
|
||||
const int ver = input->readIntBigEndian();
|
||||
if (ver != 0 && ver != (int) 0xa2805140)
|
||||
break;
|
||||
}
|
||||
else if (type == chunkName ("COMM"))
|
||||
{
|
||||
hasGotType = true;
|
||||
|
||||
numChannels = (unsigned int) input->readShortBigEndian();
|
||||
lengthInSamples = input->readIntBigEndian();
|
||||
bitsPerSample = (unsigned int) input->readShortBigEndian();
|
||||
bytesPerFrame = (int) ((numChannels * bitsPerSample) >> 3);
|
||||
|
||||
unsigned char sampleRateBytes[10];
|
||||
input->read (sampleRateBytes, 10);
|
||||
const int byte0 = sampleRateBytes[0];
|
||||
|
||||
if ((byte0 & 0x80) != 0
|
||||
|| byte0 <= 0x3F || byte0 > 0x40
|
||||
|| (byte0 == 0x40 && sampleRateBytes[1] > 0x1C))
|
||||
break;
|
||||
|
||||
unsigned int sampRate = ByteOrder::bigEndianInt (sampleRateBytes + 2);
|
||||
sampRate >>= (16414 - ByteOrder::bigEndianShort (sampleRateBytes));
|
||||
sampleRate = (int) sampRate;
|
||||
|
||||
if (length <= 18)
|
||||
{
|
||||
// some types don't have a chunk large enough to include a compression
|
||||
// type, so assume it's just big-endian pcm
|
||||
littleEndian = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
const int compType = input->readInt();
|
||||
|
||||
if (compType == chunkName ("NONE") || compType == chunkName ("twos"))
|
||||
{
|
||||
littleEndian = false;
|
||||
}
|
||||
else if (compType == chunkName ("sowt"))
|
||||
{
|
||||
littleEndian = true;
|
||||
}
|
||||
else if (compType == chunkName ("fl32") || compType == chunkName ("FL32"))
|
||||
{
|
||||
littleEndian = false;
|
||||
usesFloatingPointData = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
sampleRate = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (type == chunkName ("SSND"))
|
||||
{
|
||||
hasGotData = true;
|
||||
|
||||
const int offset = input->readIntBigEndian();
|
||||
dataChunkStart = input->getPosition() + 4 + offset;
|
||||
lengthInSamples = (bytesPerFrame > 0) ? jmin (lengthInSamples, ((int64) length) / (int64) bytesPerFrame) : 0;
|
||||
}
|
||||
else if (type == chunkName ("MARK"))
|
||||
{
|
||||
const uint16 numCues = (uint16) input->readShortBigEndian();
|
||||
|
||||
// these two are always the same for AIFF-read files
|
||||
metadataValues.set ("NumCuePoints", String (numCues));
|
||||
metadataValues.set ("NumCueLabels", String (numCues));
|
||||
|
||||
for (uint16 i = 0; i < numCues; ++i)
|
||||
{
|
||||
uint16 identifier = (uint16) input->readShortBigEndian();
|
||||
uint32 offset = (uint32) input->readIntBigEndian();
|
||||
uint8 stringLength = (uint8) input->readByte();
|
||||
MemoryBlock textBlock;
|
||||
input->readIntoMemoryBlock (textBlock, stringLength);
|
||||
|
||||
// if the stringLength is even then read one more byte as the
|
||||
// string needs to be an even number of bytes INCLUDING the
|
||||
// leading length character in the pascal string
|
||||
if ((stringLength & 1) == 0)
|
||||
input->readByte();
|
||||
|
||||
const String prefixCue ("Cue" + String (i));
|
||||
metadataValues.set (prefixCue + "Identifier", String (identifier));
|
||||
metadataValues.set (prefixCue + "Offset", String (offset));
|
||||
|
||||
const String prefixLabel ("CueLabel" + String (i));
|
||||
metadataValues.set (prefixLabel + "Identifier", String (identifier));
|
||||
metadataValues.set (prefixLabel + "Text", textBlock.toString());
|
||||
}
|
||||
}
|
||||
else if (type == chunkName ("COMT"))
|
||||
{
|
||||
const uint16 numNotes = (uint16) input->readShortBigEndian();
|
||||
metadataValues.set ("NumCueNotes", String (numNotes));
|
||||
|
||||
for (uint16 i = 0; i < numNotes; ++i)
|
||||
{
|
||||
uint32 timestamp = (uint32) input->readIntBigEndian();
|
||||
uint16 identifier = (uint16) input->readShortBigEndian(); // may be zero in this case
|
||||
uint16 stringLength = (uint16) input->readShortBigEndian();
|
||||
|
||||
MemoryBlock textBlock;
|
||||
input->readIntoMemoryBlock (textBlock, stringLength + (stringLength & 1));
|
||||
|
||||
const String prefix ("CueNote" + String (i));
|
||||
metadataValues.set (prefix + "TimeStamp", String (timestamp));
|
||||
metadataValues.set (prefix + "Identifier", String (identifier));
|
||||
metadataValues.set (prefix + "Text", textBlock.toString());
|
||||
}
|
||||
}
|
||||
else if (type == chunkName ("INST"))
|
||||
{
|
||||
HeapBlock <InstChunk> inst;
|
||||
inst.calloc (jmax ((size_t) length + 1, sizeof (InstChunk)), 1);
|
||||
input->read (inst, (int) length);
|
||||
inst->copyTo (metadataValues);
|
||||
}
|
||||
else if (type == chunkName ("basc"))
|
||||
{
|
||||
AiffFileHelpers::BASCChunk (*input).addToMetadata (metadataValues);
|
||||
}
|
||||
else if (type == chunkName ("cate"))
|
||||
{
|
||||
metadataValues.set (AiffAudioFormat::appleTag,
|
||||
AiffFileHelpers::readCATEChunk (*input, length));;
|
||||
}
|
||||
else if ((hasGotVer && hasGotData && hasGotType)
|
||||
|| chunkEnd < input->getPosition()
|
||||
|| input->isExhausted())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
input->setPosition (chunkEnd + (chunkEnd & 1)); // (chunks should be aligned to an even byte address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (metadataValues.size() > 0)
|
||||
metadataValues.set ("MetaDataSource", "AIFF");
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
|
||||
startSampleInFile, numSamples, lengthInSamples);
|
||||
|
||||
if (numSamples <= 0)
|
||||
return true;
|
||||
|
||||
input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame);
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3)
|
||||
char tempBuffer [tempBufSize];
|
||||
|
||||
const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples);
|
||||
const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame);
|
||||
|
||||
if (bytesRead < numThisTime * bytesPerFrame)
|
||||
{
|
||||
jassert (bytesRead >= 0);
|
||||
zeromem (tempBuffer + bytesRead, (size_t) (numThisTime * bytesPerFrame - bytesRead));
|
||||
}
|
||||
|
||||
if (littleEndian)
|
||||
copySampleData<AudioData::LittleEndian> (bitsPerSample, usesFloatingPointData,
|
||||
destSamples, startOffsetInDestBuffer, numDestChannels,
|
||||
tempBuffer, (int) numChannels, numThisTime);
|
||||
else
|
||||
copySampleData<AudioData::BigEndian> (bitsPerSample, usesFloatingPointData,
|
||||
destSamples, startOffsetInDestBuffer, numDestChannels,
|
||||
tempBuffer, (int) numChannels, numThisTime);
|
||||
|
||||
startOffsetInDestBuffer += numThisTime;
|
||||
numSamples -= numThisTime;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename Endianness>
|
||||
static void copySampleData (unsigned int bitsPerSample, const bool usesFloatingPointData,
|
||||
int* const* destSamples, int startOffsetInDestBuffer, int numDestChannels,
|
||||
const void* sourceData, int numChannels, int numSamples) noexcept
|
||||
{
|
||||
switch (bitsPerSample)
|
||||
{
|
||||
case 8: ReadHelper<AudioData::Int32, AudioData::Int8, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); break;
|
||||
case 16: ReadHelper<AudioData::Int32, AudioData::Int16, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); break;
|
||||
case 24: ReadHelper<AudioData::Int32, AudioData::Int24, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); break;
|
||||
case 32: if (usesFloatingPointData) ReadHelper<AudioData::Float32, AudioData::Float32, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples);
|
||||
else ReadHelper<AudioData::Int32, AudioData::Int32, Endianness>::read (destSamples, startOffsetInDestBuffer, numDestChannels, sourceData, numChannels, numSamples); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
|
||||
int bytesPerFrame;
|
||||
int64 dataChunkStart;
|
||||
bool littleEndian;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AiffAudioFormatReader)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class AiffAudioFormatWriter : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
AiffAudioFormatWriter (OutputStream* out, double rate,
|
||||
unsigned int numChans, unsigned int bits,
|
||||
const StringPairArray& metadataValues)
|
||||
: AudioFormatWriter (out, aiffFormatName, rate, numChans, bits),
|
||||
lengthInSamples (0),
|
||||
bytesWritten (0),
|
||||
writeFailed (false)
|
||||
{
|
||||
using namespace AiffFileHelpers;
|
||||
|
||||
if (metadataValues.size() > 0)
|
||||
{
|
||||
// The meta data should have been santised for the AIFF format.
|
||||
// If it was originally sourced from a WAV file the MetaDataSource
|
||||
// key should be removed (or set to "AIFF") once this has been done
|
||||
jassert (metadataValues.getValue ("MetaDataSource", "None") != "WAV");
|
||||
|
||||
MarkChunk::create (markChunk, metadataValues);
|
||||
COMTChunk::create (comtChunk, metadataValues);
|
||||
InstChunk::create (instChunk, metadataValues);
|
||||
}
|
||||
|
||||
headerPosition = out->getPosition();
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
~AiffAudioFormatWriter()
|
||||
{
|
||||
if ((bytesWritten & 1) != 0)
|
||||
output->writeByte (0);
|
||||
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (const int** data, int numSamples) override
|
||||
{
|
||||
jassert (data != nullptr && *data != nullptr); // the input must contain at least one channel!
|
||||
|
||||
if (writeFailed)
|
||||
return false;
|
||||
|
||||
const size_t bytes = (size_t) numSamples * numChannels * bitsPerSample / 8;
|
||||
tempBlock.ensureSize ((size_t) bytes, false);
|
||||
|
||||
switch (bitsPerSample)
|
||||
{
|
||||
case 8: WriteHelper<AudioData::Int8, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (int) numChannels, data, numSamples); break;
|
||||
case 16: WriteHelper<AudioData::Int16, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (int) numChannels, data, numSamples); break;
|
||||
case 24: WriteHelper<AudioData::Int24, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (int) numChannels, data, numSamples); break;
|
||||
case 32: WriteHelper<AudioData::Int32, AudioData::Int32, AudioData::BigEndian>::write (tempBlock.getData(), (int) numChannels, data, numSamples); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
|
||||
if (bytesWritten + bytes >= (size_t) 0xfff00000
|
||||
|| ! output->write (tempBlock.getData(), bytes))
|
||||
{
|
||||
// failed to write to disk, so let's try writing the header.
|
||||
// If it's just run out of disk space, then if it does manage
|
||||
// to write the header, we'll still have a useable file..
|
||||
writeHeader();
|
||||
writeFailed = true;
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
bytesWritten += bytes;
|
||||
lengthInSamples += (uint64) numSamples;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
MemoryBlock tempBlock, markChunk, comtChunk, instChunk;
|
||||
uint64 lengthInSamples, bytesWritten;
|
||||
int64 headerPosition;
|
||||
bool writeFailed;
|
||||
|
||||
void writeHeader()
|
||||
{
|
||||
using namespace AiffFileHelpers;
|
||||
|
||||
const bool couldSeekOk = output->setPosition (headerPosition);
|
||||
(void) couldSeekOk;
|
||||
|
||||
// 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 (couldSeekOk);
|
||||
|
||||
const int headerLen = (int) (54 + (markChunk.getSize() > 0 ? markChunk.getSize() + 8 : 0)
|
||||
+ (comtChunk.getSize() > 0 ? comtChunk.getSize() + 8 : 0)
|
||||
+ (instChunk.getSize() > 0 ? instChunk.getSize() + 8 : 0));
|
||||
int audioBytes = (int) (lengthInSamples * ((bitsPerSample * numChannels) / 8));
|
||||
audioBytes += (audioBytes & 1);
|
||||
|
||||
output->writeInt (chunkName ("FORM"));
|
||||
output->writeIntBigEndian (headerLen + audioBytes - 8);
|
||||
output->writeInt (chunkName ("AIFF"));
|
||||
output->writeInt (chunkName ("COMM"));
|
||||
output->writeIntBigEndian (18);
|
||||
output->writeShortBigEndian ((short) numChannels);
|
||||
output->writeIntBigEndian ((int) lengthInSamples);
|
||||
output->writeShortBigEndian ((short) bitsPerSample);
|
||||
|
||||
uint8 sampleRateBytes[10] = { 0 };
|
||||
|
||||
if (sampleRate <= 1)
|
||||
{
|
||||
sampleRateBytes[0] = 0x3f;
|
||||
sampleRateBytes[1] = 0xff;
|
||||
sampleRateBytes[2] = 0x80;
|
||||
}
|
||||
else
|
||||
{
|
||||
int mask = 0x40000000;
|
||||
sampleRateBytes[0] = 0x40;
|
||||
|
||||
if (sampleRate >= mask)
|
||||
{
|
||||
jassertfalse;
|
||||
sampleRateBytes[1] = 0x1d;
|
||||
}
|
||||
else
|
||||
{
|
||||
int n = (int) sampleRate;
|
||||
|
||||
int i;
|
||||
for (i = 0; i <= 32 ; ++i)
|
||||
{
|
||||
if ((n & mask) != 0)
|
||||
break;
|
||||
|
||||
mask >>= 1;
|
||||
}
|
||||
|
||||
n = n << (i + 1);
|
||||
|
||||
sampleRateBytes[1] = (uint8) (29 - i);
|
||||
sampleRateBytes[2] = (uint8) ((n >> 24) & 0xff);
|
||||
sampleRateBytes[3] = (uint8) ((n >> 16) & 0xff);
|
||||
sampleRateBytes[4] = (uint8) ((n >> 8) & 0xff);
|
||||
sampleRateBytes[5] = (uint8) (n & 0xff);
|
||||
}
|
||||
}
|
||||
|
||||
output->write (sampleRateBytes, 10);
|
||||
|
||||
if (markChunk.getSize() > 0)
|
||||
{
|
||||
output->writeInt (chunkName ("MARK"));
|
||||
output->writeIntBigEndian ((int) markChunk.getSize());
|
||||
*output << markChunk;
|
||||
}
|
||||
|
||||
if (comtChunk.getSize() > 0)
|
||||
{
|
||||
output->writeInt (chunkName ("COMT"));
|
||||
output->writeIntBigEndian ((int) comtChunk.getSize());
|
||||
*output << comtChunk;
|
||||
}
|
||||
|
||||
if (instChunk.getSize() > 0)
|
||||
{
|
||||
output->writeInt (chunkName ("INST"));
|
||||
output->writeIntBigEndian ((int) instChunk.getSize());
|
||||
*output << instChunk;
|
||||
}
|
||||
|
||||
output->writeInt (chunkName ("SSND"));
|
||||
output->writeIntBigEndian (audioBytes + 8);
|
||||
output->writeInt (0);
|
||||
output->writeInt (0);
|
||||
|
||||
jassert (output->getPosition() == headerLen);
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AiffAudioFormatWriter)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class MemoryMappedAiffReader : public MemoryMappedAudioFormatReader
|
||||
{
|
||||
public:
|
||||
MemoryMappedAiffReader (const File& f, const AiffAudioFormatReader& reader)
|
||||
: MemoryMappedAudioFormatReader (f, reader, reader.dataChunkStart,
|
||||
reader.bytesPerFrame * reader.lengthInSamples, reader.bytesPerFrame),
|
||||
littleEndian (reader.littleEndian)
|
||||
{
|
||||
}
|
||||
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,
|
||||
startSampleInFile, numSamples, lengthInSamples);
|
||||
|
||||
if (map == nullptr || ! mappedSection.contains (Range<int64> (startSampleInFile, startSampleInFile + numSamples)))
|
||||
{
|
||||
jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (littleEndian)
|
||||
AiffAudioFormatReader::copySampleData<AudioData::LittleEndian>
|
||||
(bitsPerSample, usesFloatingPointData, destSamples, startOffsetInDestBuffer,
|
||||
numDestChannels, sampleToPointer (startSampleInFile), (int) numChannels, numSamples);
|
||||
else
|
||||
AiffAudioFormatReader::copySampleData<AudioData::BigEndian>
|
||||
(bitsPerSample, usesFloatingPointData, destSamples, startOffsetInDestBuffer,
|
||||
numDestChannels, sampleToPointer (startSampleInFile), (int) numChannels, numSamples);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void readMaxLevels (int64 startSampleInFile, int64 numSamples,
|
||||
float& min0, float& max0, float& min1, float& max1)
|
||||
{
|
||||
if (numSamples <= 0)
|
||||
{
|
||||
min0 = max0 = min1 = max1 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
if (map == nullptr || ! mappedSection.contains (Range<int64> (startSampleInFile, startSampleInFile + numSamples)))
|
||||
{
|
||||
jassertfalse; // you must make sure that the window contains all the samples you're going to attempt to read.
|
||||
|
||||
min0 = max0 = min1 = max1 = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
switch (bitsPerSample)
|
||||
{
|
||||
case 8: scanMinAndMax<AudioData::UInt8> (startSampleInFile, numSamples, min0, max0, min1, max1); break;
|
||||
case 16: scanMinAndMax<AudioData::Int16> (startSampleInFile, numSamples, min0, max0, min1, max1); break;
|
||||
case 24: scanMinAndMax<AudioData::Int24> (startSampleInFile, numSamples, min0, max0, min1, max1); break;
|
||||
case 32: if (usesFloatingPointData) scanMinAndMax<AudioData::Float32> (startSampleInFile, numSamples, min0, max0, min1, max1);
|
||||
else scanMinAndMax<AudioData::Int32> (startSampleInFile, numSamples, min0, max0, min1, max1); break;
|
||||
default: jassertfalse; break;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
const bool littleEndian;
|
||||
|
||||
template <typename SampleType>
|
||||
void scanMinAndMax (int64 startSampleInFile, int64 numSamples,
|
||||
float& min0, float& max0, float& min1, float& max1) const noexcept
|
||||
{
|
||||
scanMinAndMax2<SampleType> (0, startSampleInFile, numSamples, min0, max0);
|
||||
|
||||
if (numChannels > 1)
|
||||
scanMinAndMax2<SampleType> (1, startSampleInFile, numSamples, min1, max1);
|
||||
else
|
||||
min1 = max1 = 0;
|
||||
}
|
||||
|
||||
template <typename SampleType>
|
||||
void scanMinAndMax2 (int channel, int64 startSampleInFile, int64 numSamples, float& mn, float& mx) const noexcept
|
||||
{
|
||||
if (littleEndian)
|
||||
scanMinAndMaxInterleaved<SampleType, AudioData::LittleEndian> (channel, startSampleInFile, numSamples, mn, mx);
|
||||
else
|
||||
scanMinAndMaxInterleaved<SampleType, AudioData::BigEndian> (channel, startSampleInFile, numSamples, mn, mx);
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MemoryMappedAiffReader)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
AiffAudioFormat::AiffAudioFormat() : AudioFormat (aiffFormatName, ".aiff .aif")
|
||||
{
|
||||
}
|
||||
|
||||
AiffAudioFormat::~AiffAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
Array<int> AiffAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
|
||||
return Array<int> (rates);
|
||||
}
|
||||
|
||||
Array<int> AiffAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 8, 16, 24, 0 };
|
||||
return Array<int> (depths);
|
||||
}
|
||||
|
||||
bool AiffAudioFormat::canDoStereo() { return true; }
|
||||
bool AiffAudioFormat::canDoMono() { return true; }
|
||||
|
||||
#if JUCE_MAC
|
||||
bool AiffAudioFormat::canHandleFile (const File& f)
|
||||
{
|
||||
if (AudioFormat::canHandleFile (f))
|
||||
return true;
|
||||
|
||||
const OSType type = f.getMacOSType();
|
||||
|
||||
// (NB: written as hex to avoid four-char-constant warnings)
|
||||
return type == 0x41494646 /* AIFF */ || type == 0x41494643 /* AIFC */
|
||||
|| type == 0x61696666 /* aiff */ || type == 0x61696663 /* aifc */;
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioFormatReader* AiffAudioFormat::createReaderFor (InputStream* sourceStream, const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
ScopedPointer <AiffAudioFormatReader> w (new AiffAudioFormatReader (sourceStream));
|
||||
|
||||
if (w->sampleRate > 0 && w->numChannels > 0)
|
||||
return w.release();
|
||||
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
w->input = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
MemoryMappedAudioFormatReader* AiffAudioFormat::createMemoryMappedReader (const File& file)
|
||||
{
|
||||
if (FileInputStream* fin = file.createInputStream())
|
||||
{
|
||||
AiffAudioFormatReader reader (fin);
|
||||
|
||||
if (reader.lengthInSamples > 0)
|
||||
return new MemoryMappedAiffReader (file, reader);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* AiffAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
if (getPossibleBitDepths().contains (bitsPerSample))
|
||||
return new AiffAudioFormatWriter (out, sampleRate, numberOfChannels, (unsigned int) bitsPerSample, metadataValues);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and Writes AIFF format audio files.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API AiffAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an format object. */
|
||||
AiffAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~AiffAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
/** 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;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(AiffAudioFormat)
|
||||
};
|
||||
@@ -0,0 +1,528 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_MAC || JUCE_IOS
|
||||
|
||||
//==============================================================================
|
||||
namespace
|
||||
{
|
||||
const char* const coreAudioFormatName = "CoreAudio supported file";
|
||||
|
||||
StringArray findFileExtensionsForCoreAudioCodecs()
|
||||
{
|
||||
StringArray extensionsArray;
|
||||
CFArrayRef extensions = nullptr;
|
||||
UInt32 sizeOfArray = sizeof (extensions);
|
||||
|
||||
if (AudioFileGetGlobalInfo (kAudioFileGlobalInfo_AllExtensions, 0, 0, &sizeOfArray, &extensions) == noErr)
|
||||
{
|
||||
const CFIndex numValues = CFArrayGetCount (extensions);
|
||||
|
||||
for (CFIndex i = 0; i < numValues; ++i)
|
||||
extensionsArray.add ("." + String::fromCFString ((CFStringRef) CFArrayGetValueAtIndex (extensions, i)));
|
||||
|
||||
CFRelease (extensions);
|
||||
}
|
||||
|
||||
return extensionsArray;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
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;
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
struct UserDefinedChunk
|
||||
{
|
||||
UserDefinedChunk (InputStream& input, int64 size)
|
||||
{
|
||||
// a user defined chunk contains 16 bytes of a UUID first
|
||||
uuid[1] = input.readInt64BigEndian();
|
||||
uuid[0] = input.readInt64BigEndian();
|
||||
|
||||
input.skipNextBytes (size - 16);
|
||||
}
|
||||
|
||||
int64 uuid[2];
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static StringPairArray parseMidiChunk (InputStream& input, int64 size)
|
||||
{
|
||||
const int64 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);
|
||||
|
||||
const int numTempoEvents = tempoEvents.getNumEvents();
|
||||
MemoryOutputStream tempoSequence;
|
||||
|
||||
for (int i = 0; i < numTempoEvents; ++i)
|
||||
{
|
||||
const double 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)
|
||||
{
|
||||
const MidiMessage& midiMessage = holder->message;
|
||||
|
||||
if (midiMessage.isTempoMetaEvent())
|
||||
{
|
||||
const double 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);
|
||||
const int 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);
|
||||
const int numKeySigEvents = keySigEvents.getNumEvents();
|
||||
|
||||
MemoryOutputStream keySigSequence;
|
||||
|
||||
for (int i = 0; i < numKeySigEvents; ++i)
|
||||
{
|
||||
const MidiMessage& message (keySigEvents.getEventPointer (i)->message);
|
||||
const int key = jlimit (0, 14, message.getKeySignatureNumberOfSharpsOrFlats() + 7);
|
||||
const 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;
|
||||
const uint32 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)
|
||||
{
|
||||
const int64 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"))
|
||||
{
|
||||
UserDefinedChunk userDefinedChunk (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.skipNextBytes (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.skipNextBytes (chunkHeader.chunkSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
input.setPosition (originalPos);
|
||||
|
||||
return isCafFile;
|
||||
}
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class CoreAudioReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
CoreAudioReader (InputStream* const inp)
|
||||
: AudioFormatReader (inp, coreAudioFormatName),
|
||||
ok (false), lastReadPosition (0)
|
||||
{
|
||||
usesFloatingPointData = true;
|
||||
bitsPerSample = 32;
|
||||
|
||||
if (input != nullptr)
|
||||
CoreAudioFormatMetatdata::read (*input, metadataValues);
|
||||
|
||||
OSStatus status = AudioFileOpenWithCallbacks (this,
|
||||
&readCallback,
|
||||
nullptr, // write needs to be null to avoid permisisions errors
|
||||
&getSizeCallback,
|
||||
nullptr, // setSize needs to be null to avoid permisisions errors
|
||||
0, // AudioFileTypeID inFileTypeHint
|
||||
&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);
|
||||
|
||||
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;
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~CoreAudioReader()
|
||||
{
|
||||
ExtAudioFileDispose (audioFileRef);
|
||||
AudioFileClose (audioFileID);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** 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)
|
||||
{
|
||||
const int numThisTime = jmin (8192, numSamples);
|
||||
const size_t numBytes = sizeof (float) * (size_t) numThisTime;
|
||||
|
||||
audioDataBlock.ensureSize (numBytes * numChannels, false);
|
||||
float* 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;
|
||||
}
|
||||
|
||||
UInt32 numFramesToRead = (UInt32) numThisTime;
|
||||
OSStatus status = ExtAudioFileRead (audioFileRef, &numFramesToRead, bufferList);
|
||||
if (status != noErr)
|
||||
return false;
|
||||
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
{
|
||||
if (destSamples[i] != nullptr)
|
||||
{
|
||||
if (i < (int) numChannels)
|
||||
memcpy (destSamples[i] + startOffsetInDestBuffer, bufferList->mBuffers[i].mData, numBytes);
|
||||
else
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer, numBytes);
|
||||
}
|
||||
}
|
||||
|
||||
startOffsetInDestBuffer += numThisTime;
|
||||
numSamples -= numThisTime;
|
||||
lastReadPosition += numThisTime;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ok;
|
||||
|
||||
private:
|
||||
AudioFileID audioFileID;
|
||||
ExtAudioFileRef audioFileRef;
|
||||
AudioStreamBasicDescription destinationAudioFormat;
|
||||
MemoryBlock audioDataBlock;
|
||||
HeapBlock<AudioBufferList> bufferList;
|
||||
int64 lastReadPosition;
|
||||
|
||||
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)
|
||||
{
|
||||
CoreAudioReader* const 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())
|
||||
{
|
||||
}
|
||||
|
||||
CoreAudioFormat::~CoreAudioFormat() {}
|
||||
|
||||
Array<int> CoreAudioFormat::getPossibleSampleRates() { return Array<int>(); }
|
||||
Array<int> CoreAudioFormat::getPossibleBitDepths() { return Array<int>(); }
|
||||
|
||||
bool CoreAudioFormat::canDoStereo() { return true; }
|
||||
bool CoreAudioFormat::canDoMono() { return true; }
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* CoreAudioFormat::createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
ScopedPointer<CoreAudioReader> r (new CoreAudioReader (sourceStream));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#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
|
||||
*/
|
||||
class JUCE_API CoreAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a format object. */
|
||||
CoreAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~CoreAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
/** 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;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioFormat)
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,556 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
namespace FlacNamespace
|
||||
{
|
||||
#if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)
|
||||
|
||||
#undef VERSION
|
||||
#define VERSION "1.2.1"
|
||||
|
||||
#define FLAC__NO_DLL 1
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (disable: 4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4312 4505 4365 4005 4334 181 111)
|
||||
#endif
|
||||
|
||||
#if JUCE_MAC
|
||||
#define FLAC__SYS_DARWIN 1
|
||||
#endif
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
#define SIZE_MAX 0xffffffff
|
||||
#endif
|
||||
|
||||
#if JUCE_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-register"
|
||||
#endif
|
||||
|
||||
#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
|
||||
|
||||
#undef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#define flac_max jmax
|
||||
#define flac_min jmin
|
||||
#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/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"
|
||||
#undef VERSION
|
||||
#else
|
||||
#include <FLAC/all.h>
|
||||
#endif
|
||||
|
||||
#if JUCE_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
}
|
||||
|
||||
#undef max
|
||||
#undef min
|
||||
|
||||
//==============================================================================
|
||||
static const char* const flacFormatName = "FLAC file";
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class FlacReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
FlacReader (InputStream* const in)
|
||||
: AudioFormatReader (in, flacFormatName),
|
||||
reservoirStart (0),
|
||||
samplesInReservoir (0),
|
||||
scanningForLength (false)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
lengthInSamples = 0;
|
||||
|
||||
decoder = FLAC__stream_decoder_new();
|
||||
|
||||
ok = FLAC__stream_decoder_init_stream (decoder,
|
||||
readCallback_, seekCallback_, tellCallback_, lengthCallback_,
|
||||
eofCallback_, writeCallback_, metadataCallback_, errorCallback_,
|
||||
this) == 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;
|
||||
const int64 tempLength = lengthInSamples;
|
||||
|
||||
FLAC__stream_decoder_reset (decoder);
|
||||
FLAC__stream_decoder_process_until_end_of_metadata (decoder);
|
||||
lengthInSamples = tempLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~FlacReader()
|
||||
{
|
||||
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);
|
||||
}
|
||||
|
||||
// returns the number of samples read
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
|
||||
if (! ok)
|
||||
return false;
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
if (startSampleInFile >= reservoirStart
|
||||
&& startSampleInFile < reservoirStart + samplesInReservoir)
|
||||
{
|
||||
const int num = (int) jmin ((int64) numSamples,
|
||||
reservoirStart + samplesInReservoir - startSampleInFile);
|
||||
|
||||
jassert (num > 0);
|
||||
|
||||
for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
memcpy (destSamples[i] + startOffsetInDestBuffer,
|
||||
reservoir.getReadPointer (i, (int) (startSampleInFile - reservoirStart)),
|
||||
sizeof (int) * (size_t) num);
|
||||
|
||||
startOffsetInDestBuffer += num;
|
||||
startSampleInFile += num;
|
||||
numSamples -= num;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startSampleInFile >= (int) lengthInSamples)
|
||||
{
|
||||
samplesInReservoir = 0;
|
||||
}
|
||||
else if (startSampleInFile < reservoirStart
|
||||
|| startSampleInFile > reservoirStart + jmax (samplesInReservoir, 511))
|
||||
{
|
||||
// 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.
|
||||
reservoirStart = (int) (startSampleInFile & ~511);
|
||||
samplesInReservoir = 0;
|
||||
FLAC__stream_decoder_seek_absolute (decoder, (FLAC__uint64) reservoirStart);
|
||||
}
|
||||
else
|
||||
{
|
||||
reservoirStart += samplesInReservoir;
|
||||
samplesInReservoir = 0;
|
||||
FLAC__stream_decoder_process_single (decoder);
|
||||
}
|
||||
|
||||
if (samplesInReservoir == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
const unsigned int bitsToShift = 32 - bitsPerSample;
|
||||
|
||||
for (int i = 0; i < (int) numChannels; ++i)
|
||||
{
|
||||
const FlacNamespace::FLAC__int32* src = buffer[i];
|
||||
|
||||
int n = i;
|
||||
while (src == 0 && n > 0)
|
||||
src = buffer [--n];
|
||||
|
||||
if (src != nullptr)
|
||||
{
|
||||
int* const dest = reinterpret_cast<int*> (reservoir.getWritePointer(i));
|
||||
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
dest[j] = src[j] << bitsToShift;
|
||||
}
|
||||
}
|
||||
|
||||
samplesInReservoir = numSamples;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static FlacNamespace::FLAC__StreamDecoderReadStatus readCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__byte buffer[], size_t* bytes, void* client_data)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
*bytes = (size_t) static_cast<const FlacReader*> (client_data)->input->read (buffer, (int) *bytes);
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderSeekStatus seekCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64 absolute_byte_offset, void* client_data)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
static_cast<const FlacReader*> (client_data)->input->setPosition ((int) absolute_byte_offset);
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderTellStatus tellCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
*absolute_byte_offset = (uint64) static_cast<const FlacReader*> (client_data)->input->getPosition();
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamDecoderLengthStatus lengthCallback_ (const FlacNamespace::FLAC__StreamDecoder*, FlacNamespace::FLAC__uint64* stream_length, void* client_data)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
*stream_length = (uint64) static_cast<const FlacReader*> (client_data)->input->getTotalLength();
|
||||
return 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)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
static_cast<FlacReader*> (client_data)->useSamples (buffer, (int) frame->header.blocksize);
|
||||
return 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;
|
||||
AudioSampleBuffer reservoir;
|
||||
int reservoirStart, samplesInReservoir;
|
||||
bool ok, scanningForLength;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacReader)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class FlacWriter : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
FlacWriter (OutputStream* const out, double rate, uint32 numChans, uint32 bits, int qualityOptionIndex)
|
||||
: AudioFormatWriter (out, flacFormatName, rate, numChans, bits)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
encoder = 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) == FLAC__STREAM_ENCODER_INIT_STATUS_OK;
|
||||
}
|
||||
|
||||
~FlacWriter()
|
||||
{
|
||||
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
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
if (! ok)
|
||||
return false;
|
||||
|
||||
HeapBlock<int*> channels;
|
||||
HeapBlock<int> temp;
|
||||
const int 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;
|
||||
|
||||
int* const destData = temp.getData() + 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.getData());
|
||||
}
|
||||
|
||||
return FLAC__stream_encoder_process (encoder, (const 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;
|
||||
const FLAC__StreamMetadata_StreamInfo& 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);
|
||||
|
||||
const bool seekOk = output->setPosition (4);
|
||||
(void) seekOk;
|
||||
|
||||
// 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)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
return static_cast<FlacWriter*> (client_data)->writeData (buffer, (int) bytes)
|
||||
? FLAC__STREAM_ENCODER_WRITE_STATUS_OK
|
||||
: FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64, void*)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static FlacNamespace::FLAC__StreamEncoderTellStatus encodeTellCallback (const FlacNamespace::FLAC__StreamEncoder*, FlacNamespace::FLAC__uint64* absolute_byte_offset, void* client_data)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
if (client_data == nullptr)
|
||||
return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
|
||||
|
||||
*absolute_byte_offset = (FLAC__uint64) static_cast<FlacWriter*> (client_data)->output->getPosition();
|
||||
return 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;
|
||||
|
||||
private:
|
||||
FlacNamespace::FLAC__StreamEncoder* encoder;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacWriter)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FlacAudioFormat::FlacAudioFormat()
|
||||
: AudioFormat (flacFormatName, ".flac")
|
||||
{
|
||||
}
|
||||
|
||||
FlacAudioFormat::~FlacAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
Array<int> FlacAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 8000, 11025, 12000, 16000, 22050, 32000, 44100, 48000,
|
||||
88200, 96000, 176400, 192000, 352800, 384000 };
|
||||
|
||||
return Array<int> (rates, numElementsInArray (rates));
|
||||
}
|
||||
|
||||
Array<int> FlacAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 16, 24 };
|
||||
|
||||
return Array<int> (depths, numElementsInArray (depths));
|
||||
}
|
||||
|
||||
bool FlacAudioFormat::canDoStereo() { return true; }
|
||||
bool FlacAudioFormat::canDoMono() { return true; }
|
||||
bool FlacAudioFormat::isCompressed() { return true; }
|
||||
|
||||
AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
ScopedPointer<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 (getPossibleBitDepths().contains (bitsPerSample))
|
||||
{
|
||||
ScopedPointer<FlacWriter> w (new FlacWriter (out, sampleRate, numberOfChannels,
|
||||
(uint32) bitsPerSample, qualityOptionIndex));
|
||||
if (w->ok)
|
||||
return w.release();
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
StringArray FlacAudioFormat::getQualityOptions()
|
||||
{
|
||||
static const char* options[] = { "0 (Fastest)", "1", "2", "3", "4", "5 (Default)","6", "7", "8 (Highest quality)", 0 };
|
||||
return StringArray (options);
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_FLAC || defined (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
|
||||
*/
|
||||
class JUCE_API FlacAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FlacAudioFormat();
|
||||
~FlacAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
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;
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (FlacAudioFormat)
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,222 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_LAME_AUDIO_FORMAT
|
||||
|
||||
class LAMEEncoderAudioFormat::Writer : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
Writer (OutputStream* destStream, const String& formatName,
|
||||
const File& appFile, int vbr, int cbr,
|
||||
double sampleRate, unsigned int numberOfChannels,
|
||||
unsigned int bitsPerSample, const StringPairArray& metadata)
|
||||
: AudioFormatWriter (destStream, formatName, sampleRate,
|
||||
numberOfChannels, bitsPerSample),
|
||||
vbrLevel (vbr), cbrBitrate (cbr),
|
||||
tempWav (".wav")
|
||||
{
|
||||
WavAudioFormat wavFormat;
|
||||
|
||||
if (FileOutputStream* out = tempWav.getFile().createOutputStream())
|
||||
{
|
||||
writer = wavFormat.createWriterFor (out, sampleRate, numChannels,
|
||||
bitsPerSample, 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)
|
||||
{
|
||||
const String value (metadata.getValue (key, String()));
|
||||
|
||||
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;
|
||||
ScopedPointer<AudioFormatWriter> writer;
|
||||
StringArray args;
|
||||
|
||||
bool runLameChildProcess (const TemporaryFile& tempMP3, const StringArray& processArgs) const
|
||||
{
|
||||
ChildProcess cp;
|
||||
|
||||
if (cp.start (processArgs))
|
||||
{
|
||||
const String childOutput (cp.readAllProcessOutput());
|
||||
DBG (childOutput); (void) 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()
|
||||
{
|
||||
const int rates[] = { 32000, 44100, 48000, 0 };
|
||||
return Array<int> (rates);
|
||||
}
|
||||
|
||||
Array<int> LAMEEncoderAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 16, 0 };
|
||||
return Array<int> (depths);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_LAME_AUDIO_FORMAT || defined (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
|
||||
*/
|
||||
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);
|
||||
|
||||
private:
|
||||
File lameApp;
|
||||
class Writer;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LAMEEncoderAudioFormat)
|
||||
};
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#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 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.
|
||||
*/
|
||||
class MP3AudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
MP3AudioFormat();
|
||||
~MP3AudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,532 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#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)
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable: 4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4305 4189 4706 4995 4365)
|
||||
#endif
|
||||
|
||||
#if JUCE_CLANG
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wconversion"
|
||||
#pragma clang diagnostic ignored "-Wshadow"
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-register"
|
||||
#endif
|
||||
|
||||
#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.2/lib/analysis.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/bitrate.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/block.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/codebook.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/envelope.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/floor0.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/floor1.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/info.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/lpc.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/lsp.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/mapping0.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/mdct.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/psy.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/registry.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/res0.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/sharedbook.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/smallft.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/synthesis.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/vorbisenc.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/vorbisfile.c"
|
||||
#include "oggvorbis/libvorbis-1.3.2/lib/window.c"
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#if JUCE_CLANG
|
||||
#pragma clang diagnostic pop
|
||||
#endif
|
||||
#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 : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
OggReader (InputStream* const inp)
|
||||
: AudioFormatReader (inp, oggFormatName),
|
||||
reservoirStart (0),
|
||||
samplesInReservoir (0)
|
||||
{
|
||||
using namespace OggVorbisNamespace;
|
||||
sampleRate = 0;
|
||||
usesFloatingPointData = true;
|
||||
|
||||
callbacks.read_func = &oggReadCallback;
|
||||
callbacks.seek_func = &oggSeekCallback;
|
||||
callbacks.close_func = &oggCloseCallback;
|
||||
callbacks.tell_func = &oggTellCallback;
|
||||
|
||||
const int err = ov_open_callbacks (input, &ovFile, 0, 0, callbacks);
|
||||
|
||||
if (err == 0)
|
||||
{
|
||||
vorbis_info* info = ov_info (&ovFile, -1);
|
||||
|
||||
vorbis_comment* const 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 = info->rate;
|
||||
|
||||
reservoir.setSize ((int) numChannels, (int) jmin (lengthInSamples, (int64) 4096));
|
||||
}
|
||||
}
|
||||
|
||||
~OggReader()
|
||||
{
|
||||
OggVorbisNamespace::ov_clear (&ovFile);
|
||||
}
|
||||
|
||||
void addMetadataItem (OggVorbisNamespace::vorbis_comment* comment, const char* name, const char* metadataName)
|
||||
{
|
||||
if (const char* value = vorbis_comment_query (comment, name, 0))
|
||||
metadataValues.set (metadataName, value);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
while (numSamples > 0)
|
||||
{
|
||||
const int numAvailable = (int) (reservoirStart + samplesInReservoir - startSampleInFile);
|
||||
|
||||
if (startSampleInFile >= reservoirStart && numAvailable > 0)
|
||||
{
|
||||
// got a few samples overlapping, so use them before seeking..
|
||||
|
||||
const int numToUse = jmin (numSamples, numAvailable);
|
||||
|
||||
for (int i = jmin (numDestChannels, reservoir.getNumChannels()); --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
memcpy (destSamples[i] + startOffsetInDestBuffer,
|
||||
reservoir.getReadPointer (i, (int) (startSampleInFile - reservoirStart)),
|
||||
sizeof (float) * (size_t) numToUse);
|
||||
|
||||
startSampleInFile += numToUse;
|
||||
numSamples -= numToUse;
|
||||
startOffsetInDestBuffer += numToUse;
|
||||
|
||||
if (numSamples == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
if (startSampleInFile < reservoirStart
|
||||
|| startSampleInFile + numSamples > reservoirStart + samplesInReservoir)
|
||||
{
|
||||
// buffer miss, so refill the reservoir
|
||||
int bitStream = 0;
|
||||
|
||||
reservoirStart = jmax (0, (int) startSampleInFile);
|
||||
samplesInReservoir = reservoir.getNumSamples();
|
||||
|
||||
if (reservoirStart != (int) OggVorbisNamespace::ov_pcm_tell (&ovFile))
|
||||
OggVorbisNamespace::ov_pcm_seek (&ovFile, reservoirStart);
|
||||
|
||||
int offset = 0;
|
||||
int numToRead = samplesInReservoir;
|
||||
|
||||
while (numToRead > 0)
|
||||
{
|
||||
float** dataIn = nullptr;
|
||||
|
||||
const long samps = OggVorbisNamespace::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], sizeof (float) * (size_t) samps);
|
||||
|
||||
numToRead -= samps;
|
||||
offset += samps;
|
||||
}
|
||||
|
||||
if (numToRead > 0)
|
||||
reservoir.clear (offset, numToRead);
|
||||
}
|
||||
}
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != nullptr)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer, sizeof (int) * (size_t) numSamples);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
InputStream* const 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;
|
||||
AudioSampleBuffer reservoir;
|
||||
int reservoirStart, samplesInReservoir;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggReader)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class OggWriter : public AudioFormatWriter
|
||||
{
|
||||
public:
|
||||
OggWriter (OutputStream* const out,
|
||||
const double sampleRate_,
|
||||
const unsigned int numChannels_,
|
||||
const unsigned int bitsPerSample_,
|
||||
const int qualityIndex,
|
||||
const StringPairArray& metadata)
|
||||
: AudioFormatWriter (out, oggFormatName, sampleRate_, numChannels_, bitsPerSample_),
|
||||
ok (false)
|
||||
{
|
||||
using namespace OggVorbisNamespace;
|
||||
|
||||
vorbis_info_init (&vi);
|
||||
|
||||
if (vorbis_encode_init_vbr (&vi, (int) numChannels_, (int) sampleRate_,
|
||||
jlimit (0.0f, 1.0f, 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());
|
||||
|
||||
ogg_packet header;
|
||||
ogg_packet header_comm;
|
||||
ogg_packet 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()
|
||||
{
|
||||
using namespace OggVorbisNamespace;
|
||||
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)
|
||||
{
|
||||
using namespace OggVorbisNamespace;
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
const double gain = 1.0 / 0x80000000u;
|
||||
float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples);
|
||||
|
||||
for (int i = (int) numChannels; --i >= 0;)
|
||||
{
|
||||
float* const dst = vorbisBuffer[i];
|
||||
const int* const src = samplesToWrite [i];
|
||||
|
||||
if (src != nullptr && dst != nullptr)
|
||||
{
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
dst[j] = (float) (src[j] * gain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeSamples (numSamples);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
void writeSamples (int numSamples)
|
||||
{
|
||||
using namespace OggVorbisNamespace;
|
||||
|
||||
vorbis_analysis_wrote (&vd, numSamples);
|
||||
|
||||
while (vorbis_analysis_blockout (&vd, &vb) == 1)
|
||||
{
|
||||
vorbis_analysis (&vb, 0);
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
const String 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()
|
||||
{
|
||||
const int rates[] = { 8000, 11025, 12000, 16000, 22050, 32000,
|
||||
44100, 48000, 88200, 96000, 176400, 192000 };
|
||||
|
||||
return Array<int> (rates, numElementsInArray (rates));
|
||||
}
|
||||
|
||||
Array<int> OggVorbisAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 32 };
|
||||
|
||||
return Array<int> (depths, numElementsInArray (depths));
|
||||
}
|
||||
|
||||
bool OggVorbisAudioFormat::canDoStereo() { return true; }
|
||||
bool OggVorbisAudioFormat::canDoMono() { return true; }
|
||||
bool OggVorbisAudioFormat::isCompressed() { return true; }
|
||||
|
||||
AudioFormatReader* OggVorbisAudioFormat::createReaderFor (InputStream* in, const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
ScopedPointer<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)
|
||||
{
|
||||
ScopedPointer <OggWriter> w (new OggWriter (out, sampleRate, numChannels,
|
||||
(unsigned int) bitsPerSample, qualityOptionIndex, metadataValues));
|
||||
|
||||
return w->ok ? w.release() : nullptr;
|
||||
}
|
||||
|
||||
StringArray OggVorbisAudioFormat::getQualityOptions()
|
||||
{
|
||||
static const char* options[] = { "64 kbps", "80 kbps", "96 kbps", "112 kbps", "128 kbps", "160 kbps",
|
||||
"192 kbps", "224 kbps", "256 kbps", "320 kbps", "500 kbps", 0 };
|
||||
return StringArray (options);
|
||||
}
|
||||
|
||||
int OggVorbisAudioFormat::estimateOggFileQuality (const File& source)
|
||||
{
|
||||
if (FileInputStream* const in = source.createInputStream())
|
||||
{
|
||||
ScopedPointer<AudioFormatReader> r (createReaderFor (in, true));
|
||||
|
||||
if (r != nullptr)
|
||||
{
|
||||
const double lengthSecs = r->lengthInSamples / r->sampleRate;
|
||||
const int approxBitsPerSecond = (int) (source.getSize() * 8 / lengthSecs);
|
||||
|
||||
const StringArray qualities (getQualityOptions());
|
||||
int bestIndex = 0;
|
||||
int bestDiff = 10000;
|
||||
|
||||
for (int i = qualities.size(); --i >= 0;)
|
||||
{
|
||||
const int diff = std::abs (qualities[i].getIntValue() - approxBitsPerSecond);
|
||||
|
||||
if (diff < bestDiff)
|
||||
{
|
||||
bestDiff = diff;
|
||||
bestIndex = i;
|
||||
}
|
||||
}
|
||||
|
||||
return bestIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_USE_OGGVORBIS || defined (DOXYGEN)
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and writes the Ogg-Vorbis audio format.
|
||||
|
||||
To compile this, you'll need to set the JUCE_USE_OGGVORBIS flag.
|
||||
|
||||
@see AudioFormat,
|
||||
*/
|
||||
class JUCE_API OggVorbisAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
OggVorbisAudioFormat();
|
||||
~OggVorbisAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
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;
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OggVorbisAudioFormat)
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_QUICKTIME && ! (JUCE_64BIT || JUCE_IOS)
|
||||
|
||||
} // (juce namespace)
|
||||
|
||||
#if ! JUCE_WINDOWS
|
||||
#define Point CarbonDummyPointName // (workaround to avoid definition of "Point" by old Carbon headers)
|
||||
#define Component CarbonDummyCompName
|
||||
#include <QuickTime/Movies.h>
|
||||
#include <QuickTime/QTML.h>
|
||||
#include <QuickTime/QuickTimeComponents.h>
|
||||
#include <QuickTime/MediaHandlers.h>
|
||||
#include <QuickTime/ImageCodec.h>
|
||||
#undef Point
|
||||
#undef Component
|
||||
#else
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (push)
|
||||
#pragma warning (disable : 4100)
|
||||
#endif
|
||||
|
||||
/* If you've got an include error here, you probably need to install the QuickTime SDK and
|
||||
add its header directory to your include path.
|
||||
|
||||
Alternatively, if you don't need any QuickTime services, just set the JUCE_QUICKTIME flag to 0.
|
||||
*/
|
||||
#undef SIZE_MAX
|
||||
#include <Movies.h>
|
||||
#include <QTML.h>
|
||||
#include <QuickTimeComponents.h>
|
||||
#include <MediaHandlers.h>
|
||||
#include <ImageCodec.h>
|
||||
#undef SIZE_MAX
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
namespace juce
|
||||
{
|
||||
|
||||
bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle);
|
||||
|
||||
static const char* const quickTimeFormatName = "QuickTime file";
|
||||
|
||||
//==============================================================================
|
||||
class QTAudioReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
QTAudioReader (InputStream* const input_, const int trackNum_)
|
||||
: AudioFormatReader (input_, quickTimeFormatName),
|
||||
ok (false),
|
||||
movie (0),
|
||||
trackNum (trackNum_),
|
||||
lastSampleRead (0),
|
||||
lastThreadId (0),
|
||||
extractor (0),
|
||||
dataHandle (0)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
bufferList.calloc (256, 1);
|
||||
|
||||
#if JUCE_WINDOWS
|
||||
if (InitializeQTML (0) != noErr)
|
||||
return;
|
||||
#endif
|
||||
|
||||
if (EnterMovies() != noErr)
|
||||
return;
|
||||
|
||||
bool opened = juce_OpenQuickTimeMovieFromStream (input_, movie, dataHandle);
|
||||
|
||||
if (! opened)
|
||||
return;
|
||||
|
||||
{
|
||||
const int numTracks = GetMovieTrackCount (movie);
|
||||
int trackCount = 0;
|
||||
|
||||
for (int i = 1; i <= numTracks; ++i)
|
||||
{
|
||||
track = GetMovieIndTrack (movie, i);
|
||||
media = GetTrackMedia (track);
|
||||
|
||||
OSType mediaType;
|
||||
GetMediaHandlerDescription (media, &mediaType, 0, 0);
|
||||
|
||||
if (mediaType == SoundMediaType
|
||||
&& trackCount++ == trackNum_)
|
||||
{
|
||||
ok = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! ok)
|
||||
return;
|
||||
|
||||
ok = false;
|
||||
|
||||
lengthInSamples = GetMediaDecodeDuration (media);
|
||||
usesFloatingPointData = false;
|
||||
|
||||
samplesPerFrame = (int) (GetMediaDecodeDuration (media) / GetMediaSampleCount (media));
|
||||
|
||||
trackUnitsPerFrame = GetMovieTimeScale (movie) * samplesPerFrame
|
||||
/ GetMediaTimeScale (media);
|
||||
|
||||
MovieAudioExtractionBegin (movie, 0, &extractor);
|
||||
|
||||
unsigned long output_layout_size;
|
||||
OSStatus err = MovieAudioExtractionGetPropertyInfo (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
|
||||
0, &output_layout_size, 0);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
HeapBlock <AudioChannelLayout> qt_audio_channel_layout;
|
||||
qt_audio_channel_layout.calloc (output_layout_size, 1);
|
||||
|
||||
MovieAudioExtractionGetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
|
||||
output_layout_size, qt_audio_channel_layout, 0);
|
||||
|
||||
qt_audio_channel_layout[0].mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
|
||||
|
||||
MovieAudioExtractionSetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
|
||||
output_layout_size,
|
||||
qt_audio_channel_layout);
|
||||
|
||||
err = MovieAudioExtractionGetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
|
||||
sizeof (inputStreamDesc),
|
||||
&inputStreamDesc, 0);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
inputStreamDesc.mFormatFlags = kAudioFormatFlagIsSignedInteger
|
||||
| kAudioFormatFlagIsPacked
|
||||
| kAudioFormatFlagsNativeEndian;
|
||||
inputStreamDesc.mBitsPerChannel = sizeof (SInt16) * 8;
|
||||
inputStreamDesc.mChannelsPerFrame = jmin ((UInt32) 2, inputStreamDesc.mChannelsPerFrame);
|
||||
inputStreamDesc.mBytesPerFrame = sizeof (SInt16) * inputStreamDesc.mChannelsPerFrame;
|
||||
inputStreamDesc.mBytesPerPacket = inputStreamDesc.mBytesPerFrame;
|
||||
|
||||
err = MovieAudioExtractionSetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioStreamBasicDescription,
|
||||
sizeof (inputStreamDesc),
|
||||
&inputStreamDesc);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
Boolean allChannelsDiscrete = false;
|
||||
err = MovieAudioExtractionSetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Movie,
|
||||
kQTMovieAudioExtractionMoviePropertyID_AllChannelsDiscrete,
|
||||
sizeof (allChannelsDiscrete),
|
||||
&allChannelsDiscrete);
|
||||
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
bufferList->mNumberBuffers = 1;
|
||||
bufferList->mBuffers[0].mNumberChannels = inputStreamDesc.mChannelsPerFrame;
|
||||
bufferList->mBuffers[0].mDataByteSize = jmax ((UInt32) 4096, (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16);
|
||||
|
||||
dataBuffer.malloc (bufferList->mBuffers[0].mDataByteSize);
|
||||
bufferList->mBuffers[0].mData = dataBuffer;
|
||||
|
||||
sampleRate = inputStreamDesc.mSampleRate;
|
||||
bitsPerSample = 16;
|
||||
numChannels = inputStreamDesc.mChannelsPerFrame;
|
||||
|
||||
detachThread();
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
~QTAudioReader()
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
checkThreadIsAttached();
|
||||
|
||||
if (dataHandle != nullptr)
|
||||
DisposeHandle (dataHandle);
|
||||
|
||||
if (extractor != nullptr)
|
||||
{
|
||||
MovieAudioExtractionEnd (extractor);
|
||||
extractor = nullptr;
|
||||
}
|
||||
|
||||
DisposeMovie (movie);
|
||||
|
||||
#if JUCE_MAC
|
||||
ExitMoviesOnThread ();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
JUCE_AUTORELEASEPOOL
|
||||
{
|
||||
checkThreadIsAttached();
|
||||
bool readOk = true;
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
if (lastSampleRead != startSampleInFile)
|
||||
{
|
||||
TimeRecord time;
|
||||
time.scale = (TimeScale) inputStreamDesc.mSampleRate;
|
||||
time.base = 0;
|
||||
time.value.hi = 0;
|
||||
time.value.lo = (UInt32) startSampleInFile;
|
||||
|
||||
OSStatus err = MovieAudioExtractionSetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Movie,
|
||||
kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
|
||||
sizeof (time), &time);
|
||||
|
||||
if (err != noErr)
|
||||
{
|
||||
readOk = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int framesToDo = jmin (numSamples, (int) (bufferList->mBuffers[0].mDataByteSize / inputStreamDesc.mBytesPerFrame));
|
||||
bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * framesToDo;
|
||||
|
||||
UInt32 outFlags = 0;
|
||||
UInt32 actualNumFrames = framesToDo;
|
||||
OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumFrames, bufferList, &outFlags);
|
||||
if (err != noErr)
|
||||
{
|
||||
readOk = false;
|
||||
break;
|
||||
}
|
||||
|
||||
lastSampleRead = startSampleInFile + actualNumFrames;
|
||||
const int samplesReceived = actualNumFrames;
|
||||
|
||||
for (int j = numDestChannels; --j >= 0;)
|
||||
{
|
||||
if (destSamples[j] != nullptr)
|
||||
{
|
||||
const short* src = ((const short*) bufferList->mBuffers[0].mData) + j;
|
||||
|
||||
for (int i = 0; i < samplesReceived; ++i)
|
||||
{
|
||||
destSamples[j][startOffsetInDestBuffer + i] = (*src << 16);
|
||||
src += numChannels;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startOffsetInDestBuffer += samplesReceived;
|
||||
startSampleInFile += samplesReceived;
|
||||
numSamples -= samplesReceived;
|
||||
|
||||
if (((outFlags & kQTMovieAudioExtractionComplete) != 0 || samplesReceived == 0) && numSamples > 0)
|
||||
{
|
||||
for (int j = numDestChannels; --j >= 0;)
|
||||
if (destSamples[j] != nullptr)
|
||||
zeromem (destSamples[j] + startOffsetInDestBuffer, sizeof (int) * numSamples);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
detachThread();
|
||||
return readOk;
|
||||
}
|
||||
}
|
||||
|
||||
bool ok;
|
||||
|
||||
private:
|
||||
Movie movie;
|
||||
Media media;
|
||||
Track track;
|
||||
const int trackNum;
|
||||
double trackUnitsPerFrame;
|
||||
int samplesPerFrame;
|
||||
int64 lastSampleRead;
|
||||
Thread::ThreadID lastThreadId;
|
||||
MovieAudioExtractionRef extractor;
|
||||
AudioStreamBasicDescription inputStreamDesc;
|
||||
HeapBlock <AudioBufferList> bufferList;
|
||||
HeapBlock <char> dataBuffer;
|
||||
Handle dataHandle;
|
||||
|
||||
//==============================================================================
|
||||
void checkThreadIsAttached()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
if (Thread::getCurrentThreadId() != lastThreadId)
|
||||
EnterMoviesOnThread (0);
|
||||
AttachMovieToCurrentThread (movie);
|
||||
#endif
|
||||
}
|
||||
|
||||
void detachThread()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
DetachMovieFromCurrentThread (movie);
|
||||
#endif
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (QTAudioReader)
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
QuickTimeAudioFormat::QuickTimeAudioFormat() : AudioFormat (quickTimeFormatName, ".mov .mp3 .mp4 .m4a")
|
||||
{
|
||||
}
|
||||
|
||||
QuickTimeAudioFormat::~QuickTimeAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
Array<int> QuickTimeAudioFormat::getPossibleSampleRates() { return Array<int>(); }
|
||||
Array<int> QuickTimeAudioFormat::getPossibleBitDepths() { return Array<int>(); }
|
||||
|
||||
bool QuickTimeAudioFormat::canDoStereo() { return true; }
|
||||
bool QuickTimeAudioFormat::canDoMono() { return true; }
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* QuickTimeAudioFormat::createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
ScopedPointer<QTAudioReader> r (new QTAudioReader (sourceStream, 0));
|
||||
|
||||
if (r->ok)
|
||||
return r.release();
|
||||
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = 0;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/,
|
||||
double /*sampleRateToUse*/,
|
||||
unsigned int /*numberOfChannels*/,
|
||||
int /*bitsPerSample*/,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
jassertfalse; // not yet implemented!
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_QUICKTIME
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Uses QuickTime to read the audio track a movie or media file.
|
||||
|
||||
As well as QuickTime movies, this should also manage to open other audio
|
||||
files that quicktime can understand, like mp3, m4a, etc.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API QuickTimeAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a format object. */
|
||||
QuickTimeAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~QuickTimeAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
Array<int> getPossibleSampleRates();
|
||||
Array<int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex);
|
||||
|
||||
|
||||
private:
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (QuickTimeAudioFormat)
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and Writes WAV format audio files.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API WavAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a format object. */
|
||||
WavAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~WavAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavDescription;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavOriginator;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavOriginatorRef;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
Date format is: yyyy-mm-dd
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavOriginationDate;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
Time format is: hh-mm-ss
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavOriginationTime;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
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;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const char* const bwavCodingHistory;
|
||||
|
||||
/** 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,
|
||||
const Time dateAndTime,
|
||||
const int64 timeReferenceSamples,
|
||||
const String& codingHistory);
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidOneShot;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidRootSet;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidStretch;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidDiskBased;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidizerFlag;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidRootNote;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidBeats;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidDenominator;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidNumerator;
|
||||
/** Metadata property name used when reading a WAV file with an acid chunk. */
|
||||
static const char* const acidTempo;
|
||||
|
||||
//==============================================================================
|
||||
/** Metadata property name used when reading an ISRC code from an AXML chunk. */
|
||||
static const char* const ISRC;
|
||||
|
||||
/** 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;
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
bool deleteStreamIfOpeningFails) override;
|
||||
|
||||
MemoryMappedAudioFormatReader* createMemoryMappedReader (const File& file) override;
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) override;
|
||||
|
||||
//==============================================================================
|
||||
/** 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)
|
||||
};
|
||||
@@ -0,0 +1,350 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
namespace WindowsMediaCodec
|
||||
{
|
||||
|
||||
class JuceIStream : public ComBaseClassHelper <IStream>
|
||||
{
|
||||
public:
|
||||
JuceIStream (InputStream& in) noexcept
|
||||
: ComBaseClassHelper <IStream> (0), source (in)
|
||||
{
|
||||
}
|
||||
|
||||
JUCE_COMRESULT Commit (DWORD) { return S_OK; }
|
||||
JUCE_COMRESULT Write (const void*, ULONG, ULONG*) { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT Clone (IStream**) { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT SetSize (ULARGE_INTEGER) { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT Revert() { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT LockRegion (ULARGE_INTEGER, ULARGE_INTEGER, DWORD) { return E_NOTIMPL; }
|
||||
JUCE_COMRESULT UnlockRegion (ULARGE_INTEGER, ULARGE_INTEGER, DWORD) { return E_NOTIMPL; }
|
||||
|
||||
JUCE_COMRESULT Read (void* dest, ULONG numBytes, ULONG* bytesRead)
|
||||
{
|
||||
const int numRead = source.read (dest, numBytes);
|
||||
|
||||
if (bytesRead != nullptr)
|
||||
*bytesRead = numRead;
|
||||
|
||||
return (numRead == (int) numBytes) ? S_OK : S_FALSE;
|
||||
}
|
||||
|
||||
JUCE_COMRESULT Seek (LARGE_INTEGER position, DWORD origin, ULARGE_INTEGER* resultPosition)
|
||||
{
|
||||
int64 newPos = (int64) position.QuadPart;
|
||||
|
||||
if (origin == STREAM_SEEK_CUR)
|
||||
{
|
||||
newPos += source.getPosition();
|
||||
}
|
||||
else if (origin == STREAM_SEEK_END)
|
||||
{
|
||||
const int64 len = source.getTotalLength();
|
||||
if (len < 0)
|
||||
return E_NOTIMPL;
|
||||
|
||||
newPos += len;
|
||||
}
|
||||
|
||||
if (resultPosition != nullptr)
|
||||
resultPosition->QuadPart = newPos;
|
||||
|
||||
return source.setPosition (newPos) ? S_OK : E_NOTIMPL;
|
||||
}
|
||||
|
||||
JUCE_COMRESULT CopyTo (IStream* destStream, ULARGE_INTEGER numBytesToDo,
|
||||
ULARGE_INTEGER* bytesRead, ULARGE_INTEGER* bytesWritten)
|
||||
{
|
||||
uint64 totalCopied = 0;
|
||||
int64 numBytes = numBytesToDo.QuadPart;
|
||||
|
||||
while (numBytes > 0 && ! source.isExhausted())
|
||||
{
|
||||
char buffer [1024];
|
||||
|
||||
const int numToCopy = (int) jmin ((int64) sizeof (buffer), (int64) numBytes);
|
||||
const int numRead = source.read (buffer, numToCopy);
|
||||
|
||||
if (numRead <= 0)
|
||||
break;
|
||||
|
||||
destStream->Write (buffer, numRead, nullptr);
|
||||
totalCopied += numRead;
|
||||
}
|
||||
|
||||
if (bytesRead != nullptr) bytesRead->QuadPart = totalCopied;
|
||||
if (bytesWritten != nullptr) bytesWritten->QuadPart = totalCopied;
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
JUCE_COMRESULT Stat (STATSTG* stat, DWORD)
|
||||
{
|
||||
if (stat == nullptr)
|
||||
return STG_E_INVALIDPOINTER;
|
||||
|
||||
zerostruct (*stat);
|
||||
stat->type = STGTY_STREAM;
|
||||
stat->cbSize.QuadPart = jmax ((int64) 0, source.getTotalLength());
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
private:
|
||||
InputStream& source;
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (JuceIStream)
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
static const char* wmFormatName = "Windows Media";
|
||||
static const char* const extensions[] = { ".mp3", ".wmv", ".asf", ".wm", ".wma", 0 };
|
||||
|
||||
//==============================================================================
|
||||
class WMAudioReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
WMAudioReader (InputStream* const input_)
|
||||
: AudioFormatReader (input_, TRANS (wmFormatName)),
|
||||
wmvCoreLib ("Wmvcore.dll")
|
||||
{
|
||||
JUCE_LOAD_WINAPI_FUNCTION (wmvCoreLib, WMCreateSyncReader, wmCreateSyncReader,
|
||||
HRESULT, (IUnknown*, DWORD, IWMSyncReader**))
|
||||
|
||||
if (wmCreateSyncReader != nullptr)
|
||||
{
|
||||
checkCoInitialiseCalled();
|
||||
|
||||
HRESULT hr = wmCreateSyncReader (nullptr, WMT_RIGHT_PLAYBACK, wmSyncReader.resetAndGetPointerAddress());
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
hr = wmSyncReader->OpenStream (new JuceIStream (*input));
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
WORD streamNum = 1;
|
||||
hr = wmSyncReader->GetStreamNumberForOutput (0, &streamNum);
|
||||
hr = wmSyncReader->SetReadStreamSamples (streamNum, false);
|
||||
|
||||
scanFileForDetails();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~WMAudioReader()
|
||||
{
|
||||
if (wmSyncReader != nullptr)
|
||||
wmSyncReader->Close();
|
||||
}
|
||||
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples) override
|
||||
{
|
||||
if (sampleRate <= 0)
|
||||
return false;
|
||||
|
||||
checkCoInitialiseCalled();
|
||||
|
||||
const int stride = numChannels * sizeof (int16);
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
if (! bufferedRange.contains (startSampleInFile))
|
||||
{
|
||||
const bool hasJumped = (startSampleInFile != bufferedRange.getEnd());
|
||||
|
||||
if (hasJumped)
|
||||
wmSyncReader->SetRange ((QWORD) (startSampleInFile * 10000000 / (int64) sampleRate), 0);
|
||||
|
||||
ComSmartPtr<INSSBuffer> sampleBuffer;
|
||||
QWORD sampleTime, duration;
|
||||
DWORD flags, outputNum;
|
||||
WORD streamNum;
|
||||
|
||||
HRESULT hr = wmSyncReader->GetNextSample (1, sampleBuffer.resetAndGetPointerAddress(),
|
||||
&sampleTime, &duration, &flags, &outputNum, &streamNum);
|
||||
|
||||
if (sampleBuffer != nullptr)
|
||||
{
|
||||
BYTE* rawData = nullptr;
|
||||
DWORD dataLength = 0;
|
||||
hr = sampleBuffer->GetBufferAndLength (&rawData, &dataLength);
|
||||
|
||||
if (dataLength == 0)
|
||||
return false;
|
||||
|
||||
if (hasJumped)
|
||||
bufferedRange.setStart ((int64) ((sampleTime * (int64) sampleRate) / 10000000));
|
||||
else
|
||||
bufferedRange.setStart (bufferedRange.getEnd()); // (because the positions returned often aren't continguous)
|
||||
|
||||
bufferedRange.setLength ((int64) (dataLength / stride));
|
||||
|
||||
buffer.ensureSize ((int) dataLength);
|
||||
memcpy (buffer.getData(), rawData, (size_t) dataLength);
|
||||
}
|
||||
else if (hr == NS_E_NO_MORE_SAMPLES)
|
||||
{
|
||||
bufferedRange.setStart (startSampleInFile);
|
||||
bufferedRange.setLength (256);
|
||||
buffer.ensureSize (256 * stride);
|
||||
buffer.fillWith (0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const int offsetInBuffer = (int) (startSampleInFile - bufferedRange.getStart());
|
||||
const int16* const rawData = static_cast<const int16*> (addBytesToPointer (buffer.getData(), offsetInBuffer * stride));
|
||||
const int numToDo = jmin (numSamples, (int) (bufferedRange.getLength() - offsetInBuffer));
|
||||
|
||||
for (int i = 0; i < numDestChannels; ++i)
|
||||
{
|
||||
jassert (destSamples[i] != nullptr);
|
||||
|
||||
const int srcChan = jmin (i, (int) numChannels - 1);
|
||||
const int16* src = rawData + srcChan;
|
||||
int* const dst = destSamples[i] + startOffsetInDestBuffer;
|
||||
|
||||
for (int j = 0; j < numToDo; ++j)
|
||||
{
|
||||
dst[j] = ((uint32) *src) << 16;
|
||||
src += numChannels;
|
||||
}
|
||||
}
|
||||
|
||||
startSampleInFile += numToDo;
|
||||
startOffsetInDestBuffer += numToDo;
|
||||
numSamples -= numToDo;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
DynamicLibrary wmvCoreLib;
|
||||
ComSmartPtr<IWMSyncReader> wmSyncReader;
|
||||
MemoryBlock buffer;
|
||||
Range<int64> bufferedRange;
|
||||
|
||||
void checkCoInitialiseCalled()
|
||||
{
|
||||
CoInitialize (0);
|
||||
}
|
||||
|
||||
void scanFileForDetails()
|
||||
{
|
||||
ComSmartPtr<IWMHeaderInfo> wmHeaderInfo;
|
||||
HRESULT hr = wmSyncReader.QueryInterface (wmHeaderInfo);
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
QWORD lengthInNanoseconds = 0;
|
||||
WORD lengthOfLength = sizeof (lengthInNanoseconds);
|
||||
WORD streamNum = 0;
|
||||
WMT_ATTR_DATATYPE wmAttrDataType;
|
||||
hr = wmHeaderInfo->GetAttributeByName (&streamNum, L"Duration", &wmAttrDataType,
|
||||
(BYTE*) &lengthInNanoseconds, &lengthOfLength);
|
||||
|
||||
ComSmartPtr<IWMProfile> wmProfile;
|
||||
hr = wmSyncReader.QueryInterface (wmProfile);
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
ComSmartPtr<IWMStreamConfig> wmStreamConfig;
|
||||
hr = wmProfile->GetStream (0, wmStreamConfig.resetAndGetPointerAddress());
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
ComSmartPtr<IWMMediaProps> wmMediaProperties;
|
||||
hr = wmStreamConfig.QueryInterface (wmMediaProperties);
|
||||
|
||||
if (SUCCEEDED (hr))
|
||||
{
|
||||
DWORD sizeMediaType;
|
||||
hr = wmMediaProperties->GetMediaType (0, &sizeMediaType);
|
||||
|
||||
HeapBlock<WM_MEDIA_TYPE> mediaType;
|
||||
mediaType.malloc (sizeMediaType, 1);
|
||||
hr = wmMediaProperties->GetMediaType (mediaType, &sizeMediaType);
|
||||
|
||||
if (mediaType->majortype == WMMEDIATYPE_Audio)
|
||||
{
|
||||
const WAVEFORMATEX* const inputFormat = reinterpret_cast<WAVEFORMATEX*> (mediaType->pbFormat);
|
||||
|
||||
sampleRate = inputFormat->nSamplesPerSec;
|
||||
numChannels = inputFormat->nChannels;
|
||||
bitsPerSample = inputFormat->wBitsPerSample;
|
||||
lengthInSamples = (lengthInNanoseconds * (int) sampleRate) / 10000000;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WMAudioReader)
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
WindowsMediaAudioFormat::WindowsMediaAudioFormat()
|
||||
: AudioFormat (TRANS (WindowsMediaCodec::wmFormatName),
|
||||
StringArray (WindowsMediaCodec::extensions))
|
||||
{
|
||||
}
|
||||
|
||||
WindowsMediaAudioFormat::~WindowsMediaAudioFormat() {}
|
||||
|
||||
Array<int> WindowsMediaAudioFormat::getPossibleSampleRates() { return Array<int>(); }
|
||||
Array<int> WindowsMediaAudioFormat::getPossibleBitDepths() { return Array<int>(); }
|
||||
|
||||
bool WindowsMediaAudioFormat::canDoStereo() { return true; }
|
||||
bool WindowsMediaAudioFormat::canDoMono() { return true; }
|
||||
bool WindowsMediaAudioFormat::isCompressed() { return true; }
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* WindowsMediaAudioFormat::createReaderFor (InputStream* sourceStream, bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
ScopedPointer<WindowsMediaCodec::WMAudioReader> r (new WindowsMediaCodec::WMAudioReader (sourceStream));
|
||||
|
||||
if (r->sampleRate > 0)
|
||||
return r.release();
|
||||
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = nullptr;
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AudioFormatWriter* WindowsMediaAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/, double /*sampleRateToUse*/,
|
||||
unsigned int /*numberOfChannels*/, int /*bitsPerSample*/,
|
||||
const StringPairArray& /*metadataValues*/, int /*qualityOptionIndex*/)
|
||||
{
|
||||
jassertfalse; // not yet implemented!
|
||||
return nullptr;
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library.
|
||||
Copyright (c) 2013 - Raw Material Software Ltd.
|
||||
|
||||
Permission is granted to use this software under the terms of either:
|
||||
a) the GPL v2 (or any later version)
|
||||
b) the Affero GPL v3
|
||||
|
||||
Details of these licenses can be found at: www.gnu.org/licenses
|
||||
|
||||
JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
A PARTICULAR PURPOSE. See the GNU General Public License for more details.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
To release a closed-source product which uses JUCE, commercial licenses are
|
||||
available: visit www.juce.com for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#if JUCE_WINDOWS || DOXYGEN
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Audio format which uses the Windows Media codecs (Windows only).
|
||||
*/
|
||||
class WindowsMediaAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
WindowsMediaAudioFormat();
|
||||
~WindowsMediaAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,47 @@
|
||||
=====================================================================
|
||||
|
||||
I've incorporated Ogg-Vorbis 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 Ogg-Vorbis code - just tweaked a few include
|
||||
paths to make it build smoothly, and added some headers to allow you to exclude
|
||||
it from the build.
|
||||
|
||||
=====================================================================
|
||||
|
||||
The following license is the BSD-style license that comes with the
|
||||
Ogg-Vorbis distribution, and which applies just to the header files I've
|
||||
included in this directory. For more info, and to get the rest of the
|
||||
distribution, visit the Ogg-Vorbis homepage: www.vorbis.com
|
||||
|
||||
=====================================================================
|
||||
|
||||
Copyright (c) 2002-2004 Xiph.org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
@@ -0,0 +1,784 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* 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-2002 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: packing variable sized words into an octet stream
|
||||
last mod: $Id: bitwise.c,v 1.1 2007/06/07 17:48:18 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* We're 'LSb' endian; if we write a word but read individual bits,
|
||||
then we'll read the lsb first */
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "ogg.h"
|
||||
|
||||
#define BUFFER_INCREMENT 256
|
||||
|
||||
static const unsigned long mask[]=
|
||||
{0x00000000,0x00000001,0x00000003,0x00000007,0x0000000f,
|
||||
0x0000001f,0x0000003f,0x0000007f,0x000000ff,0x000001ff,
|
||||
0x000003ff,0x000007ff,0x00000fff,0x00001fff,0x00003fff,
|
||||
0x00007fff,0x0000ffff,0x0001ffff,0x0003ffff,0x0007ffff,
|
||||
0x000fffff,0x001fffff,0x003fffff,0x007fffff,0x00ffffff,
|
||||
0x01ffffff,0x03ffffff,0x07ffffff,0x0fffffff,0x1fffffff,
|
||||
0x3fffffff,0x7fffffff,0xffffffff };
|
||||
|
||||
static const unsigned int mask8B[]=
|
||||
{0x00,0x80,0xc0,0xe0,0xf0,0xf8,0xfc,0xfe,0xff};
|
||||
|
||||
void oggpack_writeinit(oggpack_buffer *b){
|
||||
memset(b,0,sizeof(*b));
|
||||
b->ptr=b->buffer=(unsigned char*) _ogg_malloc(BUFFER_INCREMENT);
|
||||
b->buffer[0]='\0';
|
||||
b->storage=BUFFER_INCREMENT;
|
||||
}
|
||||
|
||||
void oggpackB_writeinit(oggpack_buffer *b){
|
||||
oggpack_writeinit(b);
|
||||
}
|
||||
|
||||
void oggpack_writetrunc(oggpack_buffer *b,long bits){
|
||||
long bytes=bits>>3;
|
||||
bits-=bytes*8;
|
||||
b->ptr=b->buffer+bytes;
|
||||
b->endbit=bits;
|
||||
b->endbyte=bytes;
|
||||
*b->ptr&=mask[bits];
|
||||
}
|
||||
|
||||
void oggpackB_writetrunc(oggpack_buffer *b,long bits){
|
||||
long bytes=bits>>3;
|
||||
bits-=bytes*8;
|
||||
b->ptr=b->buffer+bytes;
|
||||
b->endbit=bits;
|
||||
b->endbyte=bytes;
|
||||
*b->ptr&=mask8B[bits];
|
||||
}
|
||||
|
||||
/* Takes only up to 32 bits. */
|
||||
void oggpack_write(oggpack_buffer *b,unsigned long value,int bits){
|
||||
if(b->endbyte+4>=b->storage){
|
||||
b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
|
||||
b->storage+=BUFFER_INCREMENT;
|
||||
b->ptr=b->buffer+b->endbyte;
|
||||
}
|
||||
|
||||
value&=mask[bits];
|
||||
bits+=b->endbit;
|
||||
|
||||
b->ptr[0]|=value<<b->endbit;
|
||||
|
||||
if(bits>=8){
|
||||
b->ptr[1]=(unsigned char)(value>>(8-b->endbit));
|
||||
if(bits>=16){
|
||||
b->ptr[2]=(unsigned char)(value>>(16-b->endbit));
|
||||
if(bits>=24){
|
||||
b->ptr[3]=(unsigned char)(value>>(24-b->endbit));
|
||||
if(bits>=32){
|
||||
if(b->endbit)
|
||||
b->ptr[4]=(unsigned char)(value>>(32-b->endbit));
|
||||
else
|
||||
b->ptr[4]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b->endbyte+=bits/8;
|
||||
b->ptr+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
}
|
||||
|
||||
/* Takes only up to 32 bits. */
|
||||
void oggpackB_write(oggpack_buffer *b,unsigned long value,int bits){
|
||||
if(b->endbyte+4>=b->storage){
|
||||
b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage+BUFFER_INCREMENT);
|
||||
b->storage+=BUFFER_INCREMENT;
|
||||
b->ptr=b->buffer+b->endbyte;
|
||||
}
|
||||
|
||||
value=(value&mask[bits])<<(32-bits);
|
||||
bits+=b->endbit;
|
||||
|
||||
b->ptr[0]|=value>>(24+b->endbit);
|
||||
|
||||
if(bits>=8){
|
||||
b->ptr[1]=(unsigned char)(value>>(16+b->endbit));
|
||||
if(bits>=16){
|
||||
b->ptr[2]=(unsigned char)(value>>(8+b->endbit));
|
||||
if(bits>=24){
|
||||
b->ptr[3]=(unsigned char)(value>>(b->endbit));
|
||||
if(bits>=32){
|
||||
if(b->endbit)
|
||||
b->ptr[4]=(unsigned char)(value<<(8-b->endbit));
|
||||
else
|
||||
b->ptr[4]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
b->endbyte+=bits/8;
|
||||
b->ptr+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
}
|
||||
|
||||
void oggpack_writealign(oggpack_buffer *b){
|
||||
int bits=8-b->endbit;
|
||||
if(bits<8)
|
||||
oggpack_write(b,0,bits);
|
||||
}
|
||||
|
||||
void oggpackB_writealign(oggpack_buffer *b){
|
||||
int bits=8-b->endbit;
|
||||
if(bits<8)
|
||||
oggpackB_write(b,0,bits);
|
||||
}
|
||||
|
||||
static void oggpack_writecopy_helper(oggpack_buffer *b,
|
||||
void *source,
|
||||
long bits,
|
||||
void (*w)(oggpack_buffer *,
|
||||
unsigned long,
|
||||
int),
|
||||
int msb){
|
||||
unsigned char *ptr=(unsigned char *)source;
|
||||
|
||||
long bytes=bits/8;
|
||||
bits-=bytes*8;
|
||||
|
||||
if(b->endbit){
|
||||
int i;
|
||||
/* unaligned copy. Do it the hard way. */
|
||||
for(i=0;i<bytes;i++)
|
||||
w(b,(unsigned long)(ptr[i]),8);
|
||||
}else{
|
||||
/* aligned block copy */
|
||||
if(b->endbyte+bytes+1>=b->storage){
|
||||
b->storage=b->endbyte+bytes+BUFFER_INCREMENT;
|
||||
b->buffer=(unsigned char*) _ogg_realloc(b->buffer,b->storage);
|
||||
b->ptr=b->buffer+b->endbyte;
|
||||
}
|
||||
|
||||
memmove(b->ptr,source,bytes);
|
||||
b->ptr+=bytes;
|
||||
b->endbyte+=bytes;
|
||||
*b->ptr=0;
|
||||
|
||||
}
|
||||
if(bits){
|
||||
if(msb)
|
||||
w(b,(unsigned long)(ptr[bytes]>>(8-bits)),bits);
|
||||
else
|
||||
w(b,(unsigned long)(ptr[bytes]),bits);
|
||||
}
|
||||
}
|
||||
|
||||
void oggpack_writecopy(oggpack_buffer *b,void *source,long bits){
|
||||
oggpack_writecopy_helper(b,source,bits,oggpack_write,0);
|
||||
}
|
||||
|
||||
void oggpackB_writecopy(oggpack_buffer *b,void *source,long bits){
|
||||
oggpack_writecopy_helper(b,source,bits,oggpackB_write,1);
|
||||
}
|
||||
|
||||
void oggpack_reset(oggpack_buffer *b){
|
||||
b->ptr=b->buffer;
|
||||
b->buffer[0]=0;
|
||||
b->endbit=b->endbyte=0;
|
||||
}
|
||||
|
||||
void oggpackB_reset(oggpack_buffer *b){
|
||||
oggpack_reset(b);
|
||||
}
|
||||
|
||||
void oggpack_writeclear(oggpack_buffer *b){
|
||||
_ogg_free(b->buffer);
|
||||
memset(b,0,sizeof(*b));
|
||||
}
|
||||
|
||||
void oggpackB_writeclear(oggpack_buffer *b){
|
||||
oggpack_writeclear(b);
|
||||
}
|
||||
|
||||
void oggpack_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
|
||||
memset(b,0,sizeof(*b));
|
||||
b->buffer=b->ptr=buf;
|
||||
b->storage=bytes;
|
||||
}
|
||||
|
||||
void oggpackB_readinit(oggpack_buffer *b,unsigned char *buf,int bytes){
|
||||
oggpack_readinit(b,buf,bytes);
|
||||
}
|
||||
|
||||
/* Read in bits without advancing the bitptr; bits <= 32 */
|
||||
long oggpack_look(oggpack_buffer *b,int bits){
|
||||
unsigned long ret;
|
||||
unsigned long m=mask[bits];
|
||||
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte+4>=b->storage){
|
||||
/* not the main path */
|
||||
if(b->endbyte*8+bits>b->storage*8)return(-1);
|
||||
}
|
||||
|
||||
ret=b->ptr[0]>>b->endbit;
|
||||
if(bits>8){
|
||||
ret|=b->ptr[1]<<(8-b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->ptr[2]<<(16-b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->ptr[3]<<(24-b->endbit);
|
||||
if(bits>32 && b->endbit)
|
||||
ret|=b->ptr[4]<<(32-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return(m&ret);
|
||||
}
|
||||
|
||||
/* Read in bits without advancing the bitptr; bits <= 32 */
|
||||
long oggpackB_look(oggpack_buffer *b,int bits){
|
||||
unsigned long ret;
|
||||
int m=32-bits;
|
||||
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte+4>=b->storage){
|
||||
/* not the main path */
|
||||
if(b->endbyte*8+bits>b->storage*8)return(-1);
|
||||
}
|
||||
|
||||
ret=b->ptr[0]<<(24+b->endbit);
|
||||
if(bits>8){
|
||||
ret|=b->ptr[1]<<(16+b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->ptr[2]<<(8+b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->ptr[3]<<(b->endbit);
|
||||
if(bits>32 && b->endbit)
|
||||
ret|=b->ptr[4]>>(8-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ((ret&0xffffffff)>>(m>>1))>>((m+1)>>1);
|
||||
}
|
||||
|
||||
long oggpack_look1(oggpack_buffer *b){
|
||||
if(b->endbyte>=b->storage)return(-1);
|
||||
return((b->ptr[0]>>b->endbit)&1);
|
||||
}
|
||||
|
||||
long oggpackB_look1(oggpack_buffer *b){
|
||||
if(b->endbyte>=b->storage)return(-1);
|
||||
return((b->ptr[0]>>(7-b->endbit))&1);
|
||||
}
|
||||
|
||||
void oggpack_adv(oggpack_buffer *b,int bits){
|
||||
bits+=b->endbit;
|
||||
b->ptr+=bits/8;
|
||||
b->endbyte+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
}
|
||||
|
||||
void oggpackB_adv(oggpack_buffer *b,int bits){
|
||||
oggpack_adv(b,bits);
|
||||
}
|
||||
|
||||
void oggpack_adv1(oggpack_buffer *b){
|
||||
if(++(b->endbit)>7){
|
||||
b->endbit=0;
|
||||
b->ptr++;
|
||||
b->endbyte++;
|
||||
}
|
||||
}
|
||||
|
||||
void oggpackB_adv1(oggpack_buffer *b){
|
||||
oggpack_adv1(b);
|
||||
}
|
||||
|
||||
/* bits <= 32 */
|
||||
long oggpack_read(oggpack_buffer *b,int bits){
|
||||
long ret;
|
||||
unsigned long m=mask[bits];
|
||||
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte+4>=b->storage){
|
||||
/* not the main path */
|
||||
ret=-1L;
|
||||
if(b->endbyte*8+bits>b->storage*8)goto overflow;
|
||||
}
|
||||
|
||||
ret=b->ptr[0]>>b->endbit;
|
||||
if(bits>8){
|
||||
ret|=b->ptr[1]<<(8-b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->ptr[2]<<(16-b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->ptr[3]<<(24-b->endbit);
|
||||
if(bits>32 && b->endbit){
|
||||
ret|=b->ptr[4]<<(32-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
ret&=m;
|
||||
|
||||
overflow:
|
||||
|
||||
b->ptr+=bits/8;
|
||||
b->endbyte+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
/* bits <= 32 */
|
||||
long oggpackB_read(oggpack_buffer *b,int bits){
|
||||
long ret;
|
||||
long m=32-bits;
|
||||
|
||||
bits+=b->endbit;
|
||||
|
||||
if(b->endbyte+4>=b->storage){
|
||||
/* not the main path */
|
||||
ret=-1L;
|
||||
if(b->endbyte*8+bits>b->storage*8)goto overflow;
|
||||
}
|
||||
|
||||
ret=b->ptr[0]<<(24+b->endbit);
|
||||
if(bits>8){
|
||||
ret|=b->ptr[1]<<(16+b->endbit);
|
||||
if(bits>16){
|
||||
ret|=b->ptr[2]<<(8+b->endbit);
|
||||
if(bits>24){
|
||||
ret|=b->ptr[3]<<(b->endbit);
|
||||
if(bits>32 && b->endbit)
|
||||
ret|=b->ptr[4]>>(8-b->endbit);
|
||||
}
|
||||
}
|
||||
}
|
||||
ret=((ret&0xffffffffUL)>>(m>>1))>>((m+1)>>1);
|
||||
|
||||
overflow:
|
||||
|
||||
b->ptr+=bits/8;
|
||||
b->endbyte+=bits/8;
|
||||
b->endbit=bits&7;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
long oggpack_read1(oggpack_buffer *b){
|
||||
long ret;
|
||||
|
||||
if(b->endbyte>=b->storage){
|
||||
/* not the main path */
|
||||
ret=-1L;
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
ret=(b->ptr[0]>>b->endbit)&1;
|
||||
|
||||
overflow:
|
||||
|
||||
b->endbit++;
|
||||
if(b->endbit>7){
|
||||
b->endbit=0;
|
||||
b->ptr++;
|
||||
b->endbyte++;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
long oggpackB_read1(oggpack_buffer *b){
|
||||
long ret;
|
||||
|
||||
if(b->endbyte>=b->storage){
|
||||
/* not the main path */
|
||||
ret=-1L;
|
||||
goto overflow;
|
||||
}
|
||||
|
||||
ret=(b->ptr[0]>>(7-b->endbit))&1;
|
||||
|
||||
overflow:
|
||||
|
||||
b->endbit++;
|
||||
if(b->endbit>7){
|
||||
b->endbit=0;
|
||||
b->ptr++;
|
||||
b->endbyte++;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
long oggpack_bytes(oggpack_buffer *b){
|
||||
return(b->endbyte+(b->endbit+7)/8);
|
||||
}
|
||||
|
||||
long oggpack_bits(oggpack_buffer *b){
|
||||
return(b->endbyte*8+b->endbit);
|
||||
}
|
||||
|
||||
long oggpackB_bytes(oggpack_buffer *b){
|
||||
return oggpack_bytes(b);
|
||||
}
|
||||
|
||||
long oggpackB_bits(oggpack_buffer *b){
|
||||
return oggpack_bits(b);
|
||||
}
|
||||
|
||||
unsigned char *oggpack_get_buffer(oggpack_buffer *b){
|
||||
return(b->buffer);
|
||||
}
|
||||
|
||||
unsigned char *oggpackB_get_buffer(oggpack_buffer *b){
|
||||
return oggpack_get_buffer(b);
|
||||
}
|
||||
|
||||
/* Self test of the bitwise routines; everything else is based on
|
||||
them, so they damned well better be solid. */
|
||||
|
||||
#ifdef _V_SELFTEST
|
||||
#include <stdio.h>
|
||||
|
||||
static int ilog(unsigned int v){
|
||||
int ret=0;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
oggpack_buffer o;
|
||||
oggpack_buffer r;
|
||||
|
||||
void report(char *in){
|
||||
fprintf(stderr,"%s",in);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void cliptest(unsigned long *b,int vals,int bits,int *comp,int compsize){
|
||||
long bytes,i;
|
||||
unsigned char *buffer;
|
||||
|
||||
oggpack_reset(&o);
|
||||
for(i=0;i<vals;i++)
|
||||
oggpack_write(&o,b[i],bits?bits:ilog(b[i]));
|
||||
buffer=oggpack_get_buffer(&o);
|
||||
bytes=oggpack_bytes(&o);
|
||||
if(bytes!=compsize)report("wrong number of bytes!\n");
|
||||
for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
|
||||
for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
|
||||
report("wrote incorrect value!\n");
|
||||
}
|
||||
oggpack_readinit(&r,buffer,bytes);
|
||||
for(i=0;i<vals;i++){
|
||||
int tbit=bits?bits:ilog(b[i]);
|
||||
if(oggpack_look(&r,tbit)==-1)
|
||||
report("out of data!\n");
|
||||
if(oggpack_look(&r,tbit)!=(b[i]&mask[tbit]))
|
||||
report("looked at incorrect value!\n");
|
||||
if(tbit==1)
|
||||
if(oggpack_look1(&r)!=(b[i]&mask[tbit]))
|
||||
report("looked at single bit incorrect value!\n");
|
||||
if(tbit==1){
|
||||
if(oggpack_read1(&r)!=(b[i]&mask[tbit]))
|
||||
report("read incorrect single bit value!\n");
|
||||
}else{
|
||||
if(oggpack_read(&r,tbit)!=(b[i]&mask[tbit]))
|
||||
report("read incorrect value!\n");
|
||||
}
|
||||
}
|
||||
if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
|
||||
}
|
||||
|
||||
void cliptestB(unsigned long *b,int vals,int bits,int *comp,int compsize){
|
||||
long bytes,i;
|
||||
unsigned char *buffer;
|
||||
|
||||
oggpackB_reset(&o);
|
||||
for(i=0;i<vals;i++)
|
||||
oggpackB_write(&o,b[i],bits?bits:ilog(b[i]));
|
||||
buffer=oggpackB_get_buffer(&o);
|
||||
bytes=oggpackB_bytes(&o);
|
||||
if(bytes!=compsize)report("wrong number of bytes!\n");
|
||||
for(i=0;i<bytes;i++)if(buffer[i]!=comp[i]){
|
||||
for(i=0;i<bytes;i++)fprintf(stderr,"%x %x\n",(int)buffer[i],(int)comp[i]);
|
||||
report("wrote incorrect value!\n");
|
||||
}
|
||||
oggpackB_readinit(&r,buffer,bytes);
|
||||
for(i=0;i<vals;i++){
|
||||
int tbit=bits?bits:ilog(b[i]);
|
||||
if(oggpackB_look(&r,tbit)==-1)
|
||||
report("out of data!\n");
|
||||
if(oggpackB_look(&r,tbit)!=(b[i]&mask[tbit]))
|
||||
report("looked at incorrect value!\n");
|
||||
if(tbit==1)
|
||||
if(oggpackB_look1(&r)!=(b[i]&mask[tbit]))
|
||||
report("looked at single bit incorrect value!\n");
|
||||
if(tbit==1){
|
||||
if(oggpackB_read1(&r)!=(b[i]&mask[tbit]))
|
||||
report("read incorrect single bit value!\n");
|
||||
}else{
|
||||
if(oggpackB_read(&r,tbit)!=(b[i]&mask[tbit]))
|
||||
report("read incorrect value!\n");
|
||||
}
|
||||
}
|
||||
if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
|
||||
}
|
||||
|
||||
int main(void){
|
||||
unsigned char *buffer;
|
||||
long bytes,i;
|
||||
static unsigned long testbuffer1[]=
|
||||
{18,12,103948,4325,543,76,432,52,3,65,4,56,32,42,34,21,1,23,32,546,456,7,
|
||||
567,56,8,8,55,3,52,342,341,4,265,7,67,86,2199,21,7,1,5,1,4};
|
||||
int test1size=43;
|
||||
|
||||
static unsigned long testbuffer2[]=
|
||||
{216531625L,1237861823,56732452,131,3212421,12325343,34547562,12313212,
|
||||
1233432,534,5,346435231,14436467,7869299,76326614,167548585,
|
||||
85525151,0,12321,1,349528352};
|
||||
int test2size=21;
|
||||
|
||||
static unsigned long testbuffer3[]=
|
||||
{1,0,14,0,1,0,12,0,1,0,0,0,1,1,0,1,0,1,0,1,0,1,0,1,0,1,0,0,1,1,1,1,1,0,0,1,
|
||||
0,1,30,1,1,1,0,0,1,0,0,0,12,0,11,0,1,0,0,1};
|
||||
int test3size=56;
|
||||
|
||||
static unsigned long large[]=
|
||||
{2136531625L,2137861823,56732452,131,3212421,12325343,34547562,12313212,
|
||||
1233432,534,5,2146435231,14436467,7869299,76326614,167548585,
|
||||
85525151,0,12321,1,2146528352};
|
||||
|
||||
int onesize=33;
|
||||
static int one[33]={146,25,44,151,195,15,153,176,233,131,196,65,85,172,47,40,
|
||||
34,242,223,136,35,222,211,86,171,50,225,135,214,75,172,
|
||||
223,4};
|
||||
static int oneB[33]={150,101,131,33,203,15,204,216,105,193,156,65,84,85,222,
|
||||
8,139,145,227,126,34,55,244,171,85,100,39,195,173,18,
|
||||
245,251,128};
|
||||
|
||||
int twosize=6;
|
||||
static int two[6]={61,255,255,251,231,29};
|
||||
static int twoB[6]={247,63,255,253,249,120};
|
||||
|
||||
int threesize=54;
|
||||
static int three[54]={169,2,232,252,91,132,156,36,89,13,123,176,144,32,254,
|
||||
142,224,85,59,121,144,79,124,23,67,90,90,216,79,23,83,
|
||||
58,135,196,61,55,129,183,54,101,100,170,37,127,126,10,
|
||||
100,52,4,14,18,86,77,1};
|
||||
static int threeB[54]={206,128,42,153,57,8,183,251,13,89,36,30,32,144,183,
|
||||
130,59,240,121,59,85,223,19,228,180,134,33,107,74,98,
|
||||
233,253,196,135,63,2,110,114,50,155,90,127,37,170,104,
|
||||
200,20,254,4,58,106,176,144,0};
|
||||
|
||||
int foursize=38;
|
||||
static int four[38]={18,6,163,252,97,194,104,131,32,1,7,82,137,42,129,11,72,
|
||||
132,60,220,112,8,196,109,64,179,86,9,137,195,208,122,169,
|
||||
28,2,133,0,1};
|
||||
static int fourB[38]={36,48,102,83,243,24,52,7,4,35,132,10,145,21,2,93,2,41,
|
||||
1,219,184,16,33,184,54,149,170,132,18,30,29,98,229,67,
|
||||
129,10,4,32};
|
||||
|
||||
int fivesize=45;
|
||||
static int five[45]={169,2,126,139,144,172,30,4,80,72,240,59,130,218,73,62,
|
||||
241,24,210,44,4,20,0,248,116,49,135,100,110,130,181,169,
|
||||
84,75,159,2,1,0,132,192,8,0,0,18,22};
|
||||
static int fiveB[45]={1,84,145,111,245,100,128,8,56,36,40,71,126,78,213,226,
|
||||
124,105,12,0,133,128,0,162,233,242,67,152,77,205,77,
|
||||
172,150,169,129,79,128,0,6,4,32,0,27,9,0};
|
||||
|
||||
int sixsize=7;
|
||||
static int six[7]={17,177,170,242,169,19,148};
|
||||
static int sixB[7]={136,141,85,79,149,200,41};
|
||||
|
||||
/* Test read/write together */
|
||||
/* Later we test against pregenerated bitstreams */
|
||||
oggpack_writeinit(&o);
|
||||
|
||||
fprintf(stderr,"\nSmall preclipped packing (LSb): ");
|
||||
cliptest(testbuffer1,test1size,0,one,onesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nNull bit call (LSb): ");
|
||||
cliptest(testbuffer3,test3size,0,two,twosize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nLarge preclipped packing (LSb): ");
|
||||
cliptest(testbuffer2,test2size,0,three,threesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\n32 bit preclipped packing (LSb): ");
|
||||
oggpack_reset(&o);
|
||||
for(i=0;i<test2size;i++)
|
||||
oggpack_write(&o,large[i],32);
|
||||
buffer=oggpack_get_buffer(&o);
|
||||
bytes=oggpack_bytes(&o);
|
||||
oggpack_readinit(&r,buffer,bytes);
|
||||
for(i=0;i<test2size;i++){
|
||||
if(oggpack_look(&r,32)==-1)report("out of data. failed!");
|
||||
if(oggpack_look(&r,32)!=large[i]){
|
||||
fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpack_look(&r,32),large[i],
|
||||
oggpack_look(&r,32),large[i]);
|
||||
report("read incorrect value!\n");
|
||||
}
|
||||
oggpack_adv(&r,32);
|
||||
}
|
||||
if(oggpack_bytes(&r)!=bytes)report("leftover bytes after read!\n");
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nSmall unclipped packing (LSb): ");
|
||||
cliptest(testbuffer1,test1size,7,four,foursize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nLarge unclipped packing (LSb): ");
|
||||
cliptest(testbuffer2,test2size,17,five,fivesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nSingle bit unclipped packing (LSb): ");
|
||||
cliptest(testbuffer3,test3size,1,six,sixsize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nTesting read past end (LSb): ");
|
||||
oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
|
||||
for(i=0;i<64;i++){
|
||||
if(oggpack_read(&r,1)!=0){
|
||||
fprintf(stderr,"failed; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(oggpack_look(&r,1)!=-1 ||
|
||||
oggpack_read(&r,1)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
oggpack_readinit(&r,"\0\0\0\0\0\0\0\0",8);
|
||||
if(oggpack_read(&r,30)!=0 || oggpack_read(&r,16)!=0){
|
||||
fprintf(stderr,"failed 2; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(oggpack_look(&r,18)!=0 ||
|
||||
oggpack_look(&r,18)!=0){
|
||||
fprintf(stderr,"failed 3; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(oggpack_look(&r,19)!=-1 ||
|
||||
oggpack_look(&r,19)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(oggpack_look(&r,32)!=-1 ||
|
||||
oggpack_look(&r,32)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
oggpack_writeclear(&o);
|
||||
fprintf(stderr,"ok.\n");
|
||||
|
||||
/********** lazy, cut-n-paste retest with MSb packing ***********/
|
||||
|
||||
/* Test read/write together */
|
||||
/* Later we test against pregenerated bitstreams */
|
||||
oggpackB_writeinit(&o);
|
||||
|
||||
fprintf(stderr,"\nSmall preclipped packing (MSb): ");
|
||||
cliptestB(testbuffer1,test1size,0,oneB,onesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nNull bit call (MSb): ");
|
||||
cliptestB(testbuffer3,test3size,0,twoB,twosize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nLarge preclipped packing (MSb): ");
|
||||
cliptestB(testbuffer2,test2size,0,threeB,threesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\n32 bit preclipped packing (MSb): ");
|
||||
oggpackB_reset(&o);
|
||||
for(i=0;i<test2size;i++)
|
||||
oggpackB_write(&o,large[i],32);
|
||||
buffer=oggpackB_get_buffer(&o);
|
||||
bytes=oggpackB_bytes(&o);
|
||||
oggpackB_readinit(&r,buffer,bytes);
|
||||
for(i=0;i<test2size;i++){
|
||||
if(oggpackB_look(&r,32)==-1)report("out of data. failed!");
|
||||
if(oggpackB_look(&r,32)!=large[i]){
|
||||
fprintf(stderr,"%ld != %ld (%lx!=%lx):",oggpackB_look(&r,32),large[i],
|
||||
oggpackB_look(&r,32),large[i]);
|
||||
report("read incorrect value!\n");
|
||||
}
|
||||
oggpackB_adv(&r,32);
|
||||
}
|
||||
if(oggpackB_bytes(&r)!=bytes)report("leftover bytes after read!\n");
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nSmall unclipped packing (MSb): ");
|
||||
cliptestB(testbuffer1,test1size,7,fourB,foursize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nLarge unclipped packing (MSb): ");
|
||||
cliptestB(testbuffer2,test2size,17,fiveB,fivesize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nSingle bit unclipped packing (MSb): ");
|
||||
cliptestB(testbuffer3,test3size,1,sixB,sixsize);
|
||||
fprintf(stderr,"ok.");
|
||||
|
||||
fprintf(stderr,"\nTesting read past end (MSb): ");
|
||||
oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8);
|
||||
for(i=0;i<64;i++){
|
||||
if(oggpackB_read(&r,1)!=0){
|
||||
fprintf(stderr,"failed; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
if(oggpackB_look(&r,1)!=-1 ||
|
||||
oggpackB_read(&r,1)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
oggpackB_readinit(&r,"\0\0\0\0\0\0\0\0",8);
|
||||
if(oggpackB_read(&r,30)!=0 || oggpackB_read(&r,16)!=0){
|
||||
fprintf(stderr,"failed 2; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if(oggpackB_look(&r,18)!=0 ||
|
||||
oggpackB_look(&r,18)!=0){
|
||||
fprintf(stderr,"failed 3; got -1 prematurely.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(oggpackB_look(&r,19)!=-1 ||
|
||||
oggpackB_look(&r,19)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(oggpackB_look(&r,32)!=-1 ||
|
||||
oggpackB_look(&r,32)!=-1){
|
||||
fprintf(stderr,"failed; read past end without -1.\n");
|
||||
exit(1);
|
||||
}
|
||||
oggpackB_writeclear(&o);
|
||||
fprintf(stderr,"ok.\n\n");
|
||||
|
||||
|
||||
return(0);
|
||||
}
|
||||
#endif /* _V_SELFTEST */
|
||||
|
||||
#undef BUFFER_INCREMENT
|
||||
@@ -0,0 +1,242 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2001 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec.h 17021 2010-03-24 09:29:41Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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,10 @@
|
||||
#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;
|
||||
|
||||
#endif
|
||||
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.
|
||||
@@ -0,0 +1,126 @@
|
||||
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
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
Copyright (c) 2002-2008 Xiph.org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- 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,134 @@
|
||||
********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.org Foundation, http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
Vorbis is a general purpose audio and music encoding format
|
||||
contemporary to MPEG-4's AAC and TwinVQ, the next generation beyond
|
||||
MPEG audio layer 3. Unlike the MPEG sponsored formats (and other
|
||||
proprietary formats such as RealAudio G2 and Windows' flavor of the
|
||||
month), the Vorbis CODEC specification belongs to the public domain.
|
||||
All the technical details are published and documented, and any
|
||||
software entity may make full use of the format without license
|
||||
fee, royalty or patent concerns.
|
||||
|
||||
This package contains:
|
||||
|
||||
* libvorbis, a BSD-style license software implementation of
|
||||
the Vorbis specification by the Xiph.Org Foundation
|
||||
(http://www.xiph.org/)
|
||||
|
||||
* libvorbisfile, a BSD-style license convenience library
|
||||
built on Vorbis designed to simplify common uses
|
||||
|
||||
* libvorbisenc, a BSD-style license library that provides a simple,
|
||||
programmatic encoding setup interface
|
||||
|
||||
* example code making use of libogg, libvorbis, libvorbisfile and
|
||||
libvorbisenc
|
||||
|
||||
WHAT'S HERE:
|
||||
|
||||
This source distribution includes libvorbis and an example
|
||||
encoder/player to demonstrate use of libvorbis as well as
|
||||
documentation on the Ogg Vorbis audio coding format.
|
||||
|
||||
You'll need libogg (distributed separately) to compile this library.
|
||||
A more comprehensive set of utilities is available in the vorbis-tools
|
||||
package.
|
||||
|
||||
Directory:
|
||||
|
||||
./lib The source for the libraries, a BSD-license implementation
|
||||
of the public domain Ogg Vorbis audio encoding format.
|
||||
|
||||
./include Library API headers
|
||||
|
||||
./debian Rules/spec files for building Debian .deb packages
|
||||
|
||||
./doc Vorbis documentation
|
||||
|
||||
./examples Example code illustrating programmatic use of libvorbis,
|
||||
libvorbisfile and libvorbisenc
|
||||
|
||||
./mac Codewarrior project files and build tweaks for MacOS.
|
||||
|
||||
./macosx Project files for MacOS X.
|
||||
|
||||
./win32 Win32 projects files and build automation
|
||||
|
||||
./vq Internal utilities for training/building new LSP/residue
|
||||
and auxiliary codebooks.
|
||||
|
||||
CONTACT:
|
||||
|
||||
The Ogg homepage is located at 'http://www.xiph.org/ogg/'.
|
||||
Vorbis's homepage is located at 'http://www.xiph.org/vorbis/'.
|
||||
Up to date technical documents, contact information, source code and
|
||||
pre-built utilities may be found there.
|
||||
|
||||
The user website for Ogg Vorbis software and audio is http://vorbis.com/
|
||||
|
||||
BUILDING FROM TRUNK:
|
||||
|
||||
Development source is under subversion revision control at
|
||||
https://svn.xiph.org/trunk/vorbis/. 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.
|
||||
|
||||
[update or checkout latest source]
|
||||
./autogen.sh
|
||||
make
|
||||
|
||||
and as root if desired:
|
||||
|
||||
make install
|
||||
|
||||
This will install the Vorbis libraries (static and shared) into
|
||||
/usr/local/lib, includes into /usr/local/include and API manpages
|
||||
(once we write some) into /usr/local/man.
|
||||
|
||||
Documentation building requires xsltproc and pdfxmltex.
|
||||
|
||||
BUILDING FROM TARBALL DISTRIBUTIONS:
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
and optionally (as root):
|
||||
make install
|
||||
|
||||
BUILDING RPMS:
|
||||
|
||||
after normal configuring:
|
||||
|
||||
make dist
|
||||
rpm -ta libvorbis-<version>.tar.gz
|
||||
|
||||
BUILDING ON MACOS 9:
|
||||
|
||||
Vorbis on MacOS 9 is built using Metroworks CodeWarrior. To build it,
|
||||
first verify that the Ogg libraries are already built following the
|
||||
instructions in the Ogg module README. Open vorbis/mac/libvorbis.mcp,
|
||||
switch to the "Targets" pane, select everything, and make the project.
|
||||
Do the same thing to build libvorbisenc.mcp, and libvorbisfile.mcp (in
|
||||
that order). In vorbis/mac/Output you will now have both debug and final
|
||||
versions of Vorbis shared libraries to link your projects against.
|
||||
|
||||
To build a project using Ogg Vorbis, add access paths to your
|
||||
CodeWarrior project for the ogg/include, ogg/mac/Output,
|
||||
vorbis/include, and vorbis/mac/Output folders. Be sure that
|
||||
"interpret DOS and Unix paths" is turned on in your project; it can
|
||||
be found in the "access paths" pane in your project settings. Now
|
||||
simply add the shared libraries you need to your project (OggLib and
|
||||
VorbisLib at least) and #include "ogg/ogg.h" and "vorbis/codec.h"
|
||||
wherever you need to access Ogg and Vorbis functionality.
|
||||
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: single-block PCM analysis mode dispatch
|
||||
last mod: $Id: analysis.c 16226 2009-07-08 06:43:49Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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
|
||||
+144
@@ -0,0 +1,144 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis backend and mapping structures; needed for
|
||||
static mode headers
|
||||
last mod: $Id: backends.h 16962 2010-03-11 07:30:34Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* this is exposed up here because we need it for static modes.
|
||||
Lookups for each backend aren't exposed because there's no reason
|
||||
to do so */
|
||||
|
||||
#ifndef _vorbis_backend_h_
|
||||
#define _vorbis_backend_h_
|
||||
|
||||
#include "codec_internal.h"
|
||||
|
||||
/* this would all be simpler/shorter with templates, but.... */
|
||||
/* Floor backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info_floor *,oggpack_buffer *);
|
||||
vorbis_info_floor *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
vorbis_look_floor *(*look) (vorbis_dsp_state *,vorbis_info_floor *);
|
||||
void (*free_info) (vorbis_info_floor *);
|
||||
void (*free_look) (vorbis_look_floor *);
|
||||
void *(*inverse1) (struct vorbis_block *,vorbis_look_floor *);
|
||||
int (*inverse2) (struct vorbis_block *,vorbis_look_floor *,
|
||||
void *buffer,float *);
|
||||
} vorbis_func_floor;
|
||||
|
||||
typedef struct{
|
||||
int order;
|
||||
long rate;
|
||||
long barkmap;
|
||||
|
||||
int ampbits;
|
||||
int ampdB;
|
||||
|
||||
int numbooks; /* <= 16 */
|
||||
int books[16];
|
||||
|
||||
float lessthan; /* encode-only config setting hacks for libvorbis */
|
||||
float greaterthan; /* encode-only config setting hacks for libvorbis */
|
||||
|
||||
} vorbis_info_floor0;
|
||||
|
||||
|
||||
#define VIF_POSIT 63
|
||||
#define VIF_CLASS 16
|
||||
#define VIF_PARTS 31
|
||||
typedef struct{
|
||||
int partitions; /* 0 to 31 */
|
||||
int partitionclass[VIF_PARTS]; /* 0 to 15 */
|
||||
|
||||
int class_dim[VIF_CLASS]; /* 1 to 8 */
|
||||
int class_subs[VIF_CLASS]; /* 0,1,2,3 (bits: 1<<n poss) */
|
||||
int class_book[VIF_CLASS]; /* subs ^ dim entries */
|
||||
int class_subbook[VIF_CLASS][8]; /* [VIF_CLASS][subs] */
|
||||
|
||||
|
||||
int mult; /* 1 2 3 or 4 */
|
||||
int postlist[VIF_POSIT+2]; /* first two implicit */
|
||||
|
||||
|
||||
/* encode side analysis parameters */
|
||||
float maxover;
|
||||
float maxunder;
|
||||
float maxerr;
|
||||
|
||||
float twofitweight;
|
||||
float twofitatten;
|
||||
|
||||
int n;
|
||||
|
||||
} vorbis_info_floor1;
|
||||
|
||||
/* Residue backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info_residue *,oggpack_buffer *);
|
||||
vorbis_info_residue *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
vorbis_look_residue *(*look) (vorbis_dsp_state *,
|
||||
vorbis_info_residue *);
|
||||
void (*free_info) (vorbis_info_residue *);
|
||||
void (*free_look) (vorbis_look_residue *);
|
||||
long **(*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
|
||||
+253
@@ -0,0 +1,253 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
last mod: $Id: bitrate.c 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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);
|
||||
}
|
||||
+59
@@ -0,0 +1,59 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
last mod: $Id: bitrate.h 13293 2007-07-24 00:09:47Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_BITRATE_H_
|
||||
#define _V_BITRATE_H_
|
||||
|
||||
#include "../../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
|
||||
+1033
File diff suppressed because it is too large
Load Diff
+12256
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
+479
@@ -0,0 +1,479 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic codebook pack/unpack/code/decode operations
|
||||
last mod: $Id: codebook.c 17553 2010-10-21 17:54:26Z tterribe $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "../../ogg.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++){
|
||||
long thisx=c->lengthlist[i];
|
||||
long last=c->lengthlist[i-1];
|
||||
if(thisx>last){
|
||||
for(j=last;j<thisx;j++){
|
||||
oggpack_write(opb,i-count,_ilog(c->entries-count));
|
||||
count=i;
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write(opb,i-count,_ilog(c->entries-count));
|
||||
|
||||
}else{
|
||||
/* length random. Again, we don't code the codeword itself, just
|
||||
the length. This time, though, we have to encode each length */
|
||||
oggpack_write(opb,0,1); /* unordered */
|
||||
|
||||
/* algortihmic mapping has use for 'unused entries', which we tag
|
||||
here. The algorithmic mapping happens as usual, but the unused
|
||||
entry has no codeword. */
|
||||
for(i=0;i<c->entries;i++)
|
||||
if(c->lengthlist[i]==0)break;
|
||||
|
||||
if(i==c->entries){
|
||||
oggpack_write(opb,0,1); /* no unused entries */
|
||||
for(i=0;i<c->entries;i++)
|
||||
oggpack_write(opb,c->lengthlist[i]-1,5);
|
||||
}else{
|
||||
oggpack_write(opb,1,1); /* we have unused entries; thus we tag */
|
||||
for(i=0;i<c->entries;i++){
|
||||
if(c->lengthlist[i]==0){
|
||||
oggpack_write(opb,0,1);
|
||||
}else{
|
||||
oggpack_write(opb,1,1);
|
||||
oggpack_write(opb,c->lengthlist[i]-1,5);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* is the entry number the desired return value, or do we have a
|
||||
mapping? If we have a mapping, what type? */
|
||||
oggpack_write(opb,c->maptype,4);
|
||||
switch(c->maptype){
|
||||
case 0:
|
||||
/* no mapping */
|
||||
break;
|
||||
case 1:case 2:
|
||||
/* implicitly populated value mapping */
|
||||
/* explicitly populated value mapping */
|
||||
|
||||
if(!c->quantlist){
|
||||
/* no quantlist? error */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* values that define the dequantization */
|
||||
oggpack_write(opb,c->q_min,32);
|
||||
oggpack_write(opb,c->q_delta,32);
|
||||
oggpack_write(opb,c->q_quant-1,4);
|
||||
oggpack_write(opb,c->q_sequencep,1);
|
||||
|
||||
{
|
||||
int quantvals;
|
||||
switch(c->maptype){
|
||||
case 1:
|
||||
/* a single column of (c->entries/c->dim) quantized values for
|
||||
building a full value list algorithmically (square lattice) */
|
||||
quantvals=_book_maptype1_quantvals(c);
|
||||
break;
|
||||
case 2:
|
||||
/* every value (c->entries*c->dim total) specified explicitly */
|
||||
quantvals=c->entries*c->dim;
|
||||
break;
|
||||
default: /* NOT_REACHABLE */
|
||||
quantvals=-1;
|
||||
}
|
||||
|
||||
/* quantized values */
|
||||
for(i=0;i<quantvals;i++)
|
||||
oggpack_write(opb,labs(c->quantlist[i]),c->q_quant);
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* error case; we don't have any other map types now */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* unpacks a codebook from the packet buffer into the codebook struct,
|
||||
readies the codebook auxiliary structures for decode *************/
|
||||
static_codebook *vorbis_staticbook_unpack(oggpack_buffer *opb){
|
||||
long i,j;
|
||||
static_codebook *s=(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(_ilog(s->dim)+_ilog(s->entries)>24)goto _eofout;
|
||||
|
||||
/* codeword ordering.... length ordered or unordered? */
|
||||
switch((int)oggpack_read(opb,1)){
|
||||
case 0:{
|
||||
long unused;
|
||||
/* allocated but unused entries? */
|
||||
unused=oggpack_read(opb,1);
|
||||
if((s->entries*(unused?1:5)+7)>>3>opb->storage-oggpack_bytes(opb))
|
||||
goto _eofout;
|
||||
/* unordered */
|
||||
s->lengthlist=(long*)_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=(long*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
|
||||
|
||||
for(i=0;i<s->entries;){
|
||||
long num=oggpack_read(opb,_ilog(s->entries-i));
|
||||
if(num==-1)goto _eofout;
|
||||
if(length>32 || num>s->entries-i ||
|
||||
(num>0 && (num-1)>>(length-1)>1)){
|
||||
goto _errout;
|
||||
}
|
||||
if(length>32)goto _errout;
|
||||
for(j=0;j<num;j++,i++)
|
||||
s->lengthlist[i]=length;
|
||||
length++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* EOF */
|
||||
goto _eofout;
|
||||
}
|
||||
|
||||
/* Do we have a mapping to unpack? */
|
||||
switch((s->maptype=oggpack_read(opb,4))){
|
||||
case 0:
|
||||
/* no mapping */
|
||||
break;
|
||||
case 1: case 2:
|
||||
/* implicitly populated value mapping */
|
||||
/* explicitly populated value mapping */
|
||||
|
||||
s->q_min=oggpack_read(opb,32);
|
||||
s->q_delta=oggpack_read(opb,32);
|
||||
s->q_quant=oggpack_read(opb,4)+1;
|
||||
s->q_sequencep=oggpack_read(opb,1);
|
||||
if(s->q_sequencep==-1)goto _eofout;
|
||||
|
||||
{
|
||||
int quantvals=0;
|
||||
switch(s->maptype){
|
||||
case 1:
|
||||
quantvals=(s->dim==0?0:_book_maptype1_quantvals(s));
|
||||
break;
|
||||
case 2:
|
||||
quantvals=s->entries*s->dim;
|
||||
break;
|
||||
}
|
||||
|
||||
/* quantized values */
|
||||
if(((quantvals * s->q_quant + 7) >> 3) > opb->storage-oggpack_bytes(opb))
|
||||
goto _eofout;
|
||||
s->quantlist=(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;
|
||||
}
|
||||
|
||||
lok = oggpack_look(b, read);
|
||||
|
||||
while(lok<0 && read>1)
|
||||
lok = oggpack_look(b, --read);
|
||||
if(lok<0)return -1;
|
||||
|
||||
/* bisect search for the codeword in the ordered list */
|
||||
{
|
||||
ogg_uint32_t testword=bitreverse((ogg_uint32_t)lok);
|
||||
|
||||
while(hi-lo>1){
|
||||
long p=(hi-lo)>>1;
|
||||
long test=book->codelist[lo+p]>testword;
|
||||
lo+=p&(test-1);
|
||||
hi-=p&(-test);
|
||||
}
|
||||
|
||||
if(book->dec_codelengths[lo]<=read){
|
||||
oggpack_adv(b, book->dec_codelengths[lo]);
|
||||
return(lo);
|
||||
}
|
||||
}
|
||||
|
||||
oggpack_adv(b, read);
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Decode side is specced and easier, because we don't need to find
|
||||
matches using different criteria; we simply read and map. There are
|
||||
two things we need to do 'depending':
|
||||
|
||||
We may need to support interleave. We don't really, but it's
|
||||
convenient to do it here rather than rebuild the vector later.
|
||||
|
||||
Cascades may be additive or multiplicitive; this is not inherent in
|
||||
the codebook, but set in the code using the codebook. Like
|
||||
interleaving, it's easiest to do it here.
|
||||
addmul==0 -> declarative (set the value)
|
||||
addmul==1 -> additive
|
||||
addmul==2 -> multiplicitive */
|
||||
|
||||
/* returns the [original, not compacted] entry number or -1 on eof *********/
|
||||
long vorbis_book_decode(codebook *book, oggpack_buffer *b){
|
||||
if(book->used_entries>0){
|
||||
long packed_entry=decode_packed_entry_number(book,b);
|
||||
if(packed_entry>=0)
|
||||
return(book->dec_index[packed_entry]);
|
||||
}
|
||||
|
||||
/* if there's no dec_index, the codebook unpacking isn't collapsed */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* returns 0 on OK or -1 on eof *************************************/
|
||||
long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
if(book->used_entries>0){
|
||||
int step=n/book->dim;
|
||||
long *entry = (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;j<step;j++)
|
||||
a[o+j]+=t[j][i];
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long vorbis_book_decodev_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
if(book->used_entries>0){
|
||||
int i,j,entry;
|
||||
float *t;
|
||||
|
||||
if(book->dim>8){
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
for (j=0;j<book->dim;)
|
||||
a[i++]+=t[j++];
|
||||
}
|
||||
}else{
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
j=0;
|
||||
switch((int)book->dim){
|
||||
case 8:
|
||||
a[i++]+=t[j++];
|
||||
case 7:
|
||||
a[i++]+=t[j++];
|
||||
case 6:
|
||||
a[i++]+=t[j++];
|
||||
case 5:
|
||||
a[i++]+=t[j++];
|
||||
case 4:
|
||||
a[i++]+=t[j++];
|
||||
case 3:
|
||||
a[i++]+=t[j++];
|
||||
case 2:
|
||||
a[i++]+=t[j++];
|
||||
case 1:
|
||||
a[i++]+=t[j++];
|
||||
case 0:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long vorbis_book_decodev_set(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
if(book->used_entries>0){
|
||||
int i,j,entry;
|
||||
float *t;
|
||||
|
||||
for(i=0;i<n;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
t = book->valuelist+entry*book->dim;
|
||||
for (j=0;j<book->dim;)
|
||||
a[i++]=t[j++];
|
||||
}
|
||||
}else{
|
||||
int i,j;
|
||||
|
||||
for(i=0;i<n;){
|
||||
for (j=0;j<book->dim;)
|
||||
a[i++]=0.f;
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
long vorbis_book_decodevv_add(codebook *book,float **a,long offset,int ch,
|
||||
oggpack_buffer *b,int n){
|
||||
|
||||
long i,j,entry;
|
||||
int chptr=0;
|
||||
if(book->used_entries>0){
|
||||
for(i=offset/ch;i<(offset+n)/ch;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
{
|
||||
const float *t = book->valuelist+entry*book->dim;
|
||||
for (j=0;j<book->dim;j++){
|
||||
a[chptr++][i]+=t[j];
|
||||
if(chptr==ch){
|
||||
chptr=0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic shared codebook operations
|
||||
last mod: $Id: codebook.h 17030 2010-03-25 06:52:55Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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 */
|
||||
long *lengthlist; /* codeword lengths in bits */
|
||||
|
||||
/* mapping ***************************************************************/
|
||||
int maptype; /* 0=none
|
||||
1=implicitly populated values from map column
|
||||
2=listed arbitrary values */
|
||||
|
||||
/* The below does a linear, single monotonic sequence mapping. */
|
||||
long q_min; /* packed 32 bit float; quant value 0 maps to minval */
|
||||
long q_delta; /* packed 32 bit float; val 1 - val 0 == delta */
|
||||
int q_quant; /* bits: 0 < quant <= 16 */
|
||||
int q_sequencep; /* bitflag */
|
||||
|
||||
long *quantlist; /* map == 1: (int)(entries^(1/dim)) element column map
|
||||
map == 2: list of dim*entries quantized entry vals
|
||||
*/
|
||||
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 int _ilog(unsigned int v);
|
||||
extern long _book_maptype1_quantvals(const static_codebook *b);
|
||||
|
||||
extern int vorbis_book_besterror(codebook *book,float *a,int step,int addmul);
|
||||
extern long vorbis_book_codeword(codebook *book,int entry);
|
||||
extern long vorbis_book_codelen(codebook *book,int entry);
|
||||
|
||||
|
||||
|
||||
extern int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b);
|
||||
extern 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
|
||||
+187
@@ -0,0 +1,187 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec_internal.h 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_CODECI_H_
|
||||
#define _V_CODECI_H_
|
||||
|
||||
#include "envelope.h"
|
||||
#include "codebook.h"
|
||||
|
||||
#define BLOCKTYPE_IMPULSE 0
|
||||
#define BLOCKTYPE_PADDING 1
|
||||
#define BLOCKTYPE_TRANSITION 0
|
||||
#define BLOCKTYPE_LONG 1
|
||||
|
||||
#define PACKETBLOBS 15
|
||||
|
||||
typedef struct vorbis_block_internal{
|
||||
float **pcmdelay; /* this is a pointer into local storage */
|
||||
float ampmax;
|
||||
int blocktype;
|
||||
|
||||
oggpack_buffer *packetblob[PACKETBLOBS]; /* initialized, must be freed;
|
||||
blob [PACKETBLOBS/2] points to
|
||||
the oggpack_buffer in the
|
||||
main vorbis_block */
|
||||
} vorbis_block_internal;
|
||||
|
||||
typedef void vorbis_look_floor;
|
||||
typedef void vorbis_look_residue;
|
||||
typedef void vorbis_look_transform;
|
||||
|
||||
/* mode ************************************************************/
|
||||
typedef struct {
|
||||
int blockflag;
|
||||
int windowtype;
|
||||
int transformtype;
|
||||
int mapping;
|
||||
} vorbis_info_mode;
|
||||
|
||||
typedef void vorbis_info_floor;
|
||||
typedef void vorbis_info_residue;
|
||||
typedef void vorbis_info_mapping;
|
||||
|
||||
#include "psy.h"
|
||||
#include "bitrate.h"
|
||||
|
||||
static int ilog(unsigned int v){
|
||||
int ret=0;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
static int ilog2(unsigned int v){
|
||||
int ret=0;
|
||||
if(v)--v;
|
||||
while(v){
|
||||
ret++;
|
||||
v>>=1;
|
||||
}
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
+375
@@ -0,0 +1,375 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis
|
||||
last mod: $Id: envelope.c 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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;
|
||||
}
|
||||
+80
@@ -0,0 +1,80 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis and manipulation
|
||||
last mod: $Id: envelope.h 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_ENVELOPE_
|
||||
#define _V_ENVELOPE_
|
||||
|
||||
#include "mdct.h"
|
||||
|
||||
#define VE_PRE 16
|
||||
#define VE_WIN 4
|
||||
#define VE_POST 2
|
||||
#define VE_AMP (VE_PRE+VE_POST-1)
|
||||
|
||||
#define VE_BANDS 7
|
||||
#define VE_NEARDC 15
|
||||
|
||||
#define VE_MINSTRETCH 2 /* a bit less than short block */
|
||||
#define VE_MAXSTRETCH 12 /* one-third full block */
|
||||
|
||||
typedef struct {
|
||||
float ampbuf[VE_AMP];
|
||||
int ampptr;
|
||||
|
||||
float nearDC[VE_NEARDC];
|
||||
float nearDC_acc;
|
||||
float nearDC_partialacc;
|
||||
int nearptr;
|
||||
|
||||
} envelope_filter_state;
|
||||
|
||||
typedef struct {
|
||||
int begin;
|
||||
int end;
|
||||
float *window;
|
||||
float total;
|
||||
} envelope_band;
|
||||
|
||||
typedef struct {
|
||||
int ch;
|
||||
int winlength;
|
||||
int searchstep;
|
||||
float minenergy;
|
||||
|
||||
mdct_lookup mdct;
|
||||
float *mdct_win;
|
||||
|
||||
envelope_band band[VE_BANDS];
|
||||
envelope_filter_state *filter;
|
||||
int stretch;
|
||||
|
||||
int *mark;
|
||||
|
||||
long storage;
|
||||
long current;
|
||||
long curmark;
|
||||
long cursor;
|
||||
} envelope_lookup;
|
||||
|
||||
extern void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi);
|
||||
extern void _ve_envelope_clear(envelope_lookup *e);
|
||||
extern long _ve_envelope_search(vorbis_dsp_state *v);
|
||||
extern void _ve_envelope_shift(envelope_lookup *e,long shift);
|
||||
extern int _ve_envelope_mark(vorbis_dsp_state *v);
|
||||
|
||||
|
||||
#endif
|
||||
+223
@@ -0,0 +1,223 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: floor backend 0 implementation
|
||||
last mod: $Id: floor0.c 17558 2010-10-22 00:24:41Z tterribe $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
|
||||
#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,_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));
|
||||
|
||||
for(j=0;j<look->m;j+=b->dim)
|
||||
if(vorbis_book_decodev_set(b,lsp+j,&vb->opb,b->dim)==-1)goto eop;
|
||||
for(j=0;j<look->m;){
|
||||
for(k=0;k<b->dim;k++,j++)lsp[j]+=last;
|
||||
last=lsp[j-1];
|
||||
}
|
||||
|
||||
lsp[look->m]=amp;
|
||||
return(lsp);
|
||||
}
|
||||
}
|
||||
eop:
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
static int floor0_inverse2(vorbis_block *vb,vorbis_look_floor *i,
|
||||
void *memo,float *out){
|
||||
vorbis_look_floor0 *look=(vorbis_look_floor0 *)i;
|
||||
vorbis_info_floor0 *info=look->vi;
|
||||
|
||||
floor0_map_lazy_init(vb,info,look);
|
||||
|
||||
if(memo){
|
||||
float *lsp=(float *)memo;
|
||||
float amp=lsp[look->m];
|
||||
|
||||
/* take the coefficients back to a spectral envelope curve */
|
||||
vorbis_lsp_to_curve(out,
|
||||
look->linearmap[vb->W],
|
||||
look->n[vb->W],
|
||||
look->ln,
|
||||
lsp,look->m,amp,(float)info->ampdB);
|
||||
return(1);
|
||||
}
|
||||
memset(out,0,sizeof(*out)*look->n[vb->W]);
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* export hooks */
|
||||
const vorbis_func_floor floor0_exportbundle={
|
||||
NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
|
||||
&floor0_free_look,&floor0_inverse1,&floor0_inverse2
|
||||
};
|
||||
+1080
File diff suppressed because it is too large
Load Diff
+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-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: highlevel encoder setup struct separated out for vorbisenc clarity
|
||||
last mod: $Id: highlevel.h 17195 2010-05-05 21:49:51Z giles $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
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;
|
||||
+660
@@ -0,0 +1,660 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2010 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: maintain the info structure, info <-> header packets
|
||||
last mod: $Id: info.c 17584 2010-11-01 19:26:16Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* general handling of the header and the vorbis_info structure (and
|
||||
substructures) */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include "../../ogg.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.2"
|
||||
#define ENCODE_VENDOR_STRING "Xiph.Org libVorbis I 20101101 (Schaufenugget)"
|
||||
|
||||
/* 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);
|
||||
}
|
||||
}
|
||||
|
||||
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){
|
||||
char *comment=(char*)alloca(strlen(tag)+strlen(contents)+2); /* +2 for = and \0 */
|
||||
strcpy(comment, tag);
|
||||
strcat(comment, "=");
|
||||
strcat(comment, contents);
|
||||
vorbis_comment_add(vc, comment);
|
||||
}
|
||||
|
||||
/* This is more or less the same as strncasecmp - but that doesn't exist
|
||||
* everywhere, and this is a fairly trivial function, so we include it */
|
||||
static int tagcompare(const char *s1, const char *s2, int n){
|
||||
int c=0;
|
||||
while(c < n){
|
||||
if(toupper(s1[c]) != toupper(s2[c]))
|
||||
return !0;
|
||||
c++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
char *vorbis_comment_query(vorbis_comment *vc, const char *tag, int count){
|
||||
long i;
|
||||
int found = 0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = (char*)alloca(taglen+ 1);
|
||||
|
||||
strcpy(fulltag, tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(!tagcompare(vc->user_comments[i], fulltag, taglen)){
|
||||
if(count == found)
|
||||
/* We return a pointer to the data, not a copy */
|
||||
return vc->user_comments[i] + taglen;
|
||||
else
|
||||
found++;
|
||||
}
|
||||
}
|
||||
return NULL; /* didn't find anything */
|
||||
}
|
||||
|
||||
int vorbis_comment_query_count(vorbis_comment *vc, const char *tag){
|
||||
int i,count=0;
|
||||
int taglen = strlen(tag)+1; /* +1 for the = we append */
|
||||
char *fulltag = (char*)alloca(taglen+1);
|
||||
strcpy(fulltag,tag);
|
||||
strcat(fulltag, "=");
|
||||
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(!tagcompare(vc->user_comments[i], fulltag, taglen))
|
||||
count++;
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
void vorbis_comment_clear(vorbis_comment *vc){
|
||||
if(vc){
|
||||
long i;
|
||||
if(vc->user_comments){
|
||||
for(i=0;i<vc->comments;i++)
|
||||
if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
|
||||
_ogg_free(vc->user_comments);
|
||||
}
|
||||
if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
|
||||
if(vc->vendor)_ogg_free(vc->vendor);
|
||||
memset(vc,0,sizeof(*vc));
|
||||
}
|
||||
}
|
||||
|
||||
/* blocksize 0 is guaranteed to be short, 1 is guaranteed to be long.
|
||||
They may be equal, but short will never ge greater than long */
|
||||
int vorbis_info_blocksize(vorbis_info *vi,int zo){
|
||||
codec_setup_info *ci = (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;
|
||||
if(!ci)return(OV_EFAULT);
|
||||
|
||||
vi->version=oggpack_read(opb,32);
|
||||
if(vi->version!=0)return(OV_EVERSION);
|
||||
|
||||
vi->channels=oggpack_read(opb,8);
|
||||
vi->rate=oggpack_read(opb,32);
|
||||
|
||||
vi->bitrate_upper=oggpack_read(opb,32);
|
||||
vi->bitrate_nominal=oggpack_read(opb,32);
|
||||
vi->bitrate_lower=oggpack_read(opb,32);
|
||||
|
||||
ci->blocksizes[0]=1<<oggpack_read(opb,4);
|
||||
ci->blocksizes[1]=1<<oggpack_read(opb,4);
|
||||
|
||||
if(vi->rate<1)goto err_out;
|
||||
if(vi->channels<1)goto err_out;
|
||||
if(ci->blocksizes[0]<64)goto err_out;
|
||||
if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
|
||||
if(ci->blocksizes[1]>8192)goto err_out;
|
||||
|
||||
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_info_clear(vi);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
|
||||
int i;
|
||||
int vendorlen=oggpack_read(opb,32);
|
||||
if(vendorlen<0)goto err_out;
|
||||
if(vendorlen>opb->storage-8)goto err_out;
|
||||
vc->vendor=(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;
|
||||
if(!ci)return(OV_EFAULT);
|
||||
|
||||
/* codebooks */
|
||||
ci->books=oggpack_read(opb,8)+1;
|
||||
if(ci->books<=0)goto err_out;
|
||||
for(i=0;i<ci->books;i++){
|
||||
ci->book_param[i]=vorbis_staticbook_unpack(opb);
|
||||
if(!ci->book_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* time backend settings; hooks are unused */
|
||||
{
|
||||
int times=oggpack_read(opb,6)+1;
|
||||
if(times<=0)goto err_out;
|
||||
for(i=0;i<times;i++){
|
||||
int test=oggpack_read(opb,16);
|
||||
if(test<0 || test>=VI_TIMEB)goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* floor backend settings */
|
||||
ci->floors=oggpack_read(opb,6)+1;
|
||||
if(ci->floors<=0)goto err_out;
|
||||
for(i=0;i<ci->floors;i++){
|
||||
ci->floor_type[i]=oggpack_read(opb,16);
|
||||
if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
|
||||
ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
|
||||
if(!ci->floor_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* residue backend settings */
|
||||
ci->residues=oggpack_read(opb,6)+1;
|
||||
if(ci->residues<=0)goto err_out;
|
||||
for(i=0;i<ci->residues;i++){
|
||||
ci->residue_type[i]=oggpack_read(opb,16);
|
||||
if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
|
||||
ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
|
||||
if(!ci->residue_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* map backend settings */
|
||||
ci->maps=oggpack_read(opb,6)+1;
|
||||
if(ci->maps<=0)goto err_out;
|
||||
for(i=0;i<ci->maps;i++){
|
||||
ci->map_type[i]=oggpack_read(opb,16);
|
||||
if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
|
||||
ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
|
||||
if(!ci->map_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* mode settings */
|
||||
ci->modes=oggpack_read(opb,6)+1;
|
||||
if(ci->modes<=0)goto err_out;
|
||||
for(i=0;i<ci->modes;i++){
|
||||
ci->mode_param[i]=(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);
|
||||
}
|
||||
|
||||
return(_vorbis_unpack_comment(vc,&opb));
|
||||
|
||||
case 0x05: /* least significant *bit* is read first */
|
||||
if(vi->rate==0 || vc->vendor==NULL){
|
||||
/* um... we didn;t get the initial header or comments yet */
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
return(_vorbis_unpack_books(vi,&opb));
|
||||
|
||||
default:
|
||||
/* Not a valid vorbis header type */
|
||||
return(OV_EBADHEADER);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
/* pack side **********************************************************/
|
||||
|
||||
static int _vorbis_pack_info(oggpack_buffer *opb,vorbis_info *vi){
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
if(!ci)return(OV_EFAULT);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(opb,0x01,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* basic information about the stream */
|
||||
oggpack_write(opb,0x00,32);
|
||||
oggpack_write(opb,vi->channels,8);
|
||||
oggpack_write(opb,vi->rate,32);
|
||||
|
||||
oggpack_write(opb,vi->bitrate_upper,32);
|
||||
oggpack_write(opb,vi->bitrate_nominal,32);
|
||||
oggpack_write(opb,vi->bitrate_lower,32);
|
||||
|
||||
oggpack_write(opb,ilog2(ci->blocksizes[0]),4);
|
||||
oggpack_write(opb,ilog2(ci->blocksizes[1]),4);
|
||||
oggpack_write(opb,1,1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int _vorbis_pack_comment(oggpack_buffer *opb,vorbis_comment *vc){
|
||||
int bytes = strlen(ENCODE_VENDOR_STRING);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(opb,0x03,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* vendor */
|
||||
oggpack_write(opb,bytes,32);
|
||||
_v_writestring(opb,ENCODE_VENDOR_STRING, bytes);
|
||||
|
||||
/* comments */
|
||||
|
||||
oggpack_write(opb,vc->comments,32);
|
||||
if(vc->comments){
|
||||
int i;
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(vc->user_comments[i]){
|
||||
oggpack_write(opb,vc->comment_lengths[i],32);
|
||||
_v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
|
||||
}else{
|
||||
oggpack_write(opb,0,32);
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write(opb,1,1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
|
||||
codec_setup_info *ci=(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)) 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;
|
||||
|
||||
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){
|
||||
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){
|
||||
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;
|
||||
|
||||
#ifdef __GNUC__
|
||||
granuleoff |= 0x7ffffffffLL;
|
||||
#else
|
||||
granuleoff |= 0x7ffffffff;
|
||||
#endif
|
||||
return(((double)granulepos+2+granuleoff+granuleoff)/v->vi->rate);
|
||||
}
|
||||
}
|
||||
|
||||
const char *vorbis_version_string(void){
|
||||
return GENERAL_VENDOR_STRING;
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
last mod: $Id: lookup.c 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include <math.h>
|
||||
#include "lookup.h"
|
||||
#include "lookup_data.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
float vorbis_coslook(float a){
|
||||
double d=a*(.31830989*(float)COS_LOOKUP_SZ);
|
||||
int i=vorbis_ftoi(d-.5);
|
||||
|
||||
return COS_LOOKUP[i]+ (d-i)*(COS_LOOKUP[i+1]-COS_LOOKUP[i]);
|
||||
}
|
||||
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
float vorbis_invsqlook(float a){
|
||||
double d=a*(2.f*(float)INVSQ_LOOKUP_SZ)-(float)INVSQ_LOOKUP_SZ;
|
||||
int i=vorbis_ftoi(d-.5f);
|
||||
return INVSQ_LOOKUP[i]+ (d-i)*(INVSQ_LOOKUP[i+1]-INVSQ_LOOKUP[i]);
|
||||
}
|
||||
|
||||
/* interpolated 1./sqrt(p) where .5 <= p < 1. */
|
||||
float vorbis_invsq2explook(int a){
|
||||
return INVSQ2EXP_LOOKUP[a-INVSQ2EXP_LOOKUP_MIN];
|
||||
}
|
||||
|
||||
#include <stdio.h>
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
float vorbis_fromdBlook(float a){
|
||||
int i=vorbis_ftoi(a*((float)(-(1<<FROMdB2_SHIFT)))-.5f);
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
/* interpolated 1./sqrt(p) where .5 <= a < 1. (.100000... to .111111...) in
|
||||
16.16 format
|
||||
|
||||
returns in m.8 format */
|
||||
long vorbis_invsqlook_i(long a,long e){
|
||||
long i=(a&0x7fff)>>(INVSQ_LOOKUP_I_SHIFT-1);
|
||||
long d=(a&INVSQ_LOOKUP_I_MASK)<<(16-INVSQ_LOOKUP_I_SHIFT); /* 0.16 */
|
||||
long val=INVSQ_LOOKUP_I[i]- /* 1.16 */
|
||||
(((INVSQ_LOOKUP_I[i]-INVSQ_LOOKUP_I[i+1])* /* 0.16 */
|
||||
d)>>16); /* result 1.16 */
|
||||
|
||||
e+=32;
|
||||
if(e&1)val=(val*5792)>>13; /* multiply val by 1/sqrt(2) */
|
||||
e=(e>>1)-8;
|
||||
|
||||
return(val>>e);
|
||||
}
|
||||
|
||||
/* interpolated lookup based fromdB function, domain -140dB to 0dB only */
|
||||
/* a is in n.12 format */
|
||||
float vorbis_fromdBlook_i(long a){
|
||||
int i=(-a)>>(12-FROMdB2_SHIFT);
|
||||
return (i<0)?1.f:
|
||||
((i>=(FROMdB_LOOKUP_SZ<<FROMdB_SHIFT))?0.f:
|
||||
FROMdB_LOOKUP[i>>FROMdB_SHIFT]*FROMdB2_LOOKUP[i&FROMdB2_MASK]);
|
||||
}
|
||||
|
||||
/* interpolated lookup based cos function, domain 0 to PI only */
|
||||
/* a is in 0.16 format, where 0==0, 2^^16-1==PI, return 0.14 */
|
||||
long vorbis_coslook_i(long a){
|
||||
int i=a>>COS_LOOKUP_I_SHIFT;
|
||||
int d=a&COS_LOOKUP_I_MASK;
|
||||
return COS_LOOKUP_I[i]- ((d*(COS_LOOKUP_I[i]-COS_LOOKUP_I[i+1]))>>
|
||||
COS_LOOKUP_I_SHIFT);
|
||||
}
|
||||
|
||||
#endif
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
last mod: $Id: lookup.h 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
extern float vorbis_coslook(float a);
|
||||
extern float vorbis_invsqlook(float a);
|
||||
extern float vorbis_invsq2explook(int a);
|
||||
extern float vorbis_fromdBlook(float a);
|
||||
#endif
|
||||
#ifdef INT_LOOKUP
|
||||
extern long vorbis_invsqlook_i(long a,long e);
|
||||
extern long vorbis_coslook_i(long a);
|
||||
extern float vorbis_fromdBlook_i(long a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
+192
@@ -0,0 +1,192 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup data; generated by lookups.pl; edit there
|
||||
last mod: $Id: lookup_data.h 16037 2009-05-26 21:10:58Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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
|
||||
+160
@@ -0,0 +1,160 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
last mod: $Id: lpc.c 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Some of these routines (autocorrelator, LPC coefficient estimator)
|
||||
are derived from code written by Jutta Degener and Carsten Bormann;
|
||||
thus we include their copyright below. The entirety of this file
|
||||
is freely redistributable on the condition that both of these
|
||||
copyright notices are preserved without modification. */
|
||||
|
||||
/* Preserved Copyright: *********************************************/
|
||||
|
||||
/* Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universita"t Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universita"t
|
||||
Berlin are deemed to have made any representations as to the
|
||||
suitability of this software for any purpose nor are held responsible
|
||||
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
|
||||
THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
|
||||
*********************************************************************/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include "os.h"
|
||||
#include "smallft.h"
|
||||
#include "lpc.h"
|
||||
#include "scales.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* Autocorrelation LPC coeff generation algorithm invented by
|
||||
N. Levinson in 1947, modified by J. Durbin in 1959. */
|
||||
|
||||
/* Input : n elements of time doamin data
|
||||
Output: m lpc coefficients, excitation energy */
|
||||
|
||||
float vorbis_lpc_from_data(float *data,float *lpci,int n,int m){
|
||||
double *aut=(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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2007 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LPC low level routines
|
||||
last mod: $Id: lpc.h 16037 2009-05-26 21:10:58Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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 http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LSP (also called LSF) conversion routines
|
||||
last mod: $Id: lsp.c 17538 2010-10-15 02:52:29Z tterribe $
|
||||
|
||||
The LSP generation code is taken (with minimal modification and a
|
||||
few bugfixes) from "On the Computation of the LSP Frequencies" by
|
||||
Joseph Rothweiler (see http://www.rothweiler.us for contact info).
|
||||
The paper is available at:
|
||||
|
||||
http://www.myown1.com/joe/lsf
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* Note that the lpc-lsp conversion finds the roots of polynomial with
|
||||
an iterative root polisher (CACM algorithm 283). It *is* possible
|
||||
to confuse this algorithm into not converging; that should only
|
||||
happen with absurdly closely spaced roots (very sharp peaks in the
|
||||
LPC f response) which in turn should be impossible in our use of
|
||||
the code. If this *does* happen anyway, it's a bug in the floor
|
||||
finder; find the cause of the confusion (probably a single bin
|
||||
spike or accidental near-float-limit resolution problems) and
|
||||
correct it. */
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "lsp.h"
|
||||
#include "os.h"
|
||||
#include "misc.h"
|
||||
#include "lookup.h"
|
||||
#include "scales.h"
|
||||
|
||||
/* three possible LSP to f curve functions; the exact computation
|
||||
(float), a lookup based float implementation, and an integer
|
||||
implementation. The float lookup is likely the optimal choice on
|
||||
any machine with an FPU. The integer implementation is *not* fixed
|
||||
point (due to the need for a large dynamic range and thus a
|
||||
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);
|
||||
}
|
||||
@@ -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-2009 *
|
||||
* by the Xiph.Org Foundation http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: LSP (also called LSF) conversion routines
|
||||
last mod: $Id: lsp.h 16227 2009-07-08 06:58:46Z xiphmont $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
|
||||
#ifndef _V_LSP_H_
|
||||
#define _V_LSP_H_
|
||||
|
||||
extern int vorbis_lpc_to_lsp(float *lpc,float *lsp,int m);
|
||||
|
||||
extern void vorbis_lsp_to_curve(float *curve,int *map,int n,int ln,
|
||||
float *lsp,int m,
|
||||
float amp,float ampoffset);
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user