mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-02-05 03:50:07 +00:00
(Added missing files from last check-in)
This commit is contained in:
parent
4d16424d9c
commit
158a17f08a
262 changed files with 119814 additions and 137 deletions
49
src/audio/audio_file_formats/flac/Flac Licence.txt
Normal file
49
src/audio/audio_file_formats/flac/Flac Licence.txt
Normal file
|
|
@ -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.
|
||||
402
src/audio/audio_file_formats/flac/all.h
Normal file
402
src/audio/audio_file_formats/flac/all.h
Normal file
|
|
@ -0,0 +1,402 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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"
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
/* OPT: an MSVC built-in would be better */
|
||||
static _inline FLAC__uint32 local_swap32_(FLAC__uint32 x)
|
||||
{
|
||||
x = ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF);
|
||||
return (x>>16) | (x<<16);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(_MSC_VER) && defined(_X86_)
|
||||
/* OPT: an MSVC built-in would be better */
|
||||
static void local_swap32_block_(FLAC__uint32 *start, FLAC__uint32 len)
|
||||
{
|
||||
__asm {
|
||||
mov edx, start
|
||||
mov ecx, len
|
||||
test ecx, ecx
|
||||
loop1:
|
||||
jz done1
|
||||
mov eax, [edx]
|
||||
bswap eax
|
||||
mov [edx], eax
|
||||
add edx, 4
|
||||
dec ecx
|
||||
jmp short loop1
|
||||
done1:
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/** \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.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
|
||||
212
src/audio/audio_file_formats/flac/alloc.h
Normal file
212
src/audio/audio_file_formats/flac/alloc.h
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
/* alloc - Convenience routines for safely allocating memory
|
||||
* Copyright (C) 2007 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library 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
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef FLAC__SHARE__ALLOC_H
|
||||
#define FLAC__SHARE__ALLOC_H
|
||||
|
||||
#if 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 !defined _MSC_VER && !defined __MINGW32__ && !defined __EMX__
|
||||
#include <stdint.h> /* for SIZE_MAX in case limits.h didn't get it */
|
||||
#endif
|
||||
#include <stdlib.h> /* for size_t, malloc(), etc */
|
||||
|
||||
#ifndef SIZE_MAX
|
||||
# ifndef SIZE_T_MAX
|
||||
# ifdef _MSC_VER
|
||||
# define SIZE_T_MAX UINT_MAX
|
||||
# else
|
||||
# error
|
||||
# endif
|
||||
# endif
|
||||
# define SIZE_MAX SIZE_T_MAX
|
||||
#endif
|
||||
|
||||
#ifndef FLaC__INLINE
|
||||
#define FLaC__INLINE
|
||||
#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 FLaC__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 FLaC__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 FLaC__INLINE void *safe_malloc_add_2op_(size_t size1, size_t size2)
|
||||
{
|
||||
size2 += size1;
|
||||
if(size2 < size1)
|
||||
return 0;
|
||||
return safe_malloc_(size2);
|
||||
}
|
||||
|
||||
static FLaC__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 FLaC__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);
|
||||
}
|
||||
|
||||
static FLaC__INLINE void *safe_malloc_mul_2op_(size_t size1, size_t size2)
|
||||
#if 0
|
||||
needs support for cases where sizeof(size_t) != 4
|
||||
{
|
||||
/* could be faster #ifdef'ing off SIZEOF_SIZE_T */
|
||||
if(sizeof(size_t) == 4) {
|
||||
if ((double)size1 * (double)size2 < 4294967296.0)
|
||||
return malloc(size1*size2);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
/* better? */
|
||||
{
|
||||
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);
|
||||
}
|
||||
#endif
|
||||
|
||||
static FLaC__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 FLaC__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 FLaC__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;
|
||||
return safe_malloc_mul_2op_(size1, size2);
|
||||
}
|
||||
|
||||
static FLaC__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 FLaC__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 FLaC__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 FLaC__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 FLaC__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
|
||||
45
src/audio/audio_file_formats/flac/assert.h
Normal file
45
src/audio/audio_file_formats/flac/assert.h
Normal file
|
|
@ -0,0 +1,45 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
184
src/audio/audio_file_formats/flac/callback.h
Normal file
184
src/audio/audio_file_formats/flac/callback.h
Normal file
|
|
@ -0,0 +1,184 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
91
src/audio/audio_file_formats/flac/export.h
Normal file
91
src/audio/audio_file_formats/flac/export.h
Normal file
|
|
@ -0,0 +1,91 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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) || !defined(_MSC_VER)
|
||||
#define FLAC_API
|
||||
|
||||
#else
|
||||
|
||||
#ifdef FLAC_API_EXPORTS
|
||||
#define FLAC_API _declspec(dllexport)
|
||||
#else
|
||||
#define FLAC_API _declspec(dllimport)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/** These #defines will mirror the libtool-based library version number, see
|
||||
* http://www.gnu.org/software/libtool/manual.html#Libtool-versioning
|
||||
*/
|
||||
#define FLAC_API_VERSION_CURRENT 10
|
||||
#define FLAC_API_VERSION_REVISION 0 /**< see above */
|
||||
#define FLAC_API_VERSION_AGE 2 /**< 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
|
||||
1010
src/audio/audio_file_formats/flac/format.h
Normal file
1010
src/audio/audio_file_formats/flac/format.h
Normal file
File diff suppressed because it is too large
Load diff
155
src/audio/audio_file_formats/flac/libFLAC/bitmath.c
Normal file
155
src/audio/audio_file_formats/flac/libFLAC/bitmath.c
Normal file
|
|
@ -0,0 +1,155 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "include/private/bitmath.h"
|
||||
#include "../assert.h"
|
||||
|
||||
/* 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
|
||||
*/
|
||||
unsigned FLAC__bitmath_ilog2(FLAC__uint32 v)
|
||||
{
|
||||
unsigned l = 0;
|
||||
FLAC__ASSERT(v > 0);
|
||||
while(v >>= 1)
|
||||
l++;
|
||||
return l;
|
||||
}
|
||||
|
||||
unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v)
|
||||
{
|
||||
unsigned l = 0;
|
||||
FLAC__ASSERT(v > 0);
|
||||
while(v >>= 1)
|
||||
l++;
|
||||
return l;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
1355
src/audio/audio_file_formats/flac/libFLAC/bitreader.c
Normal file
1355
src/audio/audio_file_formats/flac/libFLAC/bitreader.c
Normal file
File diff suppressed because it is too large
Load diff
885
src/audio/audio_file_formats/flac/libFLAC/bitwriter.c
Normal file
885
src/audio/audio_file_formats/flac/libFLAC/bitwriter.c
Normal file
|
|
@ -0,0 +1,885 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcpy(), memset() */
|
||||
#ifdef _MSC_VER
|
||||
#include <winsock.h> /* for ntohl() */
|
||||
#elif defined FLAC__SYS_DARWIN
|
||||
#include <machine/endian.h> /* for ntohl() */
|
||||
#elif defined __MINGW32__
|
||||
#include <winsock.h> /* for ntohl() */
|
||||
#else
|
||||
#include <netinet/in.h> /* for ntohl() */
|
||||
#endif
|
||||
#if 0 /* UNUSED */
|
||||
#include "include/private/bitmath.h"
|
||||
#endif
|
||||
#include "include/private/bitwriter.h"
|
||||
#include "include/private/crc.h"
|
||||
#include "../assert.h"
|
||||
#include "../alloc.h"
|
||||
|
||||
/* Things should be fastest when this matches the machine word size */
|
||||
/* WATCHOUT: if you change this you must also change the following #defines down to SWAP_BE_WORD_TO_HOST below to match */
|
||||
/* WATCHOUT: there are a few places where the code will not work unless bwword is >= 32 bits wide */
|
||||
typedef FLAC__uint32 bwword;
|
||||
#define FLAC__BYTES_PER_WORD 4
|
||||
#define FLAC__BITS_PER_WORD 32
|
||||
#define FLAC__WORD_ALL_ONES ((FLAC__uint32)0xffffffff)
|
||||
/* SWAP_BE_WORD_TO_HOST swaps bytes in a bwword (which is always big-endian) if necessary to match host byte order */
|
||||
#if WORDS_BIGENDIAN
|
||||
#define SWAP_BE_WORD_TO_HOST(x) (x)
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#define SWAP_BE_WORD_TO_HOST(x) local_swap32_(x)
|
||||
#else
|
||||
#define SWAP_BE_WORD_TO_HOST(x) ntohl(x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* The default capacity here doesn't matter too much. The buffer always grows
|
||||
* to hold whatever is written to it. Usually the encoder will stop adding at
|
||||
* a frame or metadata block, then write that out and clear the buffer for the
|
||||
* next one.
|
||||
*/
|
||||
static const unsigned FLAC__BITWRITER_DEFAULT_CAPACITY = 32768u / sizeof(bwword); /* size in words */
|
||||
/* When growing, increment 4K at a time */
|
||||
static const unsigned FLAC__BITWRITER_DEFAULT_INCREMENT = 4096u / sizeof(bwword); /* size in words */
|
||||
|
||||
#define FLAC__WORDS_TO_BITS(words) ((words) * FLAC__BITS_PER_WORD)
|
||||
#define FLAC__TOTAL_BITS(bw) (FLAC__WORDS_TO_BITS((bw)->words) + (bw)->bits)
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x,y) ((x)<(y)?(x):(y))
|
||||
|
||||
/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
|
||||
#ifdef _MSC_VER
|
||||
#define FLAC__U64L(x) x
|
||||
#else
|
||||
#define FLAC__U64L(x) x##LLU
|
||||
#endif
|
||||
|
||||
#ifndef FLaC__INLINE
|
||||
#define FLaC__INLINE
|
||||
#endif
|
||||
|
||||
struct FLAC__BitWriter {
|
||||
bwword *buffer;
|
||||
bwword 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. */
|
||||
static FLAC__bool bitwriter_grow_(FLAC__BitWriter *bw, unsigned bits_to_add)
|
||||
{
|
||||
unsigned new_capacity;
|
||||
bwword *new_buffer;
|
||||
|
||||
FLAC__ASSERT(0 != bw);
|
||||
FLAC__ASSERT(0 != bw->buffer);
|
||||
|
||||
/* calculate total words needed to store 'bits_to_add' additional bits */
|
||||
new_capacity = bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD);
|
||||
|
||||
/* it's possible (due to pessimism in the growth estimation that
|
||||
* leads to this call) that we don't actually need to grow
|
||||
*/
|
||||
if(bw->capacity >= new_capacity)
|
||||
return true;
|
||||
|
||||
/* round up capacity increase to the nearest FLAC__BITWRITER_DEFAULT_INCREMENT */
|
||||
if((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT)
|
||||
new_capacity += FLAC__BITWRITER_DEFAULT_INCREMENT - ((new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
|
||||
/* make sure we got everything right */
|
||||
FLAC__ASSERT(0 == (new_capacity - bw->capacity) % FLAC__BITWRITER_DEFAULT_INCREMENT);
|
||||
FLAC__ASSERT(new_capacity > bw->capacity);
|
||||
FLAC__ASSERT(new_capacity >= bw->words + ((bw->bits + bits_to_add + FLAC__BITS_PER_WORD - 1) / FLAC__BITS_PER_WORD));
|
||||
|
||||
new_buffer = (bwword*)safe_realloc_mul_2op_(bw->buffer, sizeof(bwword), /*times*/new_capacity);
|
||||
if(new_buffer == 0)
|
||||
return false;
|
||||
bw->buffer = new_buffer;
|
||||
bw->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Class constructor/destructor
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__BitWriter *FLAC__bitwriter_new(void)
|
||||
{
|
||||
FLAC__BitWriter *bw = (FLAC__BitWriter*)calloc(1, sizeof(FLAC__BitWriter));
|
||||
/* note that calloc() sets all members to 0 for us */
|
||||
return bw;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_delete(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
FLAC__bitwriter_free(bw);
|
||||
free(bw);
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
*
|
||||
* Public class methods
|
||||
*
|
||||
***********************************************************************/
|
||||
|
||||
FLAC__bool FLAC__bitwriter_init(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
bw->words = bw->bits = 0;
|
||||
bw->capacity = FLAC__BITWRITER_DEFAULT_CAPACITY;
|
||||
bw->buffer = (bwword*)malloc(sizeof(bwword) * bw->capacity);
|
||||
if(bw->buffer == 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_free(FLAC__BitWriter *bw)
|
||||
{
|
||||
FLAC__ASSERT(0 != bw);
|
||||
|
||||
if(0 != bw->buffer)
|
||||
free(bw->buffer);
|
||||
bw->buffer = 0;
|
||||
bw->capacity = 0;
|
||||
bw->words = bw->bits = 0;
|
||||
}
|
||||
|
||||
void FLAC__bitwriter_clear(FLAC__BitWriter *bw)
|
||||
{
|
||||
bw->words = bw->bits = 0;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
FLaC__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 = 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;
|
||||
}
|
||||
|
||||
FLaC__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;
|
||||
}
|
||||
|
||||
FLaC__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);
|
||||
}
|
||||
|
||||
FLaC__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);
|
||||
}
|
||||
|
||||
FLaC__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;
|
||||
}
|
||||
|
||||
FLaC__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(bwword)-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 0 /* OPT: can remove this special case if it doesn't make up for the extra compare (doesn't make a statistically significant difference with msvc or gcc/x86) */
|
||||
if(bw->bits && bw->bits + msbits + lsbits <= FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */
|
||||
/* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword to work in */
|
||||
bw->bits = bw->bits + msbits + lsbits;
|
||||
uval |= mask1; /* set stop bit */
|
||||
uval &= mask2; /* mask off unused top bits */
|
||||
/* NOT: bw->accum <<= msbits + lsbits because msbits+lsbits could be 32, then the shift would be a NOP */
|
||||
bw->accum <<= msbits;
|
||||
bw->accum <<= lsbits;
|
||||
bw->accum |= uval;
|
||||
if(bw->bits == FLAC__BITS_PER_WORD) {
|
||||
bw->buffer[bw->words++] = SWAP_BE_WORD_TO_HOST(bw->accum);
|
||||
bw->bits = 0;
|
||||
/* burying the capacity check down here means we have to grow the buffer a little if there are more vals to do */
|
||||
if(bw->capacity <= bw->words && nvals > 1 && !bitwriter_grow_(bw, 1)) {
|
||||
FLAC__ASSERT(bw->capacity == bw->words);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
#elif 1 /*@@@@@@ OPT: try this version with MSVC6 to see if better, not much difference for gcc-4 */
|
||||
if(bw->bits && bw->bits + msbits + lsbits < FLAC__BITS_PER_WORD) { /* i.e. if the whole thing fits in the current bwword */
|
||||
/* ^^^ if bw->bits is 0 then we may have filled the buffer and have no free bwword 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 {
|
||||
#endif
|
||||
/* 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 bwword*/ && !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;
|
||||
}
|
||||
#if 1
|
||||
}
|
||||
#endif
|
||||
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;
|
||||
}
|
||||
|
||||
#endif
|
||||
423
src/audio/audio_file_formats/flac/libFLAC/cpu.c
Normal file
423
src/audio/audio_file_formats/flac/libFLAC/cpu.c
Normal file
|
|
@ -0,0 +1,423 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "include/private/cpu.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined FLAC__CPU_IA32
|
||||
# include <signal.h>
|
||||
#elif defined FLAC__CPU_PPC
|
||||
# if !defined FLAC__NO_ASM
|
||||
# if defined FLAC__SYS_DARWIN
|
||||
# include <sys/sysctl.h>
|
||||
# include <mach/mach.h>
|
||||
# include <mach/mach_host.h>
|
||||
# include <mach/host_info.h>
|
||||
# include <mach/machine.h>
|
||||
# ifndef CPU_SUBTYPE_POWERPC_970
|
||||
# define CPU_SUBTYPE_POWERPC_970 ((cpu_subtype_t) 100)
|
||||
# endif
|
||||
# else /* FLAC__SYS_DARWIN */
|
||||
|
||||
# include <signal.h>
|
||||
# include <setjmp.h>
|
||||
|
||||
static sigjmp_buf jmpbuf;
|
||||
static volatile sig_atomic_t canjump = 0;
|
||||
|
||||
static void sigill_handler (int sig)
|
||||
{
|
||||
if (!canjump) {
|
||||
signal (sig, SIG_DFL);
|
||||
raise (sig);
|
||||
}
|
||||
canjump = 0;
|
||||
siglongjmp (jmpbuf, 1);
|
||||
}
|
||||
# endif /* FLAC__SYS_DARWIN */
|
||||
# endif /* FLAC__NO_ASM */
|
||||
#endif /* FLAC__CPU_PPC */
|
||||
|
||||
#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
|
||||
|
||||
/* 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;
|
||||
/* 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;
|
||||
/* these are flags in EDX of CPUID AX=80000001 */
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW = 0x80000000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW = 0x40000000;
|
||||
static const unsigned FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX = 0x00400000;
|
||||
|
||||
|
||||
/*
|
||||
* 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__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"
|
||||
*/
|
||||
# undef USE_OBSOLETE_SIGCONTEXT_FLAVOR /* #define this to use the older signal handler method */
|
||||
# ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR
|
||||
static void sigill_handler_sse_os(int signal, struct sigcontext sc)
|
||||
{
|
||||
(void)signal;
|
||||
sc.eip += 3 + 3 + 6;
|
||||
}
|
||||
# else
|
||||
# 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;
|
||||
}
|
||||
# endif
|
||||
# elif defined(_MSC_VER)
|
||||
# include <windows.h>
|
||||
# undef USE_TRY_CATCH_FLAVOR /* #define this to use the try/catch method for catching illegal opcode exception */
|
||||
# ifdef USE_TRY_CATCH_FLAVOR
|
||||
# else
|
||||
LONG CALLBACK sigill_handler_sse_os(EXCEPTION_POINTERS *ep)
|
||||
{
|
||||
if(ep->ExceptionRecord->ExceptionCode == EXCEPTION_ILLEGAL_INSTRUCTION) {
|
||||
ep->ContextRecord->Eip += 3 + 3 + 6;
|
||||
return EXCEPTION_CONTINUE_EXECUTION;
|
||||
}
|
||||
return EXCEPTION_CONTINUE_SEARCH;
|
||||
}
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
|
||||
void FLAC__cpu_info(FLAC__CPUInfo *info)
|
||||
{
|
||||
/*
|
||||
* IA32-specific
|
||||
*/
|
||||
#ifdef FLAC__CPU_IA32
|
||||
info->type = FLAC__CPUINFO_TYPE_IA32;
|
||||
#if !defined FLAC__NO_ASM && defined FLAC__HAS_NASM
|
||||
info->use_asm = true; /* we assume a minimum of 80386 with FLAC__CPU_IA32 */
|
||||
info->data.ia32.cpuid = FLAC__cpu_have_cpuid_asm_ia32()? true : false;
|
||||
info->data.ia32.bswap = info->data.ia32.cpuid; /* CPUID => BSWAP since it came after */
|
||||
info->data.ia32.cmov = false;
|
||||
info->data.ia32.mmx = false;
|
||||
info->data.ia32.fxsr = false;
|
||||
info->data.ia32.sse = false;
|
||||
info->data.ia32.sse2 = false;
|
||||
info->data.ia32.sse3 = false;
|
||||
info->data.ia32.ssse3 = false;
|
||||
info->data.ia32._3dnow = false;
|
||||
info->data.ia32.ext3dnow = false;
|
||||
info->data.ia32.extmmx = false;
|
||||
if(info->data.ia32.cpuid) {
|
||||
/* http://www.sandpile.org/ia32/cpuid.htm */
|
||||
FLAC__uint32 flags_edx, flags_ecx;
|
||||
FLAC__cpu_info_asm_ia32(&flags_edx, &flags_ecx);
|
||||
info->data.ia32.cmov = (flags_edx & FLAC__CPUINFO_IA32_CPUID_CMOV )? true : false;
|
||||
info->data.ia32.mmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_MMX )? true : false;
|
||||
info->data.ia32.fxsr = (flags_edx & FLAC__CPUINFO_IA32_CPUID_FXSR )? true : false;
|
||||
info->data.ia32.sse = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE )? true : false;
|
||||
info->data.ia32.sse2 = (flags_edx & FLAC__CPUINFO_IA32_CPUID_SSE2 )? true : false;
|
||||
info->data.ia32.sse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSE3 )? true : false;
|
||||
info->data.ia32.ssse3 = (flags_ecx & FLAC__CPUINFO_IA32_CPUID_SSSE3)? true : false;
|
||||
|
||||
#ifdef FLAC__USE_3DNOW
|
||||
flags_edx = FLAC__cpu_info_extended_amd_asm_ia32();
|
||||
info->data.ia32._3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_3DNOW )? true : false;
|
||||
info->data.ia32.ext3dnow = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXT3DNOW)? true : false;
|
||||
info->data.ia32.extmmx = (flags_edx & FLAC__CPUINFO_IA32_CPUID_EXTENDED_AMD_EXTMMX )? true : false;
|
||||
#else
|
||||
info->data.ia32._3dnow = info->data.ia32.ext3dnow = info->data.ia32.extmmx = false;
|
||||
#endif
|
||||
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, "CPU info (IA-32):\n");
|
||||
fprintf(stderr, " CPUID ...... %c\n", info->data.ia32.cpuid ? 'Y' : 'n');
|
||||
fprintf(stderr, " BSWAP ...... %c\n", info->data.ia32.bswap ? 'Y' : 'n');
|
||||
fprintf(stderr, " CMOV ....... %c\n", info->data.ia32.cmov ? 'Y' : 'n');
|
||||
fprintf(stderr, " MMX ........ %c\n", info->data.ia32.mmx ? 'Y' : 'n');
|
||||
fprintf(stderr, " FXSR ....... %c\n", info->data.ia32.fxsr ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE ........ %c\n", info->data.ia32.sse ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE2 ....... %c\n", info->data.ia32.sse2 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSE3 ....... %c\n", info->data.ia32.sse3 ? 'Y' : 'n');
|
||||
fprintf(stderr, " SSSE3 ...... %c\n", info->data.ia32.ssse3 ? 'Y' : 'n');
|
||||
fprintf(stderr, " 3DNow! ..... %c\n", info->data.ia32._3dnow ? 'Y' : 'n');
|
||||
fprintf(stderr, " 3DNow!-ext . %c\n", info->data.ia32.ext3dnow? 'Y' : 'n');
|
||||
fprintf(stderr, " 3DNow!-MMX . %c\n", info->data.ia32.extmmx ? 'Y' : 'n');
|
||||
#endif
|
||||
|
||||
/*
|
||||
* now have to check for OS support of SSE/SSE2
|
||||
*/
|
||||
if(info->data.ia32.fxsr || info->data.ia32.sse || info->data.ia32.sse2) {
|
||||
#if defined FLAC__NO_SSE_OS
|
||||
/* assume user knows better than us; turn it off */
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
#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)
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
#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)
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
else { /* double-check SSE2 */
|
||||
mib[1] = CPU_SSE2;
|
||||
len = sizeof(val);
|
||||
if(sysctl(mib, 2, &val, &len, NULL, 0) < 0 || !val)
|
||||
info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
}
|
||||
# else
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
# endif
|
||||
#elif defined(__linux__)
|
||||
int sse = 0;
|
||||
struct sigaction sigill_save;
|
||||
#ifdef USE_OBSOLETE_SIGCONTEXT_FLAVOR
|
||||
if(0 == sigaction(SIGILL, NULL, &sigill_save) && signal(SIGILL, (void (*)(int))sigill_handler_sse_os) != SIG_ERR)
|
||||
#else
|
||||
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))
|
||||
#endif
|
||||
{
|
||||
/* http://www.ibiblio.org/gferg/ldp/GCC-Inline-Assembly-HOWTO.html */
|
||||
/* see sigill_handler_sse_os() for an explanation of the following: */
|
||||
asm volatile (
|
||||
"xorl %0,%0\n\t" /* for some reason, still need to do this to clear 'sse' var */
|
||||
"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)
|
||||
: "r"(sse)
|
||||
);
|
||||
|
||||
sigaction(SIGILL, &sigill_save, NULL);
|
||||
}
|
||||
|
||||
if(!sse)
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
#elif defined(_MSC_VER)
|
||||
# ifdef USE_TRY_CATCH_FLAVOR
|
||||
_try {
|
||||
__asm {
|
||||
# if _MSC_VER <= 1200
|
||||
/* VC6 assembler doesn't know SSE, have to emit bytecode instead */
|
||||
_emit 0x0F
|
||||
_emit 0x57
|
||||
_emit 0xC0
|
||||
# else
|
||||
xorps xmm0,xmm0
|
||||
# endif
|
||||
}
|
||||
}
|
||||
_except(EXCEPTION_EXECUTE_HANDLER) {
|
||||
if (_exception_code() == STATUS_ILLEGAL_INSTRUCTION)
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
}
|
||||
# else
|
||||
int sse = 0;
|
||||
LPTOP_LEVEL_EXCEPTION_FILTER save = SetUnhandledExceptionFilter(sigill_handler_sse_os);
|
||||
/* see GCC version above for explanation */
|
||||
/* http://msdn2.microsoft.com/en-us/library/4ks26t93.aspx */
|
||||
/* http://www.codeproject.com/cpp/gccasm.asp */
|
||||
/* http://www.hick.org/~mmiller/msvc_inline_asm.html */
|
||||
__asm {
|
||||
# if _MSC_VER <= 1200
|
||||
/* VC6 assembler doesn't know SSE, have to emit bytecode instead */
|
||||
_emit 0x0F
|
||||
_emit 0x57
|
||||
_emit 0xC0
|
||||
# else
|
||||
xorps xmm0,xmm0
|
||||
# endif
|
||||
inc sse
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
nop
|
||||
}
|
||||
SetUnhandledExceptionFilter(save);
|
||||
if(!sse)
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
# endif
|
||||
#else
|
||||
/* no way to test, disable to be safe */
|
||||
info->data.ia32.fxsr = info->data.ia32.sse = info->data.ia32.sse2 = info->data.ia32.sse3 = info->data.ia32.ssse3 = false;
|
||||
#endif
|
||||
#ifdef DEBUG
|
||||
fprintf(stderr, " SSE OS sup . %c\n", info->data.ia32.sse ? 'Y' : 'n');
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
#else
|
||||
info->use_asm = false;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* PPC-specific
|
||||
*/
|
||||
#elif defined FLAC__CPU_PPC
|
||||
info->type = FLAC__CPUINFO_TYPE_PPC;
|
||||
# if !defined FLAC__NO_ASM
|
||||
info->use_asm = true;
|
||||
# ifdef FLAC__USE_ALTIVEC
|
||||
# if defined FLAC__SYS_DARWIN
|
||||
{
|
||||
int val = 0, mib[2] = { CTL_HW, HW_VECTORUNIT };
|
||||
size_t len = sizeof(val);
|
||||
info->data.ppc.altivec = !(sysctl(mib, 2, &val, &len, NULL, 0) || !val);
|
||||
}
|
||||
{
|
||||
host_basic_info_data_t hostInfo;
|
||||
mach_msg_type_number_t infoCount;
|
||||
|
||||
infoCount = HOST_BASIC_INFO_COUNT;
|
||||
host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t)&hostInfo, &infoCount);
|
||||
|
||||
info->data.ppc.ppc64 = (hostInfo.cpu_type == CPU_TYPE_POWERPC) && (hostInfo.cpu_subtype == CPU_SUBTYPE_POWERPC_970);
|
||||
}
|
||||
# else /* FLAC__USE_ALTIVEC && !FLAC__SYS_DARWIN */
|
||||
{
|
||||
/* no Darwin, do it the brute-force way */
|
||||
/* @@@@@@ this is not thread-safe; replace with SSE OS method above or remove */
|
||||
info->data.ppc.altivec = 0;
|
||||
info->data.ppc.ppc64 = 0;
|
||||
|
||||
signal (SIGILL, sigill_handler);
|
||||
canjump = 0;
|
||||
if (!sigsetjmp (jmpbuf, 1)) {
|
||||
canjump = 1;
|
||||
|
||||
asm volatile (
|
||||
"mtspr 256, %0\n\t"
|
||||
"vand %%v0, %%v0, %%v0"
|
||||
:
|
||||
: "r" (-1)
|
||||
);
|
||||
|
||||
info->data.ppc.altivec = 1;
|
||||
}
|
||||
canjump = 0;
|
||||
if (!sigsetjmp (jmpbuf, 1)) {
|
||||
int x = 0;
|
||||
canjump = 1;
|
||||
|
||||
/* PPC64 hardware implements the cntlzd instruction */
|
||||
asm volatile ("cntlzd %0, %1" : "=r" (x) : "r" (x) );
|
||||
|
||||
info->data.ppc.ppc64 = 1;
|
||||
}
|
||||
signal (SIGILL, SIG_DFL); /*@@@@@@ should save and restore old signal */
|
||||
}
|
||||
# endif
|
||||
# else /* !FLAC__USE_ALTIVEC */
|
||||
info->data.ppc.altivec = 0;
|
||||
info->data.ppc.ppc64 = 0;
|
||||
# endif
|
||||
# else
|
||||
info->use_asm = false;
|
||||
# endif
|
||||
|
||||
/*
|
||||
* unknown CPI
|
||||
*/
|
||||
#else
|
||||
info->type = FLAC__CPUINFO_TYPE_UNKNOWN;
|
||||
info->use_asm = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
148
src/audio/audio_file_formats/flac/libFLAC/crc.c
Normal file
148
src/audio/audio_file_formats/flac/libFLAC/crc.c
Normal file
|
|
@ -0,0 +1,148 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if 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 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
441
src/audio/audio_file_formats/flac/libFLAC/fixed.c
Normal file
441
src/audio/audio_file_formats/flac/libFLAC/fixed.c
Normal file
|
|
@ -0,0 +1,441 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "include/private/bitmath.h"
|
||||
#include "include/private/fixed.h"
|
||||
#include "../assert.h"
|
||||
|
||||
#ifndef M_LN2
|
||||
/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
|
||||
#define M_LN2 0.69314718055994530942
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x,y) ((x) < (y)? (x) : (y))
|
||||
|
||||
#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 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4))
|
||||
order = 0;
|
||||
else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4))
|
||||
order = 1;
|
||||
else if(total_error_2 < 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 < min(min(min(total_error_1, total_error_2), total_error_3), total_error_4))
|
||||
order = 0;
|
||||
else if(total_error_1 < min(min(total_error_2, total_error_3), total_error_4))
|
||||
order = 1;
|
||||
else if(total_error_2 < 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
|
||||
#if defined _MSC_VER || defined __MINGW32__
|
||||
/* with MSVC you have to spoon feed it the casting */
|
||||
residual_bits_per_sample[0] = (FLAC__float)((total_error_0 > 0) ? log(M_LN2 * (FLAC__double)(FLAC__int64)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)(FLAC__int64)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)(FLAC__int64)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)(FLAC__int64)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)(FLAC__int64)total_error_4 / (FLAC__double)data_len) / M_LN2 : 0.0);
|
||||
#else
|
||||
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);
|
||||
#endif
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
314
src/audio/audio_file_formats/flac/libFLAC/float.c
Normal file
314
src/audio/audio_file_formats/flac/libFLAC/float.c
Normal file
|
|
@ -0,0 +1,314 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include "../assert.h"
|
||||
|
||||
#include "include/private/float.h"
|
||||
|
||||
#ifdef FLAC__INTEGER_ONLY_LIBRARY
|
||||
|
||||
/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
|
||||
#ifdef _MSC_VER
|
||||
#define FLAC__U64L(x) x
|
||||
#else
|
||||
#define FLAC__U64L(x) x##LLU
|
||||
#endif
|
||||
|
||||
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 */
|
||||
|
||||
#endif
|
||||
604
src/audio/audio_file_formats/flac/libFLAC/format.c
Normal file
604
src/audio/audio_file_formats/flac/libFLAC/format.c
Normal file
|
|
@ -0,0 +1,604 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if 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 "include/private/format.h"
|
||||
|
||||
#ifndef FLaC__INLINE
|
||||
#define FLaC__INLINE
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(a,b) ((a)<(b)?(a):(b))
|
||||
|
||||
/* adjust for compilers that can't understand using LLU suffix for uint64_t literals */
|
||||
#ifdef _MSC_VER
|
||||
#define FLAC__U64L(x) x
|
||||
#else
|
||||
#define FLAC__U64L(x) x##LLU
|
||||
#endif
|
||||
|
||||
/* VERSION should come from configure */
|
||||
FLAC_API const char *FLAC__VERSION_STRING = VERSION
|
||||
|
||||
|
||||
|
||||
|
||||
;
|
||||
|
||||
#if defined _MSC_VER || defined __BORLANDC__ || defined __MINW32__
|
||||
/* yet one more hack because of MSVC6: */
|
||||
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC 1.2.1 20070917";
|
||||
#else
|
||||
FLAC_API const char *FLAC__VENDOR_STRING = "reference libFLAC " VERSION " 20070917";
|
||||
#endif
|
||||
|
||||
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_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 FLaC__INLINE 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 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*)realloc(object->parameters, sizeof(unsigned)*(1 << max_partition_order))))
|
||||
return false;
|
||||
if(0 == (object->raw_bits = (unsigned*)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;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,42 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__BITMATH_H
|
||||
#define FLAC__PRIVATE__BITMATH_H
|
||||
|
||||
#include "../../../ordinals.h"
|
||||
|
||||
unsigned FLAC__bitmath_ilog2(FLAC__uint32 v);
|
||||
unsigned FLAC__bitmath_ilog2_wide(FLAC__uint64 v);
|
||||
unsigned FLAC__bitmath_silog2(int v);
|
||||
unsigned FLAC__bitmath_silog2_wide(FLAC__int64 v);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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__CPUInfo cpu, 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);
|
||||
#ifndef FLAC__NO_ASM
|
||||
# ifdef FLAC__CPU_IA32
|
||||
# ifdef FLAC__HAS_NASM
|
||||
FLAC__bool FLAC__bitreader_read_rice_signed_block_asm_ia32_bswap(FLAC__BitReader *br, int vals[], unsigned nvals, unsigned parameter);
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
#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);
|
||||
|
||||
FLAC__bool bitreader_read_from_client_(FLAC__BitReader *br);
|
||||
#endif
|
||||
|
|
@ -0,0 +1,103 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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,88 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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_PPC,
|
||||
FLAC__CPUINFO_TYPE_UNKNOWN
|
||||
} FLAC__CPUInfo_Type;
|
||||
|
||||
typedef struct {
|
||||
FLAC__bool cpuid;
|
||||
FLAC__bool bswap;
|
||||
FLAC__bool cmov;
|
||||
FLAC__bool mmx;
|
||||
FLAC__bool fxsr;
|
||||
FLAC__bool sse;
|
||||
FLAC__bool sse2;
|
||||
FLAC__bool sse3;
|
||||
FLAC__bool ssse3;
|
||||
FLAC__bool _3dnow;
|
||||
FLAC__bool ext3dnow;
|
||||
FLAC__bool extmmx;
|
||||
} FLAC__CPUInfo_IA32;
|
||||
|
||||
typedef struct {
|
||||
FLAC__bool altivec;
|
||||
FLAC__bool ppc64;
|
||||
} FLAC__CPUInfo_PPC;
|
||||
|
||||
typedef struct {
|
||||
FLAC__bool use_asm;
|
||||
FLAC__CPUInfo_Type type;
|
||||
union {
|
||||
FLAC__CPUInfo_IA32 ia32;
|
||||
FLAC__CPUInfo_PPC ppc;
|
||||
} data;
|
||||
} FLAC__CPUInfo;
|
||||
|
||||
void FLAC__cpu_info(FLAC__CPUInfo *info);
|
||||
|
||||
#ifndef FLAC__NO_ASM
|
||||
#ifdef FLAC__CPU_IA32
|
||||
#ifdef 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);
|
||||
FLAC__uint32 FLAC__cpu_info_extended_amd_asm_ia32(void);
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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 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
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__FIXED_H
|
||||
#define FLAC__PRIVATE__FIXED_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#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]);
|
||||
# ifndef FLAC__NO_ASM
|
||||
# ifdef FLAC__CPU_IA32
|
||||
# ifdef 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
|
||||
# endif
|
||||
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(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
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
214
src/audio/audio_file_formats/flac/libFLAC/include/private/lpc.h
Normal file
214
src/audio/audio_file_formats/flac/libFLAC/include/private/lpc.h
Normal file
|
|
@ -0,0 +1,214 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__LPC_H
|
||||
#define FLAC__PRIVATE__LPC_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#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_3dnow(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[]);
|
||||
# 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[]);
|
||||
# endif /* FLAC__HAS_NASM */
|
||||
# elif defined FLAC__CPU_PPC
|
||||
void FLAC__lpc_restore_signal_asm_ppc_altivec_16(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_ppc_altivec_16_order8(const FLAC__int32 residual[], unsigned data_len, const FLAC__int32 qlp_coeff[], unsigned order, int lp_quantization, FLAC__int32 data[]);
|
||||
# endif/* FLAC__CPU_IA32 || FLAC__CPU_PPC */
|
||||
#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,44 @@
|
|||
#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 struct {
|
||||
FLAC__uint32 in[16];
|
||||
FLAC__uint32 buf[4];
|
||||
FLAC__uint32 bytes[2];
|
||||
FLAC__byte *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
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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(unsigned elements, FLAC__int32 **unaligned_pointer, FLAC__int32 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_uint32_array(unsigned elements, FLAC__uint32 **unaligned_pointer, FLAC__uint32 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_uint64_array(unsigned elements, FLAC__uint64 **unaligned_pointer, FLAC__uint64 **aligned_pointer);
|
||||
FLAC__bool FLAC__memory_alloc_aligned_unsigned_array(unsigned elements, unsigned **unaligned_pointer, unsigned **aligned_pointer);
|
||||
#ifndef FLAC__INTEGER_ONLY_LIBRARY
|
||||
FLAC__bool FLAC__memory_alloc_aligned_real_array(unsigned elements, FLAC__real **unaligned_pointer, FLAC__real **aligned_pointer);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__METADATA_H
|
||||
#define FLAC__PRIVATE__METADATA_H
|
||||
|
||||
#include "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
|
||||
|
|
@ -0,0 +1,45 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2006,2007 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.
|
||||
*/
|
||||
|
||||
#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_welch(FLAC__real *window, const FLAC__int32 L);
|
||||
|
||||
#endif /* !defined FLAC__INTEGER_ONLY_LIBRARY */
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PROTECTED__ALL_H
|
||||
#define FLAC__PROTECTED__ALL_H
|
||||
|
||||
#include "stream_decoder.h"
|
||||
#include "stream_encoder.h"
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PROTECTED__STREAM_DECODER_H
|
||||
#define FLAC__PROTECTED__STREAM_DECODER_H
|
||||
|
||||
#include "../../../stream_decoder.h"
|
||||
#if FLAC__HAS_OGG
|
||||
#include "include/private/ogg_decoder_aspect.h"
|
||||
#endif
|
||||
|
||||
typedef struct FLAC__StreamDecoderProtected {
|
||||
FLAC__StreamDecoderState state;
|
||||
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
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#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_WELCH
|
||||
} FLAC__ApodizationFunction;
|
||||
|
||||
typedef struct {
|
||||
FLAC__ApodizationFunction type;
|
||||
union {
|
||||
struct {
|
||||
FLAC__real stddev;
|
||||
} gauss;
|
||||
struct {
|
||||
FLAC__real p;
|
||||
} 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
|
||||
42
src/audio/audio_file_formats/flac/libFLAC/juce_FlacHeader.h
Normal file
42
src/audio/audio_file_formats/flac/libFLAC/juce_FlacHeader.h
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// This file is included at the start of each FLAC .c file, just to do a few housekeeping
|
||||
// tasks..
|
||||
|
||||
|
||||
#include "../../../../../juce_Config.h"
|
||||
|
||||
#define VERSION "1.2.1"
|
||||
|
||||
#define FLAC__NO_DLL 1
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4312)
|
||||
#endif
|
||||
|
||||
#if ! (defined (_WIN32) || defined (_WIN64) || defined (LINUX))
|
||||
#define FLAC__SYS_DARWIN 1
|
||||
#endif
|
||||
1383
src/audio/audio_file_formats/flac/libFLAC/lpc_flac.c
Normal file
1383
src/audio/audio_file_formats/flac/libFLAC/lpc_flac.c
Normal file
File diff suppressed because it is too large
Load diff
431
src/audio/audio_file_formats/flac/libFLAC/md5.c
Normal file
431
src/audio/audio_file_formats/flac/libFLAC/md5.c
Normal file
|
|
@ -0,0 +1,431 @@
|
|||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if 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"
|
||||
|
||||
#ifndef FLaC__INLINE
|
||||
#define FLaC__INLINE
|
||||
#endif
|
||||
|
||||
/*
|
||||
* 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 = 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);
|
||||
memset(ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
if(0 != ctx->internal_buf) {
|
||||
free(ctx->internal_buf);
|
||||
ctx->internal_buf = 0;
|
||||
ctx->capacity = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Convert the incoming audio signal to a byte stream
|
||||
*/
|
||||
static void format_input_(FLAC__byte *buf, const FLAC__int32 * const signal[], unsigned channels, unsigned samples, unsigned bytes_per_sample)
|
||||
{
|
||||
unsigned channel, sample;
|
||||
register FLAC__int32 a_word;
|
||||
register FLAC__byte *buf_ = buf;
|
||||
|
||||
#if WORDS_BIGENDIAN
|
||||
#else
|
||||
if(channels == 2 && bytes_per_sample == 2) {
|
||||
FLAC__int16 *buf1_ = ((FLAC__int16*)buf_) + 1;
|
||||
memcpy(buf_, signal[0], sizeof(FLAC__int32) * samples);
|
||||
for(sample = 0; sample < samples; sample++, buf1_+=2)
|
||||
*buf1_ = (FLAC__int16)signal[1][sample];
|
||||
}
|
||||
else if(channels == 1 && bytes_per_sample == 2) {
|
||||
FLAC__int16 *buf1_ = (FLAC__int16*)buf_;
|
||||
for(sample = 0; sample < samples; sample++)
|
||||
*buf1_++ = (FLAC__int16)signal[0][sample];
|
||||
}
|
||||
else
|
||||
#endif
|
||||
if(bytes_per_sample == 2) {
|
||||
if(channels == 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 = signal[1][sample];
|
||||
*buf_++ = (FLAC__byte)a_word; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
}
|
||||
else if(channels == 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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(bytes_per_sample == 3) {
|
||||
if(channels == 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;
|
||||
}
|
||||
}
|
||||
else if(channels == 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;
|
||||
}
|
||||
}
|
||||
else {
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if(bytes_per_sample == 1) {
|
||||
if(channels == 2) {
|
||||
for(sample = 0; sample < samples; sample++) {
|
||||
a_word = signal[0][sample];
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
a_word = signal[1][sample];
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
}
|
||||
else if(channels == 1) {
|
||||
for(sample = 0; sample < samples; sample++) {
|
||||
a_word = signal[0][sample];
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for(sample = 0; sample < samples; sample++) {
|
||||
for(channel = 0; channel < channels; channel++) {
|
||||
a_word = signal[channel][sample];
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else { /* bytes_per_sample == 4, maybe optimize more later */
|
||||
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; a_word >>= 8;
|
||||
*buf_++ = (FLAC__byte)a_word;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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, bytes_needed);
|
||||
if(0 == tmp) {
|
||||
free(ctx->internal_buf);
|
||||
if(0 == (ctx->internal_buf = (FLAC__byte*)safe_malloc_(bytes_needed)))
|
||||
return false;
|
||||
}
|
||||
ctx->internal_buf = tmp;
|
||||
ctx->capacity = bytes_needed;
|
||||
}
|
||||
|
||||
format_input_(ctx->internal_buf, signal, channels, samples, bytes_per_sample);
|
||||
|
||||
FLAC__MD5Update(ctx, ctx->internal_buf, bytes_needed);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif
|
||||
227
src/audio/audio_file_formats/flac/libFLAC/memory.c
Normal file
227
src/audio/audio_file_formats/flac/libFLAC/memory.c
Normal file
|
|
@ -0,0 +1,227 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if HAVE_CONFIG_H
|
||||
# include <config.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, /*+*/31);
|
||||
#ifdef SIZEOF_VOIDP
|
||||
#if SIZEOF_VOIDP == 4
|
||||
/* could do *aligned_address = x + ((unsigned) (32 - (((unsigned)x) & 31))) & 31; */
|
||||
*aligned_address = (void*)(((unsigned)x + 31) & -32);
|
||||
#elif SIZEOF_VOIDP == 8
|
||||
*aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32)));
|
||||
#else
|
||||
# error Unsupported sizeof(void*)
|
||||
#endif
|
||||
#else
|
||||
/* there's got to be a better way to do this right for all archs */
|
||||
if(sizeof(void*) == sizeof(unsigned))
|
||||
*aligned_address = (void*)(((unsigned)x + 31) & -32);
|
||||
else if(sizeof(void*) == sizeof(FLAC__uint64))
|
||||
*aligned_address = (void*)(((FLAC__uint64)x + 31) & (FLAC__uint64)(-((FLAC__int64)32)));
|
||||
else
|
||||
return 0;
|
||||
#endif
|
||||
#else
|
||||
x = safe_malloc_(bytes);
|
||||
*aligned_address = x;
|
||||
#endif
|
||||
return x;
|
||||
}
|
||||
|
||||
FLAC__bool FLAC__memory_alloc_aligned_int32_array(unsigned 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((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (FLAC__int32*)FLAC__memory_alloc_aligned(sizeof(*pu) * (size_t)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(unsigned 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((size_t)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(unsigned 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((size_t)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(unsigned 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((size_t)elements > SIZE_MAX / sizeof(*pu)) /* overflow check */
|
||||
return false;
|
||||
|
||||
pu = (unsigned*)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(unsigned 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((size_t)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
|
||||
|
||||
#endif
|
||||
3391
src/audio/audio_file_formats/flac/libFLAC/stream_decoder.c
Normal file
3391
src/audio/audio_file_formats/flac/libFLAC/stream_decoder.c
Normal file
File diff suppressed because it is too large
Load diff
4364
src/audio/audio_file_formats/flac/libFLAC/stream_encoder.c
Normal file
4364
src/audio/audio_file_formats/flac/libFLAC/stream_encoder.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,559 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
|
||||
#if 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"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
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 *index = track->indices + j;
|
||||
|
||||
if(!FLAC__bitwriter_write_raw_uint64(bw, index->offset, FLAC__STREAM_METADATA_CUESHEET_INDEX_OFFSET_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitwriter_write_raw_uint32(bw, index->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;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
230
src/audio/audio_file_formats/flac/libFLAC/window_flac.c
Normal file
230
src/audio/audio_file_formats/flac/libFLAC/window_flac.c
Normal file
|
|
@ -0,0 +1,230 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2006,2007 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.
|
||||
*/
|
||||
|
||||
#include "juce_FlacHeader.h"
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
#if 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
|
||||
|
||||
#ifndef M_PI
|
||||
/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
|
||||
#define M_PI 3.14159265358979323846
|
||||
#endif
|
||||
|
||||
|
||||
void FLAC__window_bartlett(FLAC__real *window, const FLAC__int32 L)
|
||||
{
|
||||
const FLAC__int32 N = L - 1;
|
||||
FLAC__int32 n;
|
||||
|
||||
if (L & 1) {
|
||||
for (n = 0; n <= N/2; n++)
|
||||
window[n] = 2.0f * n / (float)N;
|
||||
for (; n <= N; n++)
|
||||
window[n] = 2.0f - 2.0f * n / (float)N;
|
||||
}
|
||||
else {
|
||||
for (n = 0; n <= L/2-1; n++)
|
||||
window[n] = 2.0f * n / (float)N;
|
||||
for (; n <= N; n++)
|
||||
window[n] = 2.0f - 2.0f * (N-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+0.5f)));
|
||||
}
|
||||
|
||||
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;
|
||||
for (; n <= L; n++)
|
||||
window[n-1] = ((float)(2 * (L - n)) + 1.0f) / (float)L;
|
||||
}
|
||||
}
|
||||
|
||||
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_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 */
|
||||
|
||||
#endif
|
||||
2181
src/audio/audio_file_formats/flac/metadata.h
Normal file
2181
src/audio/audio_file_formats/flac/metadata.h
Normal file
File diff suppressed because it is too large
Load diff
80
src/audio/audio_file_formats/flac/ordinals.h
Normal file
80
src/audio/audio_file_formats/flac/ordinals.h
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
/* libFLAC - Free Lossless Audio Codec library
|
||||
* Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007 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.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ORDINALS_H
|
||||
#define FLAC__ORDINALS_H
|
||||
|
||||
#if !(defined(_MSC_VER) || defined(__BORLANDC__) || defined(__EMX__))
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
typedef signed char FLAC__int8;
|
||||
typedef unsigned char FLAC__uint8;
|
||||
|
||||
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
||||
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;
|
||||
#elif defined(__EMX__)
|
||||
typedef short FLAC__int16;
|
||||
typedef long FLAC__int32;
|
||||
typedef long long FLAC__int64;
|
||||
typedef unsigned short FLAC__uint16;
|
||||
typedef unsigned long FLAC__uint32;
|
||||
typedef unsigned long long FLAC__uint64;
|
||||
#else
|
||||
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
|
||||
1559
src/audio/audio_file_formats/flac/stream_decoder.h
Normal file
1559
src/audio/audio_file_formats/flac/stream_decoder.h
Normal file
File diff suppressed because it is too large
Load diff
1768
src/audio/audio_file_formats/flac/stream_encoder.h
Normal file
1768
src/audio/audio_file_formats/flac/stream_encoder.h
Normal file
File diff suppressed because it is too large
Load diff
813
src/audio/audio_file_formats/juce_AiffAudioFormat.cpp
Normal file
813
src/audio/audio_file_formats/juce_AiffAudioFormat.cpp
Normal file
|
|
@ -0,0 +1,813 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_AiffAudioFormat.h"
|
||||
#include "../../io/streams/juce_BufferedInputStream.h"
|
||||
#include "../../core/juce_PlatformUtilities.h"
|
||||
#include "../../text/juce_LocalisedStrings.h"
|
||||
|
||||
|
||||
#undef chunkName
|
||||
#define chunkName(a) (int)littleEndianInt(a)
|
||||
|
||||
//==============================================================================
|
||||
#define aiffFormatName TRANS("AIFF file")
|
||||
static const tchar* const aiffExtensions[] = { T(".aiff"), T(".aif"), 0 };
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class AiffAudioFormatReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
int bytesPerFrame;
|
||||
int64 dataChunkStart;
|
||||
bool littleEndian;
|
||||
|
||||
//==============================================================================
|
||||
AiffAudioFormatReader (InputStream* in)
|
||||
: AudioFormatReader (in, aiffFormatName)
|
||||
{
|
||||
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 = input->readShortBigEndian();
|
||||
bytesPerFrame = (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 = bigEndianInt ((char*) sampleRateBytes + 2);
|
||||
sampRate >>= (16414 - bigEndianShort ((char*) 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
|
||||
{
|
||||
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 / bytesPerFrame)) : 0;
|
||||
}
|
||||
else if ((hasGotVer && hasGotData && hasGotType)
|
||||
|| chunkEnd < input->getPosition()
|
||||
|| input->isExhausted())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
input->setPosition (chunkEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~AiffAudioFormatReader()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
numSamples = (int) jmin ((int64) numSamples, lengthInSamples - startSampleInFile);
|
||||
|
||||
if (numSamples <= 0)
|
||||
return true;
|
||||
|
||||
input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame);
|
||||
|
||||
const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3)
|
||||
char tempBuffer [tempBufSize];
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
int* left = destSamples[0];
|
||||
if (left != 0)
|
||||
left += startOffsetInDestBuffer;
|
||||
|
||||
int* right = numDestChannels > 1 ? destSamples[1] : 0;
|
||||
if (right != 0)
|
||||
right += startOffsetInDestBuffer;
|
||||
|
||||
const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples);
|
||||
const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame);
|
||||
|
||||
if (bytesRead < numThisTime * bytesPerFrame)
|
||||
zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead);
|
||||
|
||||
if (bitsPerSample == 16)
|
||||
{
|
||||
if (littleEndian)
|
||||
{
|
||||
const short* src = (const short*) tempBuffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
*right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const char* src = (const char*) tempBuffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*right++ = bigEndianShort (src) << 16;
|
||||
src += 4;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
src += 2;
|
||||
*left++ = bigEndianShort (src) << 16;
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = bigEndianShort (src) << 16;
|
||||
src += 2;
|
||||
*right++ = bigEndianShort (src) << 16;
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = bigEndianShort (src) << 16;
|
||||
src += 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 24)
|
||||
{
|
||||
const char* src = (const char*)tempBuffer;
|
||||
|
||||
if (littleEndian)
|
||||
{
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*right++ = littleEndian24Bit (src) << 8;
|
||||
src += 6;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
src += 3;
|
||||
*left++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
*right++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*right++ = bigEndian24Bit (src) << 8;
|
||||
src += 6;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
src += 3;
|
||||
*left++ = bigEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = bigEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
*right++ = bigEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = bigEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 32)
|
||||
{
|
||||
const unsigned int* src = (const unsigned int*) tempBuffer;
|
||||
unsigned int* l = (unsigned int*) left;
|
||||
unsigned int* r = (unsigned int*) right;
|
||||
|
||||
if (littleEndian)
|
||||
{
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (l == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*r++ = swapIfBigEndian (*src++);
|
||||
}
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfBigEndian (*src++);
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfBigEndian (*src++);
|
||||
*r++ = swapIfBigEndian (*src++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfBigEndian (*src++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (l == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*r++ = swapIfLittleEndian (*src++);
|
||||
}
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfLittleEndian (*src++);
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfLittleEndian (*src++);
|
||||
*r++ = swapIfLittleEndian (*src++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfLittleEndian (*src++);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
left = (int*) l;
|
||||
right = (int*) r;
|
||||
}
|
||||
else if (bitsPerSample == 8)
|
||||
{
|
||||
const char* src = (const char*) tempBuffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*right++ = ((int) *src++) << 24;
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*left++ = ((int) *src++) << 24;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = ((int) *src++) << 24;
|
||||
*right++ = ((int) *src++) << 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = ((int) *src++) << 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startOffsetInDestBuffer += numThisTime;
|
||||
numSamples -= numThisTime;
|
||||
}
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != 0)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer,
|
||||
sizeof (int) * numSamples);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
AiffAudioFormatReader (const AiffAudioFormatReader&);
|
||||
const AiffAudioFormatReader& operator= (const AiffAudioFormatReader&);
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class AiffAudioFormatWriter : public AudioFormatWriter
|
||||
{
|
||||
MemoryBlock tempBlock;
|
||||
uint32 lengthInSamples, bytesWritten;
|
||||
int64 headerPosition;
|
||||
bool writeFailed;
|
||||
|
||||
AiffAudioFormatWriter (const AiffAudioFormatWriter&);
|
||||
const AiffAudioFormatWriter& operator= (const AiffAudioFormatWriter&);
|
||||
|
||||
void writeHeader()
|
||||
{
|
||||
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 = 54;
|
||||
int audioBytes = 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 (lengthInSamples);
|
||||
output->writeShortBigEndian ((short) bitsPerSample);
|
||||
|
||||
uint8 sampleRateBytes[10];
|
||||
zeromem (sampleRateBytes, 10);
|
||||
|
||||
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);
|
||||
|
||||
output->writeInt (chunkName ("SSND"));
|
||||
output->writeIntBigEndian (audioBytes + 8);
|
||||
output->writeInt (0);
|
||||
output->writeInt (0);
|
||||
|
||||
jassert (output->getPosition() == headerLen);
|
||||
}
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
AiffAudioFormatWriter (OutputStream* out,
|
||||
const double sampleRate_,
|
||||
const unsigned int chans,
|
||||
const int bits)
|
||||
: AudioFormatWriter (out,
|
||||
aiffFormatName,
|
||||
sampleRate_,
|
||||
chans,
|
||||
bits),
|
||||
lengthInSamples (0),
|
||||
bytesWritten (0),
|
||||
writeFailed (false)
|
||||
{
|
||||
headerPosition = out->getPosition();
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
~AiffAudioFormatWriter()
|
||||
{
|
||||
if ((bytesWritten & 1) != 0)
|
||||
output->writeByte (0);
|
||||
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (const int** data, int numSamples)
|
||||
{
|
||||
if (writeFailed)
|
||||
return false;
|
||||
|
||||
const int bytes = numChannels * numSamples * bitsPerSample / 8;
|
||||
tempBlock.ensureSize (bytes, false);
|
||||
char* buffer = (char*) tempBlock.getData();
|
||||
|
||||
const int* left = data[0];
|
||||
const int* right = data[1];
|
||||
if (right == 0)
|
||||
right = left;
|
||||
|
||||
if (bitsPerSample == 16)
|
||||
{
|
||||
short* b = (short*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (short) swapIfLittleEndian ((unsigned short) (*left++ >> 16));
|
||||
*b++ = (short) swapIfLittleEndian ((unsigned short) (*right++ >> 16));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (short) swapIfLittleEndian ((unsigned short) (*left++ >> 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 24)
|
||||
{
|
||||
char* b = (char*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
bigEndian24BitToChars (*left++ >> 8, b);
|
||||
b += 3;
|
||||
bigEndian24BitToChars (*right++ >> 8, b);
|
||||
b += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
bigEndian24BitToChars (*left++ >> 8, b);
|
||||
b += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 32)
|
||||
{
|
||||
unsigned int* b = (unsigned int*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = swapIfLittleEndian ((unsigned int) *left++);
|
||||
*b++ = swapIfLittleEndian ((unsigned int) *right++);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = swapIfLittleEndian ((unsigned int) *left++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 8)
|
||||
{
|
||||
char* b = (char*)buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (char) (*left++ >> 24);
|
||||
*b++ = (char) (*right++ >> 24);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (char) (*left++ >> 24);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesWritten + bytes >= (uint32) 0xfff00000
|
||||
|| ! output->write (buffer, 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 += numSamples;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
AiffAudioFormat::AiffAudioFormat()
|
||||
: AudioFormat (aiffFormatName, (const tchar**) aiffExtensions)
|
||||
{
|
||||
}
|
||||
|
||||
AiffAudioFormat::~AiffAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
const Array <int> AiffAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
|
||||
return Array <int> (rates);
|
||||
}
|
||||
|
||||
const 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 = PlatformUtilities::getTypeOfFile (f.getFullPathName());
|
||||
return type == 'AIFF' || type == 'AIFC'
|
||||
|| type == 'aiff' || type == 'aifc';
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioFormatReader* AiffAudioFormat::createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
AiffAudioFormatReader* w = new AiffAudioFormatReader (sourceStream);
|
||||
|
||||
if (w->sampleRate == 0)
|
||||
{
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
w->input = 0;
|
||||
|
||||
deleteAndZero (w);
|
||||
}
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
AudioFormatWriter* AiffAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int chans,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
if (getPossibleBitDepths().contains (bitsPerSample))
|
||||
{
|
||||
return new AiffAudioFormatWriter (out,
|
||||
sampleRate,
|
||||
chans,
|
||||
bitsPerSample);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
74
src/audio/audio_file_formats/juce_AiffAudioFormat.h
Normal file
74
src/audio/audio_file_formats/juce_AiffAudioFormat.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__
|
||||
#define __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads and Writes AIFF format audio files.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API AiffAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an format object. */
|
||||
AiffAudioFormat();
|
||||
|
||||
/** Destructor. */
|
||||
~AiffAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
const Array <int> getPossibleSampleRates();
|
||||
const Array <int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
#if JUCE_MAC
|
||||
bool canHandleFile (const File& fileToTest);
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AIFFAUDIOFORMAT_JUCEHEADER__
|
||||
107
src/audio/audio_file_formats/juce_AudioCDBurner.h
Normal file
107
src/audio/audio_file_formats/juce_AudioCDBurner.h
Normal file
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOCDBURNER_JUCEHEADER__
|
||||
#define __JUCE_AUDIOCDBURNER_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormatReader.h"
|
||||
#include "../audio_sources/juce_AudioSource.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
*/
|
||||
class AudioCDBurner
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Returns a list of available optical drives.
|
||||
|
||||
Use openDevice() to open one of the items from this list.
|
||||
*/
|
||||
static const StringArray findAvailableDevices();
|
||||
|
||||
/** Tries to open one of the optical drives.
|
||||
|
||||
The deviceIndex is an index into the array returned by findAvailableDevices().
|
||||
*/
|
||||
static AudioCDBurner* openDevice (const int deviceIndex);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioCDBurner();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if there's a writable disk in the drive.
|
||||
*/
|
||||
bool isDiskPresent() const;
|
||||
|
||||
/** Returns the number of free blocks on the disk.
|
||||
|
||||
There are 75 blocks per second, at 44100Hz.
|
||||
*/
|
||||
int getNumAvailableAudioBlocks() const;
|
||||
|
||||
/** Adds a track to be written.
|
||||
|
||||
The source passed-in here will be kept by this object, and it will
|
||||
be used and deleted at some point in the future, either during the
|
||||
burn() method or when this AudioCDBurner object is deleted. Your caller
|
||||
method shouldn't keep a reference to it or use it again after passing
|
||||
it in here.
|
||||
*/
|
||||
bool addAudioTrack (AudioSource* source, int numSamples);
|
||||
|
||||
/**
|
||||
|
||||
Return true to cancel the current burn operation
|
||||
*/
|
||||
class BurnProgressListener
|
||||
{
|
||||
public:
|
||||
BurnProgressListener() throw() {}
|
||||
virtual ~BurnProgressListener() {}
|
||||
|
||||
/** Called at intervals to report on the progress of the AudioCDBurner.
|
||||
|
||||
To cancel the burn, return true from this.
|
||||
*/
|
||||
virtual bool audioCDBurnProgress (float proportionComplete) = 0;
|
||||
};
|
||||
|
||||
const String burn (BurnProgressListener* listener,
|
||||
const bool ejectDiscAfterwards,
|
||||
const bool peformFakeBurnForTesting);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
AudioCDBurner (const int deviceIndex);
|
||||
|
||||
void* internal;
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOCDBURNER_JUCEHEADER__
|
||||
245
src/audio/audio_file_formats/juce_AudioCDReader.cpp
Normal file
245
src/audio/audio_file_formats/juce_AudioCDReader.cpp
Normal file
|
|
@ -0,0 +1,245 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#if JUCE_MAC
|
||||
|
||||
//==============================================================================
|
||||
// Mac version doesn't need any native code because it's all done with files..
|
||||
// Windows + Linux versions are in the platform-dependent code sections.
|
||||
|
||||
#include "juce_AudioCDReader.h"
|
||||
#include "juce_AiffAudioFormat.h"
|
||||
#include "../../io/files/juce_FileInputStream.h"
|
||||
#include "../../io/streams/juce_BufferedInputStream.h"
|
||||
|
||||
|
||||
static void findCDs (OwnedArray<File>& cds)
|
||||
{
|
||||
File volumes ("/Volumes");
|
||||
volumes.findChildFiles (cds, File::findDirectories, false);
|
||||
|
||||
for (int i = cds.size(); --i >= 0;)
|
||||
if (! cds[i]->getChildFile (".TOC.plist").exists())
|
||||
cds.remove (i);
|
||||
}
|
||||
|
||||
const StringArray AudioCDReader::getAvailableCDNames()
|
||||
{
|
||||
OwnedArray<File> cds;
|
||||
findCDs (cds);
|
||||
|
||||
StringArray names;
|
||||
|
||||
for (int i = 0; i < cds.size(); ++i)
|
||||
names.add (cds[i]->getFileName());
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
AudioCDReader* AudioCDReader::createReaderForCD (const int index)
|
||||
{
|
||||
OwnedArray<File> cds;
|
||||
findCDs (cds);
|
||||
|
||||
if (cds[index] != 0)
|
||||
return new AudioCDReader (*cds[index]);
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioCDReader::AudioCDReader (const File& volume)
|
||||
: AudioFormatReader (0, "CD Audio"),
|
||||
volumeDir (volume),
|
||||
currentReaderTrack (-1),
|
||||
reader (0)
|
||||
{
|
||||
sampleRate = 44100.0;
|
||||
bitsPerSample = 16;
|
||||
numChannels = 2;
|
||||
usesFloatingPointData = false;
|
||||
|
||||
refreshTrackLengths();
|
||||
}
|
||||
|
||||
AudioCDReader::~AudioCDReader()
|
||||
{
|
||||
if (reader != 0)
|
||||
delete reader;
|
||||
}
|
||||
|
||||
static int getTrackNumber (const File& file)
|
||||
{
|
||||
return file.getFileName()
|
||||
.initialSectionContainingOnly (T("0123456789"))
|
||||
.getIntValue();
|
||||
}
|
||||
|
||||
int AudioCDReader::compareElements (const File* const first, const File* const second) throw()
|
||||
{
|
||||
const int firstTrack = getTrackNumber (*first);
|
||||
const int secondTrack = getTrackNumber (*second);
|
||||
|
||||
jassert (firstTrack > 0 && secondTrack > 0);
|
||||
|
||||
return firstTrack - secondTrack;
|
||||
}
|
||||
|
||||
void AudioCDReader::refreshTrackLengths()
|
||||
{
|
||||
tracks.clear();
|
||||
trackStartSamples.clear();
|
||||
volumeDir.findChildFiles (tracks, File::findFiles | File::ignoreHiddenFiles, false, T("*.aiff"));
|
||||
|
||||
tracks.sort (*this);
|
||||
|
||||
AiffAudioFormat format;
|
||||
int sample = 0;
|
||||
|
||||
for (int i = 0; i < tracks.size(); ++i)
|
||||
{
|
||||
trackStartSamples.add (sample);
|
||||
|
||||
FileInputStream* const in = tracks[i]->createInputStream();
|
||||
|
||||
if (in != 0)
|
||||
{
|
||||
AudioFormatReader* const r = format.createReaderFor (in, true);
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
sample += r->lengthInSamples;
|
||||
delete r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trackStartSamples.add (sample);
|
||||
lengthInSamples = sample;
|
||||
}
|
||||
|
||||
bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
while (numSamples > 0)
|
||||
{
|
||||
int track = -1;
|
||||
|
||||
for (int i = 0; i < trackStartSamples.size() - 1; ++i)
|
||||
{
|
||||
if (startSampleInFile < trackStartSamples.getUnchecked (i + 1))
|
||||
{
|
||||
track = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (track < 0)
|
||||
return false;
|
||||
|
||||
if (track != currentReaderTrack)
|
||||
{
|
||||
deleteAndZero (reader);
|
||||
|
||||
if (tracks [track] != 0)
|
||||
{
|
||||
FileInputStream* const in = tracks [track]->createInputStream();
|
||||
|
||||
if (in != 0)
|
||||
{
|
||||
BufferedInputStream* const bin = new BufferedInputStream (in, 65536, true);
|
||||
|
||||
AiffAudioFormat format;
|
||||
reader = format.createReaderFor (bin, true);
|
||||
|
||||
if (reader == 0)
|
||||
currentReaderTrack = -1;
|
||||
else
|
||||
currentReaderTrack = track;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (reader == 0)
|
||||
return false;
|
||||
|
||||
const int startPos = (int) (startSampleInFile - trackStartSamples.getUnchecked (track));
|
||||
const int numAvailable = (int) jmin ((int64) numSamples, reader->lengthInSamples - startPos);
|
||||
|
||||
reader->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer, startPos, numAvailable);
|
||||
|
||||
numSamples -= numAvailable;
|
||||
startSampleInFile += numAvailable;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioCDReader::isCDStillPresent() const
|
||||
{
|
||||
return volumeDir.exists();
|
||||
}
|
||||
|
||||
int AudioCDReader::getNumTracks() const
|
||||
{
|
||||
return tracks.size();
|
||||
}
|
||||
|
||||
int AudioCDReader::getPositionOfTrackStart (int trackNum) const
|
||||
{
|
||||
return trackStartSamples [trackNum];
|
||||
}
|
||||
|
||||
bool AudioCDReader::isTrackAudio (int trackNum) const
|
||||
{
|
||||
return tracks [trackNum] != 0;
|
||||
}
|
||||
|
||||
void AudioCDReader::enableIndexScanning (bool b)
|
||||
{
|
||||
// any way to do this on a Mac??
|
||||
}
|
||||
|
||||
int AudioCDReader::getLastIndex() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const Array <int> AudioCDReader::findIndexesInTrack (const int trackNumber)
|
||||
{
|
||||
return Array <int>();
|
||||
}
|
||||
|
||||
int AudioCDReader::getCDDBId()
|
||||
{
|
||||
return 0; //xxx
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
180
src/audio/audio_file_formats/juce_AudioCDReader.h
Normal file
180
src/audio/audio_file_formats/juce_AudioCDReader.h
Normal file
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOCDREADER_JUCEHEADER__
|
||||
#define __JUCE_AUDIOCDREADER_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormatReader.h"
|
||||
#include "../../text/juce_StringArray.h"
|
||||
#if JUCE_MAC
|
||||
#include "../../io/files/juce_File.h"
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A type of AudioFormatReader that reads from an audio CD.
|
||||
|
||||
One of these can be used to read a CD as if it's one big audio stream. Use the
|
||||
getPositionOfTrackStart() method to find where the individual tracks are
|
||||
within the stream.
|
||||
|
||||
@see AudioFormatReader
|
||||
*/
|
||||
class JUCE_API AudioCDReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Returns a list of names of Audio CDs currently available for reading.
|
||||
|
||||
If there's a CD drive but no CD in it, this might return an empty list, or
|
||||
possibly a device that can be opened but which has no tracks, depending
|
||||
on the platform.
|
||||
|
||||
@see createReaderForCD
|
||||
*/
|
||||
static const StringArray getAvailableCDNames();
|
||||
|
||||
/** Tries to create an AudioFormatReader that can read from an Audio CD.
|
||||
|
||||
@param index the index of one of the available CDs - use getAvailableCDNames()
|
||||
to find out how many there are.
|
||||
@returns a new AudioCDReader object, or 0 if it couldn't be created. The
|
||||
caller will be responsible for deleting the object returned.
|
||||
*/
|
||||
static AudioCDReader* createReaderForCD (const int index);
|
||||
|
||||
//==============================================================================
|
||||
/** Destructor. */
|
||||
~AudioCDReader();
|
||||
|
||||
/** Implementation of the AudioFormatReader method. */
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples);
|
||||
|
||||
/** Checks whether the CD has been removed from the drive.
|
||||
*/
|
||||
bool isCDStillPresent() const;
|
||||
|
||||
/** Returns the total number of tracks (audio + data).
|
||||
*/
|
||||
int getNumTracks() const;
|
||||
|
||||
/** Finds the sample offset of the start of a track.
|
||||
|
||||
@param trackNum the track number, where 0 is the first track.
|
||||
*/
|
||||
int getPositionOfTrackStart (int trackNum) const;
|
||||
|
||||
/** Returns true if a given track is an audio track.
|
||||
|
||||
@param trackNum the track number, where 0 is the first track.
|
||||
*/
|
||||
bool isTrackAudio (int trackNum) const;
|
||||
|
||||
/** Refreshes the object's table of contents.
|
||||
|
||||
If the disc has been ejected and a different one put in since this
|
||||
object was created, this will cause it to update its idea of how many tracks
|
||||
there are, etc.
|
||||
*/
|
||||
void refreshTrackLengths();
|
||||
|
||||
/** Enables scanning for indexes within tracks.
|
||||
|
||||
@see getLastIndex
|
||||
*/
|
||||
void enableIndexScanning (bool enabled);
|
||||
|
||||
/** Returns the index number found during the last read() call.
|
||||
|
||||
Index scanning is turned off by default - turn it on with enableIndexScanning().
|
||||
|
||||
Then when the read() method is called, if it comes across an index within that
|
||||
block, the index number is stored and returned by this method.
|
||||
|
||||
Some devices might not support indexes, of course.
|
||||
|
||||
(If you don't know what CD indexes are, it's unlikely you'll ever need them).
|
||||
|
||||
@see enableIndexScanning
|
||||
*/
|
||||
int getLastIndex() const;
|
||||
|
||||
/** Scans a track to find the position of any indexes within it.
|
||||
|
||||
@param trackNumber the track to look in, where 0 is the first track on the disc
|
||||
@returns an array of sample positions of any index points found (not including
|
||||
the index that marks the start of the track)
|
||||
*/
|
||||
const Array <int> findIndexesInTrack (const int trackNumber);
|
||||
|
||||
/** Returns the CDDB id number for the CD.
|
||||
|
||||
It's not a great way of identifying a disc, but it's traditional.
|
||||
*/
|
||||
int getCDDBId();
|
||||
|
||||
/** Tries to eject the disk.
|
||||
|
||||
Of course this might not be possible, if some other process is using it.
|
||||
*/
|
||||
void ejectDisk();
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
|
||||
#if JUCE_MAC
|
||||
File volumeDir;
|
||||
OwnedArray<File> tracks;
|
||||
Array <int> trackStartSamples;
|
||||
int currentReaderTrack;
|
||||
AudioFormatReader* reader;
|
||||
AudioCDReader (const File& volume);
|
||||
public:
|
||||
static int compareElements (const File* const, const File* const) throw();
|
||||
private:
|
||||
|
||||
#elif JUCE_WIN32
|
||||
int numTracks;
|
||||
int trackStarts[100];
|
||||
bool audioTracks [100];
|
||||
void* handle;
|
||||
bool indexingEnabled;
|
||||
int lastIndex, firstFrameInBuffer, samplesInBuffer;
|
||||
MemoryBlock buffer;
|
||||
AudioCDReader (void* handle);
|
||||
int getIndexAt (int samplePos);
|
||||
|
||||
#elif JUCE_LINUX
|
||||
AudioCDReader();
|
||||
#endif
|
||||
|
||||
AudioCDReader (const AudioCDReader&);
|
||||
const AudioCDReader& operator= (const AudioCDReader&);
|
||||
};
|
||||
|
||||
#endif // __JUCE_AUDIOCDREADER_JUCEHEADER__
|
||||
557
src/audio/audio_file_formats/juce_AudioFormat.cpp
Normal file
557
src/audio/audio_file_formats/juce_AudioFormat.cpp
Normal file
|
|
@ -0,0 +1,557 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_AudioFormat.h"
|
||||
#include "../dsp/juce_AudioSampleBuffer.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader::AudioFormatReader (InputStream* const in,
|
||||
const String& formatName_)
|
||||
: sampleRate (0),
|
||||
bitsPerSample (0),
|
||||
lengthInSamples (0),
|
||||
numChannels (0),
|
||||
usesFloatingPointData (false),
|
||||
input (in),
|
||||
formatName (formatName_)
|
||||
{
|
||||
}
|
||||
|
||||
AudioFormatReader::~AudioFormatReader()
|
||||
{
|
||||
delete input;
|
||||
}
|
||||
|
||||
bool AudioFormatReader::read (int** destSamples,
|
||||
int numDestChannels,
|
||||
int64 startSampleInSource,
|
||||
int numSamplesToRead,
|
||||
const bool fillLeftoverChannelsWithCopies)
|
||||
{
|
||||
jassert (numDestChannels > 0); // you have to actually give this some channels to work with!
|
||||
|
||||
int startOffsetInDestBuffer = 0;
|
||||
|
||||
if (startSampleInSource < 0)
|
||||
{
|
||||
const int silence = (int) jmin (-startSampleInSource, (int64) numSamplesToRead);
|
||||
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != 0)
|
||||
zeromem (destSamples[i], sizeof (int) * silence);
|
||||
|
||||
startOffsetInDestBuffer += silence;
|
||||
numSamplesToRead -= silence;
|
||||
startSampleInSource = 0;
|
||||
}
|
||||
|
||||
if (numSamplesToRead <= 0)
|
||||
return true;
|
||||
|
||||
if (! readSamples (destSamples, jmin (numChannels, numDestChannels), startOffsetInDestBuffer,
|
||||
startSampleInSource, numSamplesToRead))
|
||||
return false;
|
||||
|
||||
if (numDestChannels > (int) numChannels)
|
||||
{
|
||||
if (fillLeftoverChannelsWithCopies)
|
||||
{
|
||||
int* lastFullChannel = destSamples[0];
|
||||
|
||||
for (int i = numDestChannels; --i > 0;)
|
||||
{
|
||||
if (destSamples[i] != 0)
|
||||
{
|
||||
lastFullChannel = destSamples[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (lastFullChannel != 0)
|
||||
for (int i = numChannels; i < numDestChannels; ++i)
|
||||
if (destSamples[i] != 0)
|
||||
memcpy (destSamples[i], lastFullChannel, sizeof (int) * numSamplesToRead);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numChannels; i < numDestChannels; ++i)
|
||||
if (destSamples[i] != 0)
|
||||
zeromem (destSamples[i], sizeof (int) * numSamplesToRead);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void findMaxMin (const float* src, const int num,
|
||||
float& maxVal, float& minVal)
|
||||
{
|
||||
float mn = src[0];
|
||||
float mx = mn;
|
||||
|
||||
for (int i = 1; i < num; ++i)
|
||||
{
|
||||
const float s = src[i];
|
||||
if (s > mx)
|
||||
mx = s;
|
||||
if (s < mn)
|
||||
mn = s;
|
||||
}
|
||||
|
||||
maxVal = mx;
|
||||
minVal = mn;
|
||||
}
|
||||
|
||||
void AudioFormatReader::readMaxLevels (int64 startSampleInFile,
|
||||
int64 numSamples,
|
||||
float& lowestLeft, float& highestLeft,
|
||||
float& lowestRight, float& highestRight)
|
||||
{
|
||||
if (numSamples <= 0)
|
||||
{
|
||||
lowestLeft = 0;
|
||||
lowestRight = 0;
|
||||
highestLeft = 0;
|
||||
highestRight = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
const int bufferSize = (int) jmin (numSamples, (int64) 4096);
|
||||
MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64);
|
||||
|
||||
int* tempBuffer[3];
|
||||
tempBuffer[0] = (int*) tempSpace.getData();
|
||||
tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize;
|
||||
tempBuffer[2] = 0;
|
||||
|
||||
if (usesFloatingPointData)
|
||||
{
|
||||
float lmin = 1.0e6;
|
||||
float lmax = -lmin;
|
||||
float rmin = lmin;
|
||||
float rmax = lmax;
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
|
||||
read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false);
|
||||
|
||||
numSamples -= numToDo;
|
||||
|
||||
float bufmin, bufmax;
|
||||
findMaxMin ((float*) tempBuffer[0], numToDo, bufmax, bufmin);
|
||||
lmin = jmin (lmin, bufmin);
|
||||
lmax = jmax (lmax, bufmax);
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
findMaxMin ((float*) tempBuffer[1], numToDo, bufmax, bufmin);
|
||||
rmin = jmin (rmin, bufmin);
|
||||
rmax = jmax (rmax, bufmax);
|
||||
}
|
||||
}
|
||||
|
||||
if (numChannels <= 1)
|
||||
{
|
||||
rmax = lmax;
|
||||
rmin = lmin;
|
||||
}
|
||||
|
||||
lowestLeft = lmin;
|
||||
highestLeft = lmax;
|
||||
lowestRight = rmin;
|
||||
highestRight = rmax;
|
||||
}
|
||||
else
|
||||
{
|
||||
int lmax = INT_MIN;
|
||||
int lmin = INT_MAX;
|
||||
int rmax = INT_MIN;
|
||||
int rmin = INT_MAX;
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
const int numToDo = (int) jmin (numSamples, (int64) bufferSize);
|
||||
read ((int**) tempBuffer, 2, startSampleInFile, numToDo, false);
|
||||
|
||||
numSamples -= numToDo;
|
||||
|
||||
for (int j = numChannels; --j >= 0;)
|
||||
{
|
||||
int bufMax = INT_MIN;
|
||||
int bufMin = INT_MAX;
|
||||
|
||||
const int* const b = tempBuffer[j];
|
||||
|
||||
for (int i = 0; i < numToDo; ++i)
|
||||
{
|
||||
const int samp = b[i];
|
||||
|
||||
if (samp < bufMin)
|
||||
bufMin = samp;
|
||||
|
||||
if (samp > bufMax)
|
||||
bufMax = samp;
|
||||
}
|
||||
|
||||
if (j == 0)
|
||||
{
|
||||
lmax = jmax (lmax, bufMax);
|
||||
lmin = jmin (lmin, bufMin);
|
||||
}
|
||||
else
|
||||
{
|
||||
rmax = jmax (rmax, bufMax);
|
||||
rmin = jmin (rmin, bufMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (numChannels <= 1)
|
||||
{
|
||||
rmax = lmax;
|
||||
rmin = lmin;
|
||||
}
|
||||
|
||||
lowestLeft = lmin / (float)INT_MAX;
|
||||
highestLeft = lmax / (float)INT_MAX;
|
||||
lowestRight = rmin / (float)INT_MAX;
|
||||
highestRight = rmax / (float)INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
int64 AudioFormatReader::searchForLevel (int64 startSample,
|
||||
int64 numSamplesToSearch,
|
||||
const double magnitudeRangeMinimum,
|
||||
const double magnitudeRangeMaximum,
|
||||
const int minimumConsecutiveSamples)
|
||||
{
|
||||
if (numSamplesToSearch == 0)
|
||||
return -1;
|
||||
|
||||
const int bufferSize = 4096;
|
||||
MemoryBlock tempSpace (bufferSize * sizeof (int) * 2 + 64);
|
||||
|
||||
int* tempBuffer[3];
|
||||
tempBuffer[0] = (int*) tempSpace.getData();
|
||||
tempBuffer[1] = ((int*) tempSpace.getData()) + bufferSize;
|
||||
tempBuffer[2] = 0;
|
||||
|
||||
int consecutive = 0;
|
||||
int64 firstMatchPos = -1;
|
||||
|
||||
jassert (magnitudeRangeMaximum > magnitudeRangeMinimum);
|
||||
|
||||
const double doubleMin = jlimit (0.0, (double) INT_MAX, magnitudeRangeMinimum * INT_MAX);
|
||||
const double doubleMax = jlimit (doubleMin, (double) INT_MAX, magnitudeRangeMaximum * INT_MAX);
|
||||
const int intMagnitudeRangeMinimum = roundDoubleToInt (doubleMin);
|
||||
const int intMagnitudeRangeMaximum = roundDoubleToInt (doubleMax);
|
||||
|
||||
while (numSamplesToSearch != 0)
|
||||
{
|
||||
const int numThisTime = (int) jmin (abs64 (numSamplesToSearch), (int64) bufferSize);
|
||||
int64 bufferStart = startSample;
|
||||
|
||||
if (numSamplesToSearch < 0)
|
||||
bufferStart -= numThisTime;
|
||||
|
||||
if (bufferStart >= (int) lengthInSamples)
|
||||
break;
|
||||
|
||||
read ((int**) tempBuffer, 2, bufferStart, numThisTime, false);
|
||||
|
||||
int num = numThisTime;
|
||||
while (--num >= 0)
|
||||
{
|
||||
if (numSamplesToSearch < 0)
|
||||
--startSample;
|
||||
|
||||
bool matches = false;
|
||||
const int index = (int) (startSample - bufferStart);
|
||||
|
||||
if (usesFloatingPointData)
|
||||
{
|
||||
const float sample1 = fabsf (((float*) tempBuffer[0]) [index]);
|
||||
|
||||
if (sample1 >= magnitudeRangeMinimum
|
||||
&& sample1 <= magnitudeRangeMaximum)
|
||||
{
|
||||
matches = true;
|
||||
}
|
||||
else if (numChannels > 1)
|
||||
{
|
||||
const float sample2 = fabsf (((float*) tempBuffer[1]) [index]);
|
||||
|
||||
matches = (sample2 >= magnitudeRangeMinimum
|
||||
&& sample2 <= magnitudeRangeMaximum);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const int sample1 = abs (tempBuffer[0] [index]);
|
||||
|
||||
if (sample1 >= intMagnitudeRangeMinimum
|
||||
&& sample1 <= intMagnitudeRangeMaximum)
|
||||
{
|
||||
matches = true;
|
||||
}
|
||||
else if (numChannels > 1)
|
||||
{
|
||||
const int sample2 = abs (tempBuffer[1][index]);
|
||||
|
||||
matches = (sample2 >= intMagnitudeRangeMinimum
|
||||
&& sample2 <= intMagnitudeRangeMaximum);
|
||||
}
|
||||
}
|
||||
|
||||
if (matches)
|
||||
{
|
||||
if (firstMatchPos < 0)
|
||||
firstMatchPos = startSample;
|
||||
|
||||
if (++consecutive >= minimumConsecutiveSamples)
|
||||
{
|
||||
if (firstMatchPos < 0 || firstMatchPos >= lengthInSamples)
|
||||
return -1;
|
||||
|
||||
return firstMatchPos;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
consecutive = 0;
|
||||
firstMatchPos = -1;
|
||||
}
|
||||
|
||||
if (numSamplesToSearch > 0)
|
||||
++startSample;
|
||||
}
|
||||
|
||||
if (numSamplesToSearch > 0)
|
||||
numSamplesToSearch -= numThisTime;
|
||||
else
|
||||
numSamplesToSearch += numThisTime;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatWriter::AudioFormatWriter (OutputStream* const out,
|
||||
const String& formatName_,
|
||||
const double rate,
|
||||
const unsigned int numChannels_,
|
||||
const unsigned int bitsPerSample_)
|
||||
: sampleRate (rate),
|
||||
numChannels (numChannels_),
|
||||
bitsPerSample (bitsPerSample_),
|
||||
usesFloatingPointData (false),
|
||||
output (out),
|
||||
formatName (formatName_)
|
||||
{
|
||||
}
|
||||
|
||||
AudioFormatWriter::~AudioFormatWriter()
|
||||
{
|
||||
delete output;
|
||||
}
|
||||
|
||||
bool AudioFormatWriter::writeFromAudioReader (AudioFormatReader& reader,
|
||||
int64 startSample,
|
||||
int64 numSamplesToRead)
|
||||
{
|
||||
const int bufferSize = 16384;
|
||||
const int maxChans = 128;
|
||||
AudioSampleBuffer tempBuffer (reader.numChannels, bufferSize);
|
||||
int* buffers [maxChans];
|
||||
|
||||
for (int i = maxChans; --i >= 0;)
|
||||
buffers[i] = 0;
|
||||
|
||||
if (numSamplesToRead < 0)
|
||||
numSamplesToRead = reader.lengthInSamples;
|
||||
|
||||
while (numSamplesToRead > 0)
|
||||
{
|
||||
const int numToDo = (int) jmin (numSamplesToRead, (int64) bufferSize);
|
||||
|
||||
for (int i = tempBuffer.getNumChannels(); --i >= 0;)
|
||||
buffers[i] = (int*) tempBuffer.getSampleData (i, 0);
|
||||
|
||||
if (! reader.read (buffers, maxChans, startSample, numToDo, false))
|
||||
return false;
|
||||
|
||||
if (reader.usesFloatingPointData != isFloatingPoint())
|
||||
{
|
||||
int** bufferChan = buffers;
|
||||
|
||||
while (*bufferChan != 0)
|
||||
{
|
||||
int* b = *bufferChan++;
|
||||
|
||||
if (isFloatingPoint())
|
||||
{
|
||||
// int -> float
|
||||
const double factor = 1.0 / INT_MAX;
|
||||
|
||||
for (int i = 0; i < numToDo; ++i)
|
||||
((float*)b)[i] = (float) (factor * b[i]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// float -> int
|
||||
for (int i = 0; i < numToDo; ++i)
|
||||
{
|
||||
const double samp = *(const float*) b;
|
||||
|
||||
if (samp <= -1.0)
|
||||
*b++ = INT_MIN;
|
||||
else if (samp >= 1.0)
|
||||
*b++ = INT_MAX;
|
||||
else
|
||||
*b++ = roundDoubleToInt (INT_MAX * samp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! write ((const int**) buffers, numToDo))
|
||||
return false;
|
||||
|
||||
numSamplesToRead -= numToDo;
|
||||
startSample += numToDo;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AudioFormatWriter::writeFromAudioSource (AudioSource& source,
|
||||
int numSamplesToRead,
|
||||
const int samplesPerBlock)
|
||||
{
|
||||
const int maxChans = 128;
|
||||
AudioSampleBuffer tempBuffer (getNumChannels(), samplesPerBlock);
|
||||
int* buffers [maxChans];
|
||||
|
||||
while (numSamplesToRead > 0)
|
||||
{
|
||||
const int numToDo = jmin (numSamplesToRead, samplesPerBlock);
|
||||
|
||||
AudioSourceChannelInfo info;
|
||||
info.buffer = &tempBuffer;
|
||||
info.startSample = 0;
|
||||
info.numSamples = numToDo;
|
||||
info.clearActiveBufferRegion();
|
||||
|
||||
source.getNextAudioBlock (info);
|
||||
|
||||
int i;
|
||||
for (i = maxChans; --i >= 0;)
|
||||
buffers[i] = 0;
|
||||
|
||||
for (i = tempBuffer.getNumChannels(); --i >= 0;)
|
||||
buffers[i] = (int*) tempBuffer.getSampleData (i, 0);
|
||||
|
||||
if (! isFloatingPoint())
|
||||
{
|
||||
int** bufferChan = buffers;
|
||||
|
||||
while (*bufferChan != 0)
|
||||
{
|
||||
int* b = *bufferChan++;
|
||||
|
||||
// float -> int
|
||||
for (int j = numToDo; --j >= 0;)
|
||||
{
|
||||
const double samp = *(const float*) b;
|
||||
|
||||
if (samp <= -1.0)
|
||||
*b++ = INT_MIN;
|
||||
else if (samp >= 1.0)
|
||||
*b++ = INT_MAX;
|
||||
else
|
||||
*b++ = roundDoubleToInt (INT_MAX * samp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (! write ((const int**) buffers, numToDo))
|
||||
return false;
|
||||
|
||||
numSamplesToRead -= numToDo;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AudioFormat::AudioFormat (const String& name,
|
||||
const tchar** const extensions)
|
||||
: formatName (name),
|
||||
fileExtensions (extensions)
|
||||
{
|
||||
}
|
||||
|
||||
AudioFormat::~AudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
const String& AudioFormat::getFormatName() const
|
||||
{
|
||||
return formatName;
|
||||
}
|
||||
|
||||
const StringArray& AudioFormat::getFileExtensions() const
|
||||
{
|
||||
return fileExtensions;
|
||||
}
|
||||
|
||||
bool AudioFormat::canHandleFile (const File& f)
|
||||
{
|
||||
for (int i = 0; i < fileExtensions.size(); ++i)
|
||||
if (f.hasFileExtension (fileExtensions[i]))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AudioFormat::isCompressed()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const StringArray AudioFormat::getQualityOptions()
|
||||
{
|
||||
return StringArray();
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
172
src/audio/audio_file_formats/juce_AudioFormat.h
Normal file
172
src/audio/audio_file_formats/juce_AudioFormat.h
Normal file
|
|
@ -0,0 +1,172 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOFORMAT_JUCEHEADER__
|
||||
#define __JUCE_AUDIOFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormatReader.h"
|
||||
#include "juce_AudioFormatWriter.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Subclasses of AudioFormat are used to read and write different audio
|
||||
file formats.
|
||||
|
||||
@see AudioFormatReader, AudioFormatWriter, WavAudioFormat, AiffAudioFormat
|
||||
*/
|
||||
class JUCE_API AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Destructor. */
|
||||
virtual ~AudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the name of this format.
|
||||
|
||||
e.g. "WAV file" or "AIFF file"
|
||||
*/
|
||||
const String& getFormatName() const;
|
||||
|
||||
/** Returns all the file extensions that might apply to a file of this format.
|
||||
|
||||
The first item will be the one that's preferred when creating a new file.
|
||||
|
||||
So for a wav file this might just return ".wav"; for an AIFF file it might
|
||||
return two items, ".aif" and ".aiff"
|
||||
*/
|
||||
const StringArray& getFileExtensions() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns true if this the given file can be read by this format.
|
||||
|
||||
Subclasses shouldn't do too much work here, just check the extension or
|
||||
file type. The base class implementation just checks the file's extension
|
||||
against one of the ones that was registered in the constructor.
|
||||
*/
|
||||
virtual bool canHandleFile (const File& fileToTest);
|
||||
|
||||
/** Returns a set of sample rates that the format can read and write. */
|
||||
virtual const Array <int> getPossibleSampleRates() = 0;
|
||||
|
||||
/** Returns a set of bit depths that the format can read and write. */
|
||||
virtual const Array <int> getPossibleBitDepths() = 0;
|
||||
|
||||
/** Returns true if the format can do 2-channel audio. */
|
||||
virtual bool canDoStereo() = 0;
|
||||
|
||||
/** Returns true if the format can do 1-channel audio. */
|
||||
virtual bool canDoMono() = 0;
|
||||
|
||||
/** Returns true if the format uses compressed data. */
|
||||
virtual bool isCompressed();
|
||||
|
||||
/** Returns a list of different qualities that can be used when writing.
|
||||
|
||||
Non-compressed formats will just return an empty array, but for something
|
||||
like Ogg-Vorbis or MP3, it might return a list of bit-rates, etc.
|
||||
|
||||
When calling createWriterFor(), an index from this array is passed in to
|
||||
tell the format which option is required.
|
||||
*/
|
||||
virtual const StringArray getQualityOptions();
|
||||
|
||||
//==============================================================================
|
||||
/** Tries to create an object that can read from a stream containing audio
|
||||
data in this format.
|
||||
|
||||
The reader object that is returned can be used to read from the stream, and
|
||||
should then be deleted by the caller.
|
||||
|
||||
@param sourceStream the stream to read from - the AudioFormatReader object
|
||||
that is returned will delete this stream when it no longer
|
||||
needs it.
|
||||
@param deleteStreamIfOpeningFails if no reader can be created, this determines whether this method
|
||||
should delete the stream object that was passed-in. (If a valid
|
||||
reader is returned, it will always be in charge of deleting the
|
||||
stream, so this parameter is ignored)
|
||||
@see AudioFormatReader
|
||||
*/
|
||||
virtual AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails) = 0;
|
||||
|
||||
/** Tries to create an object that can write to a stream with this audio format.
|
||||
|
||||
The writer object that is returned can be used to write to the stream, and
|
||||
should then be deleted by the caller.
|
||||
|
||||
If the stream can't be created for some reason (e.g. the parameters passed in
|
||||
here aren't suitable), this will return 0.
|
||||
|
||||
@param streamToWriteTo the stream that the data will go to - this will be
|
||||
deleted by the AudioFormatWriter object when it's no longer
|
||||
needed. If no AudioFormatWriter can be created by this method,
|
||||
the stream will NOT be deleted, so that the caller can re-use it
|
||||
to try to open a different format, etc
|
||||
@param sampleRateToUse the sample rate for the file, which must be one of the ones
|
||||
returned by getPossibleSampleRates()
|
||||
@param numberOfChannels the number of channels - this must be either 1 or 2, and
|
||||
the choice will depend on the results of canDoMono() and
|
||||
canDoStereo()
|
||||
@param bitsPerSample the bits per sample to use - this must be one of the values
|
||||
returned by getPossibleBitDepths()
|
||||
@param metadataValues a set of metadata values that the writer should try to write
|
||||
to the stream. Exactly what these are depends on the format,
|
||||
and the subclass doesn't actually have to do anything with
|
||||
them if it doesn't want to. Have a look at the specific format
|
||||
implementation classes to see possible values that can be
|
||||
used
|
||||
@param qualityOptionIndex the index of one of compression qualities returned by the
|
||||
getQualityOptions() method. If there aren't any quality options
|
||||
for this format, just pass 0 in this parameter, as it'll be
|
||||
ignored
|
||||
@see AudioFormatWriter
|
||||
*/
|
||||
virtual AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex) = 0;
|
||||
|
||||
protected:
|
||||
/** Creates an AudioFormat object.
|
||||
|
||||
@param formatName this sets the value that will be returned by getFormatName()
|
||||
@param fileExtensions a zero-terminated list of file extensions - this is what will
|
||||
be returned by getFileExtension()
|
||||
*/
|
||||
AudioFormat (const String& formatName,
|
||||
const tchar** const fileExtensions);
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
String formatName;
|
||||
StringArray fileExtensions;
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOFORMAT_JUCEHEADER__
|
||||
225
src/audio/audio_file_formats/juce_AudioFormatManager.cpp
Normal file
225
src/audio/audio_file_formats/juce_AudioFormatManager.cpp
Normal file
|
|
@ -0,0 +1,225 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_AudioFormatManager.h"
|
||||
#include "juce_AiffAudioFormat.h"
|
||||
#include "juce_WavAudioFormat.h"
|
||||
#include "juce_FlacAudioFormat.h"
|
||||
#include "juce_OggVorbisAudioFormat.h"
|
||||
#include "../../io/files/juce_FileInputStream.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatManager::AudioFormatManager()
|
||||
: knownFormats (4),
|
||||
defaultFormatIndex (0)
|
||||
{
|
||||
}
|
||||
|
||||
AudioFormatManager::~AudioFormatManager()
|
||||
{
|
||||
clearFormats();
|
||||
clearSingletonInstance();
|
||||
}
|
||||
|
||||
juce_ImplementSingleton (AudioFormatManager);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
void AudioFormatManager::registerFormat (AudioFormat* newFormat,
|
||||
const bool makeThisTheDefaultFormat)
|
||||
{
|
||||
jassert (newFormat != 0);
|
||||
|
||||
if (newFormat != 0)
|
||||
{
|
||||
#ifdef JUCE_DEBUG
|
||||
for (int i = getNumKnownFormats(); --i >= 0;)
|
||||
{
|
||||
if (getKnownFormat (i)->getFormatName() == newFormat->getFormatName())
|
||||
{
|
||||
jassertfalse // trying to add the same format twice!
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (makeThisTheDefaultFormat)
|
||||
defaultFormatIndex = knownFormats.size();
|
||||
|
||||
knownFormats.add (newFormat);
|
||||
}
|
||||
}
|
||||
|
||||
void AudioFormatManager::registerBasicFormats()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
registerFormat (new AiffAudioFormat(), true);
|
||||
registerFormat (new WavAudioFormat(), false);
|
||||
#else
|
||||
registerFormat (new WavAudioFormat(), true);
|
||||
registerFormat (new AiffAudioFormat(), false);
|
||||
#endif
|
||||
|
||||
#if JUCE_USE_FLAC
|
||||
registerFormat (new FlacAudioFormat(), false);
|
||||
#endif
|
||||
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
registerFormat (new OggVorbisAudioFormat(), false);
|
||||
#endif
|
||||
}
|
||||
|
||||
void AudioFormatManager::clearFormats()
|
||||
{
|
||||
for (int i = getNumKnownFormats(); --i >= 0;)
|
||||
{
|
||||
AudioFormat* const af = getKnownFormat(i);
|
||||
delete af;
|
||||
}
|
||||
|
||||
knownFormats.clear();
|
||||
defaultFormatIndex = 0;
|
||||
}
|
||||
|
||||
int AudioFormatManager::getNumKnownFormats() const
|
||||
{
|
||||
return knownFormats.size();
|
||||
}
|
||||
|
||||
AudioFormat* AudioFormatManager::getKnownFormat (const int index) const
|
||||
{
|
||||
return (AudioFormat*) knownFormats [index];
|
||||
}
|
||||
|
||||
AudioFormat* AudioFormatManager::getDefaultFormat() const
|
||||
{
|
||||
return getKnownFormat (defaultFormatIndex);
|
||||
}
|
||||
|
||||
AudioFormat* AudioFormatManager::findFormatForFileExtension (const String& fileExtension) const
|
||||
{
|
||||
String e (fileExtension);
|
||||
if (! e.startsWithChar (T('.')))
|
||||
e = T(".") + e;
|
||||
|
||||
for (int i = 0; i < getNumKnownFormats(); ++i)
|
||||
if (getKnownFormat(i)->getFileExtensions().contains (e, true))
|
||||
return getKnownFormat(i);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const String AudioFormatManager::getWildcardForAllFormats() const
|
||||
{
|
||||
StringArray allExtensions;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < getNumKnownFormats(); ++i)
|
||||
allExtensions.addArray (getKnownFormat (i)->getFileExtensions());
|
||||
|
||||
allExtensions.trim();
|
||||
allExtensions.removeEmptyStrings();
|
||||
|
||||
String s;
|
||||
for (i = 0; i < allExtensions.size(); ++i)
|
||||
{
|
||||
s << T('*');
|
||||
|
||||
if (! allExtensions[i].startsWithChar (T('.')))
|
||||
s << T('.');
|
||||
|
||||
s << allExtensions[i];
|
||||
|
||||
if (i < allExtensions.size() - 1)
|
||||
s << T(';');
|
||||
}
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* AudioFormatManager::createReaderFor (const File& file)
|
||||
{
|
||||
// you need to actually register some formats before the manager can
|
||||
// use them to open a file!
|
||||
jassert (knownFormats.size() > 0);
|
||||
|
||||
for (int i = 0; i < getNumKnownFormats(); ++i)
|
||||
{
|
||||
AudioFormat* const af = getKnownFormat(i);
|
||||
|
||||
if (af->canHandleFile (file))
|
||||
{
|
||||
InputStream* const in = file.createInputStream();
|
||||
|
||||
if (in != 0)
|
||||
{
|
||||
AudioFormatReader* const r = af->createReaderFor (in, true);
|
||||
|
||||
if (r != 0)
|
||||
return r;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
AudioFormatReader* AudioFormatManager::createReaderFor (InputStream* in)
|
||||
{
|
||||
// you need to actually register some formats before the manager can
|
||||
// use them to open a file!
|
||||
jassert (knownFormats.size() > 0);
|
||||
|
||||
if (in != 0)
|
||||
{
|
||||
const int64 originalStreamPos = in->getPosition();
|
||||
|
||||
for (int i = 0; i < getNumKnownFormats(); ++i)
|
||||
{
|
||||
AudioFormatReader* const r = getKnownFormat(i)->createReaderFor (in, false);
|
||||
|
||||
if (r != 0)
|
||||
return r;
|
||||
|
||||
in->setPosition (originalStreamPos);
|
||||
|
||||
// the stream that is passed-in must be capable of being repositioned so
|
||||
// that all the formats can have a go at opening it.
|
||||
jassert (in->getPosition() == originalStreamPos);
|
||||
}
|
||||
|
||||
delete in;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
144
src/audio/audio_file_formats/juce_AudioFormatManager.h
Normal file
144
src/audio/audio_file_formats/juce_AudioFormatManager.h
Normal file
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOFORMATMANAGER_JUCEHEADER__
|
||||
#define __JUCE_AUDIOFORMATMANAGER_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormat.h"
|
||||
#include "../../core/juce_Singleton.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
A class for keeping a list of available audio formats, and for deciding which
|
||||
one to use to open a given file.
|
||||
|
||||
You can either use this class as a singleton object, or create instances of it
|
||||
yourself. Once created, use its registerFormat() method to tell it which
|
||||
formats it should use.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API AudioFormatManager
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an empty format manager.
|
||||
|
||||
Before it'll be any use, you'll need to call registerFormat() with all the
|
||||
formats you want it to be able to recognise.
|
||||
*/
|
||||
AudioFormatManager();
|
||||
|
||||
/** Destructor. */
|
||||
~AudioFormatManager();
|
||||
|
||||
juce_DeclareSingleton (AudioFormatManager, false);
|
||||
|
||||
//==============================================================================
|
||||
/** Adds a format to the manager's list of available file types.
|
||||
|
||||
The object passed-in will be deleted by this object, so don't keep a pointer
|
||||
to it!
|
||||
|
||||
If makeThisTheDefaultFormat is true, then the getDefaultFormat() method will
|
||||
return this one when called.
|
||||
*/
|
||||
void registerFormat (AudioFormat* newFormat,
|
||||
const bool makeThisTheDefaultFormat);
|
||||
|
||||
/** Handy method to make it easy to register the formats that come with Juce.
|
||||
|
||||
Currently, this will add WAV and AIFF to the list.
|
||||
*/
|
||||
void registerBasicFormats();
|
||||
|
||||
/** Clears the list of known formats. */
|
||||
void clearFormats();
|
||||
|
||||
/** Returns the number of currently registered file formats. */
|
||||
int getNumKnownFormats() const;
|
||||
|
||||
/** Returns one of the registered file formats. */
|
||||
AudioFormat* getKnownFormat (const int index) const;
|
||||
|
||||
/** Looks for which of the known formats is listed as being for a given file
|
||||
extension.
|
||||
|
||||
The extension may have a dot before it, so e.g. ".wav" or "wav" are both ok.
|
||||
*/
|
||||
AudioFormat* findFormatForFileExtension (const String& fileExtension) const;
|
||||
|
||||
/** Returns the format which has been set as the default one.
|
||||
|
||||
You can set a format as being the default when it is registered. It's useful
|
||||
when you want to write to a file, because the best format may change between
|
||||
platforms, e.g. AIFF is preferred on the Mac, WAV on Windows.
|
||||
|
||||
If none has been set as the default, this method will just return the first
|
||||
one in the list.
|
||||
*/
|
||||
AudioFormat* getDefaultFormat() const;
|
||||
|
||||
/** Returns a set of wildcards for file-matching that contains the extensions for
|
||||
all known formats.
|
||||
|
||||
E.g. if might return "*.wav;*.aiff" if it just knows about wavs and aiffs.
|
||||
*/
|
||||
const String getWildcardForAllFormats() const;
|
||||
|
||||
//==============================================================================
|
||||
/** Searches through the known formats to try to create a suitable reader for
|
||||
this file.
|
||||
|
||||
If none of the registered formats can open the file, it'll return 0. If it
|
||||
returns a reader, it's the caller's responsibility to delete the reader.
|
||||
*/
|
||||
AudioFormatReader* createReaderFor (const File& audioFile);
|
||||
|
||||
/** Searches through the known formats to try to create a suitable reader for
|
||||
this stream.
|
||||
|
||||
The stream object that is passed-in will be deleted by this method or by the
|
||||
reader that is returned, so the caller should not keep any references to it.
|
||||
|
||||
The stream that is passed-in must be capable of being repositioned so
|
||||
that all the formats can have a go at opening it.
|
||||
|
||||
If none of the registered formats can open the stream, it'll return 0. If it
|
||||
returns a reader, it's the caller's responsibility to delete the reader.
|
||||
*/
|
||||
AudioFormatReader* createReaderFor (InputStream* audioFileStream);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
VoidArray knownFormats;
|
||||
int defaultFormatIndex;
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOFORMATMANAGER_JUCEHEADER__
|
||||
229
src/audio/audio_file_formats/juce_AudioFormatReader.h
Normal file
229
src/audio/audio_file_formats/juce_AudioFormatReader.h
Normal file
|
|
@ -0,0 +1,229 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOFORMATREADER_JUCEHEADER__
|
||||
#define __JUCE_AUDIOFORMATREADER_JUCEHEADER__
|
||||
|
||||
#include "../../io/streams/juce_InputStream.h"
|
||||
#include "../../text/juce_StringPairArray.h"
|
||||
class AudioFormat;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Reads samples from an audio file stream.
|
||||
|
||||
A subclass that reads a specific type of audio format will be created by
|
||||
an AudioFormat object.
|
||||
|
||||
@see AudioFormat, AudioFormatWriter
|
||||
*/
|
||||
class JUCE_API AudioFormatReader
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates an AudioFormatReader object.
|
||||
|
||||
@param sourceStream the stream to read from - this will be deleted
|
||||
by this object when it is no longer needed. (Some
|
||||
specialised readers might not use this parameter and
|
||||
can leave it as 0).
|
||||
@param formatName the description that will be returned by the getFormatName()
|
||||
method
|
||||
*/
|
||||
AudioFormatReader (InputStream* const sourceStream,
|
||||
const String& formatName);
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~AudioFormatReader();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a description of what type of format this is.
|
||||
|
||||
E.g. "AIFF"
|
||||
*/
|
||||
const String getFormatName() const throw() { return formatName; }
|
||||
|
||||
//==============================================================================
|
||||
/** Reads samples from the stream.
|
||||
|
||||
@param destSamples an array of buffers into which the sample data for each
|
||||
channel will be written.
|
||||
If the format is fixed-point, each channel will be written
|
||||
as an array of 32-bit signed integers using the full
|
||||
range -0x80000000 to 0x7fffffff, regardless of the source's
|
||||
bit-depth. If it is a floating-point format, you should cast
|
||||
the resulting array to a (float**) to get the values (in the
|
||||
range -1.0 to 1.0 or beyond)
|
||||
If the format is stereo, then destSamples[0] is the left channel
|
||||
data, and destSamples[1] is the right channel.
|
||||
The numDestChannels parameter indicates how many pointers this array
|
||||
contains, but some of these pointers can be null if you don't want to
|
||||
read data for some of the channels
|
||||
@param numDestChannels the number of array elements in the destChannels array
|
||||
@param startSampleInSource the position in the audio file or stream at which the samples
|
||||
should be read, as a number of samples from the start of the
|
||||
stream. It's ok for this to be beyond the start or end of the
|
||||
available data - any samples that are out-of-range will be returned
|
||||
as zeros.
|
||||
@param numSamplesToRead the number of samples to read. If this is greater than the number
|
||||
of samples that the file or stream contains. the result will be padded
|
||||
with zeros
|
||||
@param fillLeftoverChannelsWithCopies if true, this indicates that if there's no source data available
|
||||
for some of the channels that you pass in, then they should be filled with
|
||||
copies of valid source channels.
|
||||
E.g. if you're reading a mono file and you pass 2 channels to this method, then
|
||||
if fillLeftoverChannelsWithCopies is true, both destination channels will be filled
|
||||
with the same data from the file's single channel. If fillLeftoverChannelsWithCopies
|
||||
was false, then only the first channel would be filled with the file's contents, and
|
||||
the second would be cleared. If there are many channels, e.g. you try to read 4 channels
|
||||
from a stereo file, then the last 3 would all end up with copies of the same data.
|
||||
@returns true if the operation succeeded, false if there was an error. Note
|
||||
that reading sections of data beyond the extent of the stream isn't an
|
||||
error - the reader should just return zeros for these regions
|
||||
@see readMaxLevels
|
||||
*/
|
||||
bool read (int** destSamples,
|
||||
int numDestChannels,
|
||||
int64 startSampleInSource,
|
||||
int numSamplesToRead,
|
||||
const bool fillLeftoverChannelsWithCopies);
|
||||
|
||||
/** Finds the highest and lowest sample levels from a section of the audio stream.
|
||||
|
||||
This will read a block of samples from the stream, and measure the
|
||||
highest and lowest sample levels from the channels in that section, returning
|
||||
these as normalised floating-point levels.
|
||||
|
||||
@param startSample the offset into the audio stream to start reading from. It's
|
||||
ok for this to be beyond the start or end of the stream.
|
||||
@param numSamples how many samples to read
|
||||
@param lowestLeft on return, this is the lowest absolute sample from the left channel
|
||||
@param highestLeft on return, this is the highest absolute sample from the left channel
|
||||
@param lowestRight on return, this is the lowest absolute sample from the right
|
||||
channel (if there is one)
|
||||
@param highestRight on return, this is the highest absolute sample from the right
|
||||
channel (if there is one)
|
||||
@see read
|
||||
*/
|
||||
virtual void readMaxLevels (int64 startSample,
|
||||
int64 numSamples,
|
||||
float& lowestLeft,
|
||||
float& highestLeft,
|
||||
float& lowestRight,
|
||||
float& highestRight);
|
||||
|
||||
/** Scans the source looking for a sample whose magnitude is in a specified range.
|
||||
|
||||
This will read from the source, either forwards or backwards between two sample
|
||||
positions, until it finds a sample whose magnitude lies between two specified levels.
|
||||
|
||||
If it finds a suitable sample, it returns its position; if not, it will return -1.
|
||||
|
||||
There's also a minimumConsecutiveSamples setting to help avoid spikes or zero-crossing
|
||||
points when you're searching for a continuous range of samples
|
||||
|
||||
@param startSample the first sample to look at
|
||||
@param numSamplesToSearch the number of samples to scan. If this value is negative,
|
||||
the search will go backwards
|
||||
@param magnitudeRangeMinimum the lowest magnitude (inclusive) that is considered a hit, from 0 to 1.0
|
||||
@param magnitudeRangeMaximum the highest magnitude (inclusive) that is considered a hit, from 0 to 1.0
|
||||
@param minimumConsecutiveSamples if this is > 0, the method will only look for a sequence
|
||||
of this many consecutive samples, all of which lie
|
||||
within the target range. When it finds such a sequence,
|
||||
it returns the position of the first in-range sample
|
||||
it found (i.e. the earliest one if scanning forwards, the
|
||||
latest one if scanning backwards)
|
||||
*/
|
||||
int64 searchForLevel (int64 startSample,
|
||||
int64 numSamplesToSearch,
|
||||
const double magnitudeRangeMinimum,
|
||||
const double magnitudeRangeMaximum,
|
||||
const int minimumConsecutiveSamples);
|
||||
|
||||
//==============================================================================
|
||||
/** The sample-rate of the stream. */
|
||||
double sampleRate;
|
||||
|
||||
/** The number of bits per sample, e.g. 16, 24, 32. */
|
||||
unsigned int bitsPerSample;
|
||||
|
||||
/** The total number of samples in the audio stream. */
|
||||
int64 lengthInSamples;
|
||||
|
||||
/** The total number of channels in the audio stream. */
|
||||
unsigned int numChannels;
|
||||
|
||||
/** Indicates whether the data is floating-point or fixed. */
|
||||
bool usesFloatingPointData;
|
||||
|
||||
/** A set of metadata values that the reader has pulled out of the stream.
|
||||
|
||||
Exactly what these values are depends on the format, so you can
|
||||
check out the format implementation code to see what kind of stuff
|
||||
they understand.
|
||||
*/
|
||||
StringPairArray metadataValues;
|
||||
|
||||
/** The input stream, for use by subclasses. */
|
||||
InputStream* input;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/** Subclasses must implement this method to perform the low-level read operation.
|
||||
|
||||
Callers should use read() instead of calling this directly.
|
||||
|
||||
@param destSamples the array of destination buffers to fill. Some of these
|
||||
pointers may be null
|
||||
@param numDestChannels the number of items in the destSamples array. This
|
||||
value is guaranteed not to be greater than the number of
|
||||
channels that this reader object contains
|
||||
@param startOffsetInDestBuffer the number of samples from the start of the
|
||||
dest data at which to begin writing
|
||||
@param startSampleInFile the number of samples into the source data at which
|
||||
to begin reading. This value is guaranteed to be >= 0.
|
||||
@param numSamples the number of samples to read
|
||||
*/
|
||||
virtual bool readSamples (int** destSamples,
|
||||
int numDestChannels,
|
||||
int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile,
|
||||
int numSamples) = 0;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
String formatName;
|
||||
|
||||
AudioFormatReader (const AudioFormatReader&);
|
||||
const AudioFormatReader& operator= (const AudioFormatReader&);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOFORMATREADER_JUCEHEADER__
|
||||
168
src/audio/audio_file_formats/juce_AudioFormatWriter.h
Normal file
168
src/audio/audio_file_formats/juce_AudioFormatWriter.h
Normal file
|
|
@ -0,0 +1,168 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOFORMATWRITER_JUCEHEADER__
|
||||
#define __JUCE_AUDIOFORMATWRITER_JUCEHEADER__
|
||||
|
||||
#include "../../io/files/juce_FileOutputStream.h"
|
||||
#include "juce_AudioFormatReader.h"
|
||||
#include "../audio_sources/juce_AudioSource.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Writes samples to an audio file stream.
|
||||
|
||||
A subclass that writes a specific type of audio format will be created by
|
||||
an AudioFormat object.
|
||||
|
||||
After creating one of these with the AudioFormat::createWriterFor() method
|
||||
you can call its write() method to store the samples, and then delete it.
|
||||
|
||||
@see AudioFormat, AudioFormatReader
|
||||
*/
|
||||
class JUCE_API AudioFormatWriter
|
||||
{
|
||||
protected:
|
||||
//==============================================================================
|
||||
/** Creates an AudioFormatWriter object.
|
||||
|
||||
@param destStream the stream to write to - this will be deleted
|
||||
by this object when it is no longer needed
|
||||
@param formatName the description that will be returned by the getFormatName()
|
||||
method
|
||||
@param sampleRate the sample rate to use - the base class just stores
|
||||
this value, it doesn't do anything with it
|
||||
@param numberOfChannels the number of channels to write - the base class just stores
|
||||
this value, it doesn't do anything with it
|
||||
@param bitsPerSample the bit depth of the stream - the base class just stores
|
||||
this value, it doesn't do anything with it
|
||||
*/
|
||||
AudioFormatWriter (OutputStream* const destStream,
|
||||
const String& formatName,
|
||||
const double sampleRate,
|
||||
const unsigned int numberOfChannels,
|
||||
const unsigned int bitsPerSample);
|
||||
|
||||
public:
|
||||
/** Destructor. */
|
||||
virtual ~AudioFormatWriter();
|
||||
|
||||
//==============================================================================
|
||||
/** Returns a description of what type of format this is.
|
||||
|
||||
E.g. "AIFF file"
|
||||
*/
|
||||
const String getFormatName() const throw() { return formatName; }
|
||||
|
||||
//==============================================================================
|
||||
/** Writes a set of samples to the audio stream.
|
||||
|
||||
Note that if you're trying to write the contents of an AudioSampleBuffer, you
|
||||
can use AudioSampleBuffer::writeToAudioWriter().
|
||||
|
||||
@param samplesToWrite an array of arrays containing the sample data for
|
||||
each channel to write. This is a zero-terminated
|
||||
array of arrays, and can contain a different number
|
||||
of channels than the actual stream uses, and the
|
||||
writer should do its best to cope with this.
|
||||
If the format is fixed-point, each channel will be formatted
|
||||
as an array of signed integers using the full 32-bit
|
||||
range -0x80000000 to 0x7fffffff, regardless of the source's
|
||||
bit-depth. If it is a floating-point format, you should treat
|
||||
the arrays as arrays of floats, and just cast it to an (int**)
|
||||
to pass it into the method.
|
||||
@param numSamples the number of samples to write
|
||||
*/
|
||||
virtual bool write (const int** samplesToWrite,
|
||||
int numSamples) = 0;
|
||||
|
||||
//==============================================================================
|
||||
/** Reads a section of samples from an AudioFormatReader, and writes these to
|
||||
the output.
|
||||
|
||||
This will take care of any floating-point conversion that's required to convert
|
||||
between the two formats. It won't deal with sample-rate conversion, though.
|
||||
|
||||
If numSamplesToRead < 0, it will write the entire length of the reader.
|
||||
|
||||
@returns false if it can't read or write properly during the operation
|
||||
*/
|
||||
bool writeFromAudioReader (AudioFormatReader& reader,
|
||||
int64 startSample,
|
||||
int64 numSamplesToRead);
|
||||
|
||||
/** Reads some samples from an AudioSource, and writes these to the output.
|
||||
|
||||
The source must already have been initialised with the AudioSource::prepareToPlay() method
|
||||
|
||||
@param source the source to read from
|
||||
@param numSamplesToRead total number of samples to read and write
|
||||
@param samplesPerBlock the maximum number of samples to fetch from the source
|
||||
@returns false if it can't read or write properly during the operation
|
||||
*/
|
||||
bool writeFromAudioSource (AudioSource& source,
|
||||
int numSamplesToRead,
|
||||
const int samplesPerBlock = 2048);
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the sample rate being used. */
|
||||
double getSampleRate() const throw() { return sampleRate; }
|
||||
|
||||
/** Returns the number of channels being written. */
|
||||
int getNumChannels() const throw() { return numChannels; }
|
||||
|
||||
/** Returns the bit-depth of the data being written. */
|
||||
int getBitsPerSample() const throw() { return bitsPerSample; }
|
||||
|
||||
/** Returns true if it's a floating-point format, false if it's fixed-point. */
|
||||
bool isFloatingPoint() const throw() { return usesFloatingPointData; }
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
protected:
|
||||
/** The sample rate of the stream. */
|
||||
double sampleRate;
|
||||
|
||||
/** The number of channels being written to the stream. */
|
||||
unsigned int numChannels;
|
||||
|
||||
/** The bit depth of the file. */
|
||||
unsigned int bitsPerSample;
|
||||
|
||||
/** True if it's a floating-point format, false if it's fixed-point. */
|
||||
bool usesFloatingPointData;
|
||||
|
||||
/** The output stream for Use by subclasses. */
|
||||
OutputStream* output;
|
||||
|
||||
private:
|
||||
String formatName;
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOFORMATWRITER_JUCEHEADER__
|
||||
96
src/audio/audio_file_formats/juce_AudioSubsectionReader.cpp
Normal file
96
src/audio/audio_file_formats/juce_AudioSubsectionReader.cpp
Normal file
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_AudioSubsectionReader.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
AudioSubsectionReader::AudioSubsectionReader (AudioFormatReader* const source_,
|
||||
const int64 startSample_,
|
||||
const int64 length_,
|
||||
const bool deleteSourceWhenDeleted_)
|
||||
: AudioFormatReader (0, source_->getFormatName()),
|
||||
source (source_),
|
||||
startSample (startSample_),
|
||||
deleteSourceWhenDeleted (deleteSourceWhenDeleted_)
|
||||
{
|
||||
length = jmin (jmax ((int64) 0, source->lengthInSamples - startSample), length_);
|
||||
|
||||
sampleRate = source->sampleRate;
|
||||
bitsPerSample = source->bitsPerSample;
|
||||
lengthInSamples = length;
|
||||
numChannels = source->numChannels;
|
||||
usesFloatingPointData = source->usesFloatingPointData;
|
||||
}
|
||||
|
||||
AudioSubsectionReader::~AudioSubsectionReader()
|
||||
{
|
||||
if (deleteSourceWhenDeleted)
|
||||
delete source;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
if (startSampleInFile + numSamples > length)
|
||||
{
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != 0)
|
||||
zeromem (destSamples[i], sizeof (int) * numSamples);
|
||||
|
||||
numSamples = jmin (numSamples, (int) (length - startSampleInFile));
|
||||
|
||||
if (numSamples <= 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return source->readSamples (destSamples, numDestChannels, startOffsetInDestBuffer,
|
||||
startSampleInFile + startSample, numSamples);
|
||||
}
|
||||
|
||||
void AudioSubsectionReader::readMaxLevels (int64 startSampleInFile,
|
||||
int64 numSamples,
|
||||
float& lowestLeft,
|
||||
float& highestLeft,
|
||||
float& lowestRight,
|
||||
float& highestRight)
|
||||
{
|
||||
startSampleInFile = jmax ((int64) 0, startSampleInFile);
|
||||
numSamples = jmax ((int64) 0, jmin (numSamples, length - startSampleInFile));
|
||||
|
||||
source->readMaxLevels (startSampleInFile + startSample,
|
||||
numSamples,
|
||||
lowestLeft,
|
||||
highestLeft,
|
||||
lowestRight,
|
||||
highestRight);
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
93
src/audio/audio_file_formats/juce_AudioSubsectionReader.h
Normal file
93
src/audio/audio_file_formats/juce_AudioSubsectionReader.h
Normal file
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__
|
||||
#define __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormatReader.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
This class is used to wrap an AudioFormatReader and only read from a
|
||||
subsection of the file.
|
||||
|
||||
So if you have a reader which can read a 1000 sample file, you could wrap it
|
||||
in one of these to only access, e.g. samples 100 to 200, and any samples
|
||||
outside that will come back as 0. Accessing sample 0 from this reader will
|
||||
actually read the first sample from the other's subsection, which might
|
||||
be at a non-zero position.
|
||||
|
||||
@see AudioFormatReader
|
||||
*/
|
||||
class JUCE_API AudioSubsectionReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a AudioSubsectionReader for a given data source.
|
||||
|
||||
@param sourceReader the source reader from which we'll be taking data
|
||||
@param subsectionStartSample the sample within the source reader which will be
|
||||
mapped onto sample 0 for this reader.
|
||||
@param subsectionLength the number of samples from the source that will
|
||||
make up the subsection. If this reader is asked for
|
||||
any samples beyond this region, it will return zero.
|
||||
@param deleteSourceWhenDeleted if true, the sourceReader object will be deleted when
|
||||
this object is deleted.
|
||||
*/
|
||||
AudioSubsectionReader (AudioFormatReader* const sourceReader,
|
||||
const int64 subsectionStartSample,
|
||||
const int64 subsectionLength,
|
||||
const bool deleteSourceWhenDeleted);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioSubsectionReader();
|
||||
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples);
|
||||
|
||||
void readMaxLevels (int64 startSample,
|
||||
int64 numSamples,
|
||||
float& lowestLeft,
|
||||
float& highestLeft,
|
||||
float& lowestRight,
|
||||
float& highestRight);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
AudioFormatReader* const source;
|
||||
int64 startSample, length;
|
||||
const bool deleteSourceWhenDeleted;
|
||||
|
||||
AudioSubsectionReader (const AudioSubsectionReader&);
|
||||
const AudioSubsectionReader& operator= (const AudioSubsectionReader&);
|
||||
};
|
||||
|
||||
#endif // __JUCE_AUDIOSUBSECTIONREADER_JUCEHEADER__
|
||||
535
src/audio/audio_file_formats/juce_AudioThumbnail.cpp
Normal file
535
src/audio/audio_file_formats/juce_AudioThumbnail.cpp
Normal file
|
|
@ -0,0 +1,535 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_AudioThumbnail.h"
|
||||
#include "juce_AudioThumbnailCache.h"
|
||||
|
||||
const int timeBeforeDeletingReader = 2000;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct AudioThumbnailDataFormat
|
||||
{
|
||||
char thumbnailMagic[4];
|
||||
int samplesPerThumbSample;
|
||||
int64 totalSamples; // source samples
|
||||
int64 numFinishedSamples; // source samples
|
||||
int numThumbnailSamples;
|
||||
int numChannels;
|
||||
int sampleRate;
|
||||
char future[16];
|
||||
char data[1];
|
||||
};
|
||||
|
||||
#if JUCE_BIG_ENDIAN
|
||||
static void swap (int& n) { n = (int) swapByteOrder ((uint32) n); }
|
||||
static void swap (int64& n) { n = (int64) swapByteOrder ((uint64) n); }
|
||||
#endif
|
||||
|
||||
static void swapEndiannessIfNeeded (AudioThumbnailDataFormat* const d)
|
||||
{
|
||||
(void) d;
|
||||
|
||||
#if JUCE_BIG_ENDIAN
|
||||
swap (d->samplesPerThumbSample);
|
||||
swap (d->totalSamples);
|
||||
swap (d->numFinishedSamples);
|
||||
swap (d->numThumbnailSamples);
|
||||
swap (d->numChannels);
|
||||
swap (d->sampleRate);
|
||||
#endif
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
AudioThumbnail::AudioThumbnail (const int orginalSamplesPerThumbnailSample_,
|
||||
AudioFormatManager& formatManagerToUse_,
|
||||
AudioThumbnailCache& cacheToUse)
|
||||
: formatManagerToUse (formatManagerToUse_),
|
||||
cache (cacheToUse),
|
||||
source (0),
|
||||
reader (0),
|
||||
orginalSamplesPerThumbnailSample (orginalSamplesPerThumbnailSample_)
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
AudioThumbnail::~AudioThumbnail()
|
||||
{
|
||||
cache.removeThumbnail (this);
|
||||
|
||||
const ScopedLock sl (readerLock);
|
||||
deleteAndZero (reader);
|
||||
|
||||
delete source;
|
||||
}
|
||||
|
||||
void AudioThumbnail::setSource (InputSource* const newSource)
|
||||
{
|
||||
cache.removeThumbnail (this);
|
||||
timerCallback(); // stops the timer and deletes the reader
|
||||
|
||||
delete source;
|
||||
source = newSource;
|
||||
|
||||
clear();
|
||||
|
||||
if (newSource != 0
|
||||
&& ! (cache.loadThumb (*this, newSource->hashCode())
|
||||
&& isFullyLoaded()))
|
||||
{
|
||||
{
|
||||
const ScopedLock sl (readerLock);
|
||||
reader = createReader();
|
||||
}
|
||||
|
||||
if (reader != 0)
|
||||
{
|
||||
initialiseFromAudioFile (*reader);
|
||||
cache.addThumbnail (this);
|
||||
}
|
||||
}
|
||||
|
||||
sendChangeMessage (this);
|
||||
}
|
||||
|
||||
bool AudioThumbnail::useTimeSlice()
|
||||
{
|
||||
const ScopedLock sl (readerLock);
|
||||
|
||||
if (isFullyLoaded())
|
||||
{
|
||||
if (reader != 0)
|
||||
startTimer (timeBeforeDeletingReader);
|
||||
|
||||
cache.removeThumbnail (this);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (reader == 0)
|
||||
reader = createReader();
|
||||
|
||||
if (reader != 0)
|
||||
{
|
||||
readNextBlockFromAudioFile (*reader);
|
||||
stopTimer();
|
||||
|
||||
sendChangeMessage (this);
|
||||
|
||||
const bool justFinished = isFullyLoaded();
|
||||
|
||||
if (justFinished)
|
||||
cache.storeThumb (*this, source->hashCode());
|
||||
|
||||
return ! justFinished;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
AudioFormatReader* AudioThumbnail::createReader() const
|
||||
{
|
||||
if (source != 0)
|
||||
{
|
||||
InputStream* const audioFileStream = source->createInputStream();
|
||||
|
||||
if (audioFileStream != 0)
|
||||
return formatManagerToUse.createReaderFor (audioFileStream);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void AudioThumbnail::timerCallback()
|
||||
{
|
||||
stopTimer();
|
||||
|
||||
const ScopedLock sl (readerLock);
|
||||
deleteAndZero (reader);
|
||||
}
|
||||
|
||||
void AudioThumbnail::clear()
|
||||
{
|
||||
data.setSize (sizeof (AudioThumbnailDataFormat) + 3);
|
||||
|
||||
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
|
||||
|
||||
d->thumbnailMagic[0] = 'j';
|
||||
d->thumbnailMagic[1] = 'a';
|
||||
d->thumbnailMagic[2] = 't';
|
||||
d->thumbnailMagic[3] = 'm';
|
||||
|
||||
d->samplesPerThumbSample = orginalSamplesPerThumbnailSample;
|
||||
d->totalSamples = 0;
|
||||
d->numFinishedSamples = 0;
|
||||
d->numThumbnailSamples = 0;
|
||||
d->numChannels = 0;
|
||||
d->sampleRate = 0;
|
||||
|
||||
numSamplesCached = 0;
|
||||
cacheNeedsRefilling = true;
|
||||
}
|
||||
|
||||
void AudioThumbnail::loadFrom (InputStream& input)
|
||||
{
|
||||
data.setSize (0);
|
||||
input.readIntoMemoryBlock (data);
|
||||
|
||||
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
|
||||
swapEndiannessIfNeeded (d);
|
||||
|
||||
if (! (d->thumbnailMagic[0] == 'j'
|
||||
&& d->thumbnailMagic[1] == 'a'
|
||||
&& d->thumbnailMagic[2] == 't'
|
||||
&& d->thumbnailMagic[3] == 'm'))
|
||||
{
|
||||
clear();
|
||||
}
|
||||
|
||||
numSamplesCached = 0;
|
||||
cacheNeedsRefilling = true;
|
||||
}
|
||||
|
||||
void AudioThumbnail::saveTo (OutputStream& output) const
|
||||
{
|
||||
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
|
||||
swapEndiannessIfNeeded (d);
|
||||
output.write (data.getData(), data.getSize());
|
||||
swapEndiannessIfNeeded (d);
|
||||
}
|
||||
|
||||
bool AudioThumbnail::initialiseFromAudioFile (AudioFormatReader& reader)
|
||||
{
|
||||
AudioThumbnailDataFormat* d = (AudioThumbnailDataFormat*) data.getData();
|
||||
|
||||
d->totalSamples = reader.lengthInSamples;
|
||||
d->numChannels = jmin (2, reader.numChannels);
|
||||
d->numFinishedSamples = 0;
|
||||
d->sampleRate = roundDoubleToInt (reader.sampleRate);
|
||||
d->numThumbnailSamples = (int) (d->totalSamples / d->samplesPerThumbSample) + 1;
|
||||
|
||||
data.setSize (sizeof (AudioThumbnailDataFormat) + 3 + d->numThumbnailSamples * d->numChannels * 2);
|
||||
|
||||
d = (AudioThumbnailDataFormat*) data.getData();
|
||||
zeromem (&(d->data[0]), d->numThumbnailSamples * d->numChannels * 2);
|
||||
|
||||
return d->totalSamples > 0;
|
||||
}
|
||||
|
||||
bool AudioThumbnail::readNextBlockFromAudioFile (AudioFormatReader& reader)
|
||||
{
|
||||
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
|
||||
|
||||
if (d->numFinishedSamples < d->totalSamples)
|
||||
{
|
||||
const int numToDo = (int) jmin ((int64) 65536, d->totalSamples - d->numFinishedSamples);
|
||||
|
||||
generateSection (reader,
|
||||
d->numFinishedSamples,
|
||||
numToDo);
|
||||
|
||||
d->numFinishedSamples += numToDo;
|
||||
}
|
||||
|
||||
cacheNeedsRefilling = true;
|
||||
return (d->numFinishedSamples < d->totalSamples);
|
||||
}
|
||||
|
||||
int AudioThumbnail::getNumChannels() const throw()
|
||||
{
|
||||
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
|
||||
jassert (d != 0);
|
||||
|
||||
return d->numChannels;
|
||||
}
|
||||
|
||||
double AudioThumbnail::getTotalLength() const throw()
|
||||
{
|
||||
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
|
||||
jassert (d != 0);
|
||||
|
||||
if (d->sampleRate > 0)
|
||||
return d->totalSamples / (double)d->sampleRate;
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
void AudioThumbnail::generateSection (AudioFormatReader& reader,
|
||||
int64 startSample,
|
||||
int numSamples)
|
||||
{
|
||||
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
|
||||
jassert (d != 0);
|
||||
|
||||
int firstDataPos = (int) (startSample / d->samplesPerThumbSample);
|
||||
int lastDataPos = (int) ((startSample + numSamples) / d->samplesPerThumbSample);
|
||||
|
||||
char* l = getChannelData (0);
|
||||
char* r = getChannelData (1);
|
||||
|
||||
for (int i = firstDataPos; i < lastDataPos; ++i)
|
||||
{
|
||||
const int sourceStart = i * d->samplesPerThumbSample;
|
||||
const int sourceEnd = sourceStart + d->samplesPerThumbSample;
|
||||
|
||||
float lowestLeft, highestLeft, lowestRight, highestRight;
|
||||
|
||||
reader.readMaxLevels (sourceStart,
|
||||
sourceEnd - sourceStart,
|
||||
lowestLeft,
|
||||
highestLeft,
|
||||
lowestRight,
|
||||
highestRight);
|
||||
|
||||
int n = i * 2;
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
l [n] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f);
|
||||
r [n++] = (char) jlimit (-128.0f, 127.0f, lowestRight * 127.0f);
|
||||
l [n] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f);
|
||||
r [n++] = (char) jlimit (-128.0f, 127.0f, highestRight * 127.0f);
|
||||
}
|
||||
else
|
||||
{
|
||||
l [n++] = (char) jlimit (-128.0f, 127.0f, lowestLeft * 127.0f);
|
||||
l [n++] = (char) jlimit (-128.0f, 127.0f, highestLeft * 127.0f);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char* AudioThumbnail::getChannelData (int channel) const
|
||||
{
|
||||
AudioThumbnailDataFormat* const d = (AudioThumbnailDataFormat*) data.getData();
|
||||
jassert (d != 0);
|
||||
|
||||
if (channel >= 0 && channel < d->numChannels)
|
||||
return d->data + (channel * 2 * d->numThumbnailSamples);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool AudioThumbnail::isFullyLoaded() const throw()
|
||||
{
|
||||
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
|
||||
jassert (d != 0);
|
||||
|
||||
return d->numFinishedSamples >= d->totalSamples;
|
||||
}
|
||||
|
||||
void AudioThumbnail::refillCache (const int numSamples,
|
||||
double startTime,
|
||||
const double timePerPixel)
|
||||
{
|
||||
const AudioThumbnailDataFormat* const d = (const AudioThumbnailDataFormat*) data.getData();
|
||||
jassert (d != 0);
|
||||
|
||||
if (numSamples <= 0
|
||||
|| timePerPixel <= 0.0
|
||||
|| d->sampleRate <= 0)
|
||||
{
|
||||
numSamplesCached = 0;
|
||||
cacheNeedsRefilling = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (numSamples == numSamplesCached
|
||||
&& numChannelsCached == d->numChannels
|
||||
&& startTime == cachedStart
|
||||
&& timePerPixel == cachedTimePerPixel
|
||||
&& ! cacheNeedsRefilling)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
numSamplesCached = numSamples;
|
||||
numChannelsCached = d->numChannels;
|
||||
cachedStart = startTime;
|
||||
cachedTimePerPixel = timePerPixel;
|
||||
|
||||
cachedLevels.ensureSize (2 * numChannelsCached * numSamples);
|
||||
|
||||
const bool needExtraDetail = (timePerPixel * d->sampleRate <= d->samplesPerThumbSample);
|
||||
|
||||
const ScopedLock sl (readerLock);
|
||||
|
||||
cacheNeedsRefilling = false;
|
||||
|
||||
if (needExtraDetail && reader == 0)
|
||||
reader = createReader();
|
||||
|
||||
if (reader != 0 && timePerPixel * d->sampleRate <= d->samplesPerThumbSample)
|
||||
{
|
||||
startTimer (timeBeforeDeletingReader);
|
||||
|
||||
char* cacheData = (char*) cachedLevels.getData();
|
||||
int sample = roundDoubleToInt (startTime * d->sampleRate);
|
||||
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
const int nextSample = roundDoubleToInt ((startTime + timePerPixel) * d->sampleRate);
|
||||
|
||||
if (sample >= 0)
|
||||
{
|
||||
if (sample >= reader->lengthInSamples)
|
||||
break;
|
||||
|
||||
float lmin, lmax, rmin, rmax;
|
||||
|
||||
reader->readMaxLevels (sample,
|
||||
jmax (1, nextSample - sample),
|
||||
lmin, lmax, rmin, rmax);
|
||||
|
||||
cacheData[0] = (char) jlimit (-128, 127, roundFloatToInt (lmin * 127.0f));
|
||||
cacheData[1] = (char) jlimit (-128, 127, roundFloatToInt (lmax * 127.0f));
|
||||
|
||||
if (numChannelsCached > 1)
|
||||
{
|
||||
cacheData[2] = (char) jlimit (-128, 127, roundFloatToInt (rmin * 127.0f));
|
||||
cacheData[3] = (char) jlimit (-128, 127, roundFloatToInt (rmax * 127.0f));
|
||||
}
|
||||
|
||||
cacheData += 2 * numChannelsCached;
|
||||
}
|
||||
|
||||
startTime += timePerPixel;
|
||||
sample = nextSample;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int channelNum = 0; channelNum < numChannelsCached; ++channelNum)
|
||||
{
|
||||
char* const data = getChannelData (channelNum);
|
||||
char* cacheData = ((char*) cachedLevels.getData()) + channelNum * 2;
|
||||
|
||||
const double timeToThumbSampleFactor = d->sampleRate / (double) d->samplesPerThumbSample;
|
||||
|
||||
startTime = cachedStart;
|
||||
int sample = roundDoubleToInt (startTime * timeToThumbSampleFactor);
|
||||
const int numFinished = (int) (d->numFinishedSamples / d->samplesPerThumbSample);
|
||||
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
const int nextSample = roundDoubleToInt ((startTime + timePerPixel) * timeToThumbSampleFactor);
|
||||
|
||||
if (sample >= 0 && data != 0)
|
||||
{
|
||||
char mx = -128;
|
||||
char mn = 127;
|
||||
|
||||
while (sample <= nextSample)
|
||||
{
|
||||
if (sample >= numFinished)
|
||||
break;
|
||||
|
||||
const int n = sample << 1;
|
||||
const char sampMin = data [n];
|
||||
const char sampMax = data [n + 1];
|
||||
|
||||
if (sampMin < mn)
|
||||
mn = sampMin;
|
||||
|
||||
if (sampMax > mx)
|
||||
mx = sampMax;
|
||||
|
||||
++sample;
|
||||
}
|
||||
|
||||
if (mn <= mx)
|
||||
{
|
||||
cacheData[0] = mn;
|
||||
cacheData[1] = mx;
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheData[0] = 1;
|
||||
cacheData[1] = 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cacheData[0] = 1;
|
||||
cacheData[1] = 0;
|
||||
}
|
||||
|
||||
cacheData += numChannelsCached * 2;
|
||||
startTime += timePerPixel;
|
||||
sample = nextSample;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AudioThumbnail::drawChannel (Graphics& g,
|
||||
int x, int y, int w, int h,
|
||||
double startTime,
|
||||
double endTime,
|
||||
int channelNum,
|
||||
const float verticalZoomFactor)
|
||||
{
|
||||
refillCache (w, startTime, (endTime - startTime) / w);
|
||||
|
||||
if (numSamplesCached >= w
|
||||
&& channelNum >= 0
|
||||
&& channelNum < numChannelsCached)
|
||||
{
|
||||
const float topY = (float) y;
|
||||
const float bottomY = topY + h;
|
||||
const float midY = topY + h * 0.5f;
|
||||
const float vscale = verticalZoomFactor * h / 256.0f;
|
||||
|
||||
const Rectangle clip (g.getClipBounds());
|
||||
const int skipLeft = jlimit (0, w, clip.getX() - x);
|
||||
w -= skipLeft;
|
||||
x += skipLeft;
|
||||
|
||||
const char* cacheData = ((const char*) cachedLevels.getData())
|
||||
+ (channelNum << 1)
|
||||
+ skipLeft * (numChannelsCached << 1);
|
||||
|
||||
while (--w >= 0)
|
||||
{
|
||||
const char mn = cacheData[0];
|
||||
const char mx = cacheData[1];
|
||||
cacheData += numChannelsCached << 1;
|
||||
|
||||
if (mn <= mx) // if the wrong way round, signifies that the sample's not yet known
|
||||
g.drawLine ((float) x, jmax (midY - mx * vscale - 0.3f, topY),
|
||||
(float) x, jmin (midY - mn * vscale + 0.3f, bottomY));
|
||||
|
||||
++x;
|
||||
|
||||
if (x >= clip.getRight())
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
189
src/audio/audio_file_formats/juce_AudioThumbnail.h
Normal file
189
src/audio/audio_file_formats/juce_AudioThumbnail.h
Normal file
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__
|
||||
#define __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__
|
||||
|
||||
#include "../../threads/juce_TimeSliceThread.h"
|
||||
#include "../../io/streams/juce_InputSource.h"
|
||||
#include "../../io/streams/juce_OutputStream.h"
|
||||
#include "../../events/juce_ChangeBroadcaster.h"
|
||||
#include "../../events/juce_Timer.h"
|
||||
#include "../../gui/graphics/contexts/juce_Graphics.h"
|
||||
#include "juce_AudioFormatReader.h"
|
||||
#include "juce_AudioFormatManager.h"
|
||||
|
||||
class AudioThumbnailCache;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
Makes it easy to quickly draw scaled views of the waveform shape of an
|
||||
audio file.
|
||||
|
||||
To use this class, just create an AudioThumbNail class for the file you want
|
||||
to draw, call setSource to tell it which file or resource to use, then call
|
||||
drawChannel() to draw it.
|
||||
|
||||
The class will asynchronously scan the wavefile to create its scaled-down view,
|
||||
so you should make your UI repaint itself as this data comes in. To do this, the
|
||||
AudioThumbnail is a ChangeBroadcaster, and will broadcast a message when its
|
||||
listeners should repaint themselves.
|
||||
|
||||
The thumbnail stores an internal low-res version of the wave data, and this can
|
||||
be loaded and saved to avoid having to scan the file again.
|
||||
|
||||
@see AudioThumbnailCache
|
||||
*/
|
||||
class JUCE_API AudioThumbnail : public ChangeBroadcaster,
|
||||
public TimeSliceClient,
|
||||
private Timer
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates an audio thumbnail.
|
||||
|
||||
@param sourceSamplesPerThumbnailSample when creating a stored, low-res version
|
||||
of the audio data, this is the scale at which it should be done
|
||||
@param formatManagerToUse the audio format manager that is used to open the file
|
||||
@param cacheToUse an instance of an AudioThumbnailCache - this provides a background
|
||||
thread and storage that is used to by the thumbnail, and the cache
|
||||
object can be shared between multiple thumbnails
|
||||
*/
|
||||
AudioThumbnail (const int sourceSamplesPerThumbnailSample,
|
||||
AudioFormatManager& formatManagerToUse,
|
||||
AudioThumbnailCache& cacheToUse);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioThumbnail();
|
||||
|
||||
//==============================================================================
|
||||
/** Specifies the file or stream that contains the audio file.
|
||||
|
||||
For a file, just call
|
||||
@code
|
||||
setSource (new FileInputSource (file))
|
||||
@endcode
|
||||
|
||||
You can pass a zero in here to clear the thumbnail.
|
||||
|
||||
The source that is passed in will be deleted by this object when it is no
|
||||
longer needed
|
||||
*/
|
||||
void setSource (InputSource* const newSource);
|
||||
|
||||
/** Reloads the low res thumbnail data from an input stream.
|
||||
|
||||
The thumb will automatically attempt to reload itself from its
|
||||
AudioThumbnailCache.
|
||||
*/
|
||||
void loadFrom (InputStream& input);
|
||||
|
||||
/** Saves the low res thumbnail data to an output stream.
|
||||
|
||||
The thumb will automatically attempt to save itself to its
|
||||
AudioThumbnailCache after it finishes scanning the wave file.
|
||||
*/
|
||||
void saveTo (OutputStream& output) const;
|
||||
|
||||
//==============================================================================
|
||||
/** Returns the number of channels in the file.
|
||||
*/
|
||||
int getNumChannels() const throw();
|
||||
|
||||
/** Returns the length of the audio file.
|
||||
*/
|
||||
double getTotalLength() const throw();
|
||||
|
||||
/** Renders the waveform shape for a channel.
|
||||
|
||||
The waveform will be drawn within the specified rectangle, where startTime
|
||||
and endTime specify the times within the audio file that should be positioned
|
||||
at the left and right edges of the rectangle.
|
||||
|
||||
The waveform will be scaled vertically so that a full-volume sample will fill
|
||||
the rectangle vertically, but you can also specify an extra vertical scale factor
|
||||
with the verticalZoomFactor parameter.
|
||||
*/
|
||||
void drawChannel (Graphics& g,
|
||||
int x, int y, int w, int h,
|
||||
double startTime,
|
||||
double endTime,
|
||||
int channelNum,
|
||||
const float verticalZoomFactor);
|
||||
|
||||
/** Returns true if the low res preview is fully generated.
|
||||
*/
|
||||
bool isFullyLoaded() const throw();
|
||||
|
||||
//==============================================================================
|
||||
/** @internal */
|
||||
bool useTimeSlice();
|
||||
/** @internal */
|
||||
void timerCallback();
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
AudioFormatManager& formatManagerToUse;
|
||||
AudioThumbnailCache& cache;
|
||||
InputSource* source;
|
||||
|
||||
CriticalSection readerLock;
|
||||
AudioFormatReader* reader;
|
||||
|
||||
MemoryBlock data, cachedLevels;
|
||||
int orginalSamplesPerThumbnailSample;
|
||||
|
||||
int numChannelsCached, numSamplesCached;
|
||||
double cachedStart, cachedTimePerPixel;
|
||||
bool cacheNeedsRefilling;
|
||||
|
||||
void clear();
|
||||
|
||||
AudioFormatReader* createReader() const;
|
||||
|
||||
void generateSection (AudioFormatReader& reader,
|
||||
int64 startSample,
|
||||
int numSamples);
|
||||
|
||||
char* getChannelData (int channel) const;
|
||||
|
||||
void refillCache (const int numSamples,
|
||||
double startTime,
|
||||
const double timePerPixel);
|
||||
|
||||
friend class AudioThumbnailCache;
|
||||
|
||||
// true if it needs more callbacks from the readNextBlockFromAudioFile() method
|
||||
bool initialiseFromAudioFile (AudioFormatReader& reader);
|
||||
|
||||
// returns true if more needs to be read
|
||||
bool readNextBlockFromAudioFile (AudioFormatReader& reader);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOTHUMBNAIL_JUCEHEADER__
|
||||
139
src/audio/audio_file_formats/juce_AudioThumbnailCache.cpp
Normal file
139
src/audio/audio_file_formats/juce_AudioThumbnailCache.cpp
Normal file
|
|
@ -0,0 +1,139 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_AudioThumbnailCache.h"
|
||||
#include "../../io/streams/juce_MemoryInputStream.h"
|
||||
#include "../../io/streams/juce_MemoryOutputStream.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct ThumbnailCacheEntry
|
||||
{
|
||||
int64 hash;
|
||||
uint32 lastUsed;
|
||||
MemoryBlock data;
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbsToStore_)
|
||||
: TimeSliceThread (T("thumb cache")),
|
||||
maxNumThumbsToStore (maxNumThumbsToStore_)
|
||||
{
|
||||
startThread (2);
|
||||
}
|
||||
|
||||
AudioThumbnailCache::~AudioThumbnailCache()
|
||||
{
|
||||
}
|
||||
|
||||
bool AudioThumbnailCache::loadThumb (AudioThumbnail& thumb, const int64 hashCode)
|
||||
{
|
||||
for (int i = thumbs.size(); --i >= 0;)
|
||||
{
|
||||
if (thumbs[i]->hash == hashCode)
|
||||
{
|
||||
MemoryInputStream in ((const char*) thumbs[i]->data.getData(),
|
||||
thumbs[i]->data.getSize(),
|
||||
false);
|
||||
|
||||
thumb.loadFrom (in);
|
||||
|
||||
thumbs[i]->lastUsed = Time::getMillisecondCounter();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AudioThumbnailCache::storeThumb (const AudioThumbnail& thumb,
|
||||
const int64 hashCode)
|
||||
{
|
||||
MemoryOutputStream out;
|
||||
thumb.saveTo (out);
|
||||
|
||||
ThumbnailCacheEntry* te = 0;
|
||||
|
||||
for (int i = thumbs.size(); --i >= 0;)
|
||||
{
|
||||
if (thumbs[i]->hash == hashCode)
|
||||
{
|
||||
te = thumbs[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (te == 0)
|
||||
{
|
||||
te = new ThumbnailCacheEntry();
|
||||
te->hash = hashCode;
|
||||
|
||||
if (thumbs.size() < maxNumThumbsToStore)
|
||||
{
|
||||
thumbs.add (te);
|
||||
}
|
||||
else
|
||||
{
|
||||
int oldest = 0;
|
||||
unsigned int oldestTime = Time::getMillisecondCounter() + 1;
|
||||
|
||||
int i;
|
||||
for (i = thumbs.size(); --i >= 0;)
|
||||
if (thumbs[i]->lastUsed < oldestTime)
|
||||
oldest = i;
|
||||
|
||||
thumbs.set (i, te);
|
||||
}
|
||||
}
|
||||
|
||||
te->lastUsed = Time::getMillisecondCounter();
|
||||
te->data.setSize (0);
|
||||
te->data.append (out.getData(), out.getDataSize());
|
||||
}
|
||||
|
||||
void AudioThumbnailCache::clear()
|
||||
{
|
||||
thumbs.clear();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
void AudioThumbnailCache::addThumbnail (AudioThumbnail* const thumb)
|
||||
{
|
||||
addTimeSliceClient (thumb);
|
||||
}
|
||||
|
||||
void AudioThumbnailCache::removeThumbnail (AudioThumbnail* const thumb)
|
||||
{
|
||||
removeTimeSliceClient (thumb);
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
92
src/audio/audio_file_formats/juce_AudioThumbnailCache.h
Normal file
92
src/audio/audio_file_formats/juce_AudioThumbnailCache.h
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
|
||||
#define __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioThumbnail.h"
|
||||
struct ThumbnailCacheEntry;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
An instance of this class is used to manage multiple AudioThumbnail objects.
|
||||
|
||||
The cache runs a single background thread that is shared by all the thumbnails
|
||||
that need it, and it maintains a set of low-res previews in memory, to avoid
|
||||
having to re-scan audio files too often.
|
||||
|
||||
@see AudioThumbnail
|
||||
*/
|
||||
class JUCE_API AudioThumbnailCache : public TimeSliceThread
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
/** Creates a cache object.
|
||||
|
||||
The maxNumThumbsToStore parameter lets you specify how many previews should
|
||||
be kept in memory at once.
|
||||
*/
|
||||
AudioThumbnailCache (const int maxNumThumbsToStore);
|
||||
|
||||
/** Destructor. */
|
||||
~AudioThumbnailCache();
|
||||
|
||||
//==============================================================================
|
||||
/** Clears out any stored thumbnails.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/** Reloads the specified thumb if this cache contains the appropriate stored
|
||||
data.
|
||||
|
||||
This is called automatically by the AudioThumbnail class, so you shouldn't
|
||||
normally need to call it directly.
|
||||
*/
|
||||
bool loadThumb (AudioThumbnail& thumb, const int64 hashCode);
|
||||
|
||||
/** Stores the cachable data from the specified thumb in this cache.
|
||||
|
||||
This is called automatically by the AudioThumbnail class, so you shouldn't
|
||||
normally need to call it directly.
|
||||
*/
|
||||
void storeThumb (const AudioThumbnail& thumb, const int64 hashCode);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
private:
|
||||
//==============================================================================
|
||||
OwnedArray <ThumbnailCacheEntry> thumbs;
|
||||
int maxNumThumbsToStore;
|
||||
|
||||
friend class AudioThumbnail;
|
||||
void addThumbnail (AudioThumbnail* const thumb);
|
||||
void removeThumbnail (AudioThumbnail* const thumb);
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_AUDIOTHUMBNAILCACHE_JUCEHEADER__
|
||||
554
src/audio/audio_file_formats/juce_FlacAudioFormat.cpp
Normal file
554
src/audio/audio_file_formats/juce_FlacAudioFormat.cpp
Normal file
|
|
@ -0,0 +1,554 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../juce_Config.h"
|
||||
#ifdef _MSC_VER
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#if JUCE_USE_FLAC
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable : 4505)
|
||||
#pragma warning (push)
|
||||
#endif
|
||||
|
||||
namespace FlacNamespace
|
||||
{
|
||||
#if JUCE_INCLUDE_FLAC_CODE
|
||||
#define FLAC__NO_DLL 1
|
||||
|
||||
#if ! defined (SIZE_MAX)
|
||||
#define SIZE_MAX 0xffffffff
|
||||
#endif
|
||||
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#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"
|
||||
#else
|
||||
#include <FLAC/all.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_FlacAudioFormat.h"
|
||||
#include "../../text/juce_LocalisedStrings.h"
|
||||
|
||||
using namespace FlacNamespace;
|
||||
|
||||
//==============================================================================
|
||||
#define flacFormatName TRANS("FLAC file")
|
||||
static const tchar* const flacExtensions[] = { T(".flac"), 0 };
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class FlacReader : public AudioFormatReader
|
||||
{
|
||||
FLAC__StreamDecoder* decoder;
|
||||
AudioSampleBuffer reservoir;
|
||||
int reservoirStart, samplesInReservoir;
|
||||
bool ok, scanningForLength;
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
FlacReader (InputStream* const in)
|
||||
: AudioFormatReader (in, flacFormatName),
|
||||
reservoir (2, 0),
|
||||
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_,
|
||||
(void*) 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()
|
||||
{
|
||||
FLAC__stream_decoder_delete (decoder);
|
||||
}
|
||||
|
||||
void useMetadata (const FLAC__StreamMetadata_StreamInfo& info)
|
||||
{
|
||||
sampleRate = info.sample_rate;
|
||||
bitsPerSample = info.bits_per_sample;
|
||||
lengthInSamples = (unsigned int) info.total_samples;
|
||||
numChannels = info.channels;
|
||||
|
||||
reservoir.setSize (numChannels, 2 * info.max_blocksize, false, false, true);
|
||||
}
|
||||
|
||||
// returns the number of samples read
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
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] != 0)
|
||||
memcpy (destSamples[i] + startOffsetInDestBuffer,
|
||||
reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)),
|
||||
sizeof (int) * num);
|
||||
|
||||
startOffsetInDestBuffer += num;
|
||||
startSampleInFile += num;
|
||||
numSamples -= num;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (startSampleInFile < reservoirStart
|
||||
|| startSampleInFile > reservoirStart + jmax (samplesInReservoir, 511))
|
||||
{
|
||||
if (startSampleInFile >= (int) lengthInSamples)
|
||||
{
|
||||
samplesInReservoir = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
// 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);
|
||||
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] != 0)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer,
|
||||
sizeof (int) * numSamples);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void useSamples (const FLAC__int32* const buffer[], int numSamples)
|
||||
{
|
||||
if (scanningForLength)
|
||||
{
|
||||
lengthInSamples += numSamples;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (numSamples > reservoir.getNumSamples())
|
||||
reservoir.setSize (numChannels, numSamples, false, false, true);
|
||||
|
||||
const int bitsToShift = 32 - bitsPerSample;
|
||||
|
||||
for (int i = 0; i < (int) numChannels; ++i)
|
||||
{
|
||||
const FLAC__int32* src = buffer[i];
|
||||
|
||||
int n = i;
|
||||
while (src == 0 && n > 0)
|
||||
src = buffer [--n];
|
||||
|
||||
if (src != 0)
|
||||
{
|
||||
int* dest = (int*) reservoir.getSampleData(i);
|
||||
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
dest[j] = src[j] << bitsToShift;
|
||||
}
|
||||
}
|
||||
|
||||
samplesInReservoir = numSamples;
|
||||
}
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static FLAC__StreamDecoderReadStatus readCallback_ (const FLAC__StreamDecoder*, FLAC__byte buffer[], size_t* bytes, void* client_data)
|
||||
{
|
||||
*bytes = (unsigned int) ((const FlacReader*) client_data)->input->read (buffer, (int) *bytes);
|
||||
return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderSeekStatus seekCallback_ (const FLAC__StreamDecoder*, FLAC__uint64 absolute_byte_offset, void* client_data)
|
||||
{
|
||||
((const FlacReader*) client_data)->input->setPosition ((int) absolute_byte_offset);
|
||||
return FLAC__STREAM_DECODER_SEEK_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderTellStatus tellCallback_ (const FLAC__StreamDecoder*, FLAC__uint64* absolute_byte_offset, void* client_data)
|
||||
{
|
||||
*absolute_byte_offset = ((const FlacReader*) client_data)->input->getPosition();
|
||||
return FLAC__STREAM_DECODER_TELL_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderLengthStatus lengthCallback_ (const FLAC__StreamDecoder*, FLAC__uint64* stream_length, void* client_data)
|
||||
{
|
||||
*stream_length = ((const FlacReader*) client_data)->input->getTotalLength();
|
||||
return FLAC__STREAM_DECODER_LENGTH_STATUS_OK;
|
||||
}
|
||||
|
||||
static FLAC__bool eofCallback_ (const FLAC__StreamDecoder*, void* client_data)
|
||||
{
|
||||
return ((const FlacReader*) client_data)->input->isExhausted();
|
||||
}
|
||||
|
||||
static FLAC__StreamDecoderWriteStatus writeCallback_ (const FLAC__StreamDecoder*,
|
||||
const FLAC__Frame* frame,
|
||||
const FLAC__int32* const buffer[],
|
||||
void* client_data)
|
||||
{
|
||||
((FlacReader*) client_data)->useSamples (buffer, frame->header.blocksize);
|
||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||
}
|
||||
|
||||
static void metadataCallback_ (const FLAC__StreamDecoder*,
|
||||
const FLAC__StreamMetadata* metadata,
|
||||
void* client_data)
|
||||
{
|
||||
((FlacReader*) client_data)->useMetadata (metadata->data.stream_info);
|
||||
}
|
||||
|
||||
static void errorCallback_ (const FLAC__StreamDecoder*, FLAC__StreamDecoderErrorStatus, void*)
|
||||
{
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class FlacWriter : public AudioFormatWriter
|
||||
{
|
||||
FLAC__StreamEncoder* encoder;
|
||||
MemoryBlock temp;
|
||||
|
||||
public:
|
||||
bool ok;
|
||||
|
||||
//==============================================================================
|
||||
FlacWriter (OutputStream* const out,
|
||||
const double sampleRate,
|
||||
const int numChannels,
|
||||
const int bitsPerSample_)
|
||||
: AudioFormatWriter (out, flacFormatName,
|
||||
sampleRate,
|
||||
numChannels,
|
||||
bitsPerSample_)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
encoder = FLAC__stream_encoder_new();
|
||||
|
||||
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 (24, bitsPerSample));
|
||||
FLAC__stream_encoder_set_sample_rate (encoder, (unsigned int) sampleRate);
|
||||
FLAC__stream_encoder_set_blocksize (encoder, 2048);
|
||||
FLAC__stream_encoder_set_do_escape_coding (encoder, true);
|
||||
|
||||
ok = FLAC__stream_encoder_init_stream (encoder,
|
||||
encodeWriteCallback, encodeSeekCallback,
|
||||
encodeTellCallback, encodeMetadataCallback,
|
||||
(void*) this) == FLAC__STREAM_ENCODER_INIT_STATUS_OK;
|
||||
}
|
||||
|
||||
~FlacWriter()
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
FLAC__stream_encoder_finish (encoder);
|
||||
output->flush();
|
||||
}
|
||||
else
|
||||
{
|
||||
output = 0; // to stop the base class deleting this, as it needs to be returned
|
||||
// to the caller of createWriter()
|
||||
}
|
||||
|
||||
FLAC__stream_encoder_delete (encoder);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (const int** samplesToWrite, int numSamples)
|
||||
{
|
||||
if (! ok)
|
||||
return false;
|
||||
|
||||
int* buf[3];
|
||||
const int bitsToShift = 32 - bitsPerSample;
|
||||
|
||||
if (bitsToShift > 0)
|
||||
{
|
||||
const int numChannels = (samplesToWrite[1] == 0) ? 1 : 2;
|
||||
temp.setSize (sizeof (int) * numSamples * numChannels);
|
||||
|
||||
buf[0] = (int*) temp.getData();
|
||||
buf[1] = buf[0] + numSamples;
|
||||
buf[2] = 0;
|
||||
|
||||
for (int i = numChannels; --i >= 0;)
|
||||
{
|
||||
if (samplesToWrite[i] != 0)
|
||||
{
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
buf [i][j] = (samplesToWrite [i][j] >> bitsToShift);
|
||||
}
|
||||
}
|
||||
|
||||
samplesToWrite = (const int**) buf;
|
||||
}
|
||||
|
||||
return FLAC__stream_encoder_process (encoder,
|
||||
(const FLAC__int32**) samplesToWrite,
|
||||
numSamples) != 0;
|
||||
}
|
||||
|
||||
bool writeData (const void* const data, const int size) const
|
||||
{
|
||||
return output->write (data, size);
|
||||
}
|
||||
|
||||
static void packUint32 (FLAC__uint32 val, FLAC__byte* b, const int bytes)
|
||||
{
|
||||
b += bytes;
|
||||
|
||||
for (int i = 0; i < bytes; ++i)
|
||||
{
|
||||
*(--b) = (FLAC__byte) (val & 0xff);
|
||||
val >>= 8;
|
||||
}
|
||||
}
|
||||
|
||||
void writeMetaData (const 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 ok = output->setPosition (4);
|
||||
(void) ok;
|
||||
|
||||
// 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 (ok);
|
||||
|
||||
output->writeIntBigEndian (FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
|
||||
output->write (buffer, FLAC__STREAM_METADATA_STREAMINFO_LENGTH);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static FLAC__StreamEncoderWriteStatus encodeWriteCallback (const FLAC__StreamEncoder*,
|
||||
const FLAC__byte buffer[],
|
||||
size_t bytes,
|
||||
unsigned int /*samples*/,
|
||||
unsigned int /*current_frame*/,
|
||||
void* client_data)
|
||||
{
|
||||
using namespace FlacNamespace;
|
||||
return ((FlacWriter*) client_data)->writeData (buffer, (int) bytes)
|
||||
? FLAC__STREAM_ENCODER_WRITE_STATUS_OK
|
||||
: FLAC__STREAM_ENCODER_WRITE_STATUS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
static FLAC__StreamEncoderSeekStatus encodeSeekCallback (const FLAC__StreamEncoder*, FLAC__uint64, void*)
|
||||
{
|
||||
return FLAC__STREAM_ENCODER_SEEK_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static FLAC__StreamEncoderTellStatus encodeTellCallback (const FLAC__StreamEncoder*, FLAC__uint64*, void*)
|
||||
{
|
||||
return FLAC__STREAM_ENCODER_TELL_STATUS_UNSUPPORTED;
|
||||
}
|
||||
|
||||
static void encodeMetadataCallback (const FLAC__StreamEncoder*,
|
||||
const FLAC__StreamMetadata* metadata,
|
||||
void* client_data)
|
||||
{
|
||||
((FlacWriter*) client_data)->writeMetaData (metadata);
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
FlacAudioFormat::FlacAudioFormat()
|
||||
: AudioFormat (flacFormatName, (const tchar**) flacExtensions)
|
||||
{
|
||||
}
|
||||
|
||||
FlacAudioFormat::~FlacAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
const Array <int> FlacAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 0 };
|
||||
return Array <int> (rates);
|
||||
}
|
||||
|
||||
const Array <int> FlacAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 16, 24, 0 };
|
||||
return Array <int> (depths);
|
||||
}
|
||||
|
||||
bool FlacAudioFormat::canDoStereo()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlacAudioFormat::canDoMono()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlacAudioFormat::isCompressed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioFormatReader* FlacAudioFormat::createReaderFor (InputStream* in,
|
||||
const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
FlacReader* r = new FlacReader (in);
|
||||
|
||||
if (r->sampleRate == 0)
|
||||
{
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = 0;
|
||||
|
||||
deleteAndZero (r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
AudioFormatWriter* FlacAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
if (getPossibleBitDepths().contains (bitsPerSample))
|
||||
{
|
||||
FlacWriter* w = new FlacWriter (out,
|
||||
sampleRate,
|
||||
numberOfChannels,
|
||||
bitsPerSample);
|
||||
|
||||
if (! w->ok)
|
||||
deleteAndZero (w);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
#endif
|
||||
75
src/audio/audio_file_formats/juce_FlacAudioFormat.h
Normal file
75
src/audio/audio_file_formats/juce_FlacAudioFormat.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_FLACAUDIOFORMAT_JUCEHEADER__
|
||||
#define __JUCE_FLACAUDIOFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormat.h" // (must keep this outside the conditional define)
|
||||
|
||||
#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 in juce_Config.h,
|
||||
and make sure your include search path and library search path are set up to find
|
||||
the FLAC header files and static libraries.
|
||||
|
||||
@see AudioFormat
|
||||
*/
|
||||
class JUCE_API FlacAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
FlacAudioFormat();
|
||||
~FlacAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
const Array <int> getPossibleSampleRates();
|
||||
const Array <int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
bool isCompressed();
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // __JUCE_FLACAUDIOFORMAT_JUCEHEADER__
|
||||
504
src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp
Normal file
504
src/audio/audio_file_formats/juce_OggVorbisAudioFormat.cpp
Normal file
|
|
@ -0,0 +1,504 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../juce_Config.h"
|
||||
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
#if JUCE_MAC
|
||||
#define __MACOSX__ 1
|
||||
#endif
|
||||
|
||||
|
||||
namespace OggVorbisNamespace
|
||||
{
|
||||
#if JUCE_INCLUDE_OGGVORBIS_CODE
|
||||
#include "oggvorbis/vorbisenc.h"
|
||||
#include "oggvorbis/codec.h"
|
||||
#include "oggvorbis/vorbisfile.h"
|
||||
|
||||
#include "oggvorbis/bitwise.c"
|
||||
#include "oggvorbis/framing.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/analysis.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/bitrate.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/block.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/codebook.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/envelope.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/floor0.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/floor1.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/info.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/lpc.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/lsp.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/mapping0.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/mdct.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/psy.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/registry.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/res0.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/sharedbook.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/smallft.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/synthesis.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/vorbisenc.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/vorbisfile.c"
|
||||
#include "oggvorbis/libvorbis-1.1.2/lib/window.c"
|
||||
#else
|
||||
#include <vorbis/vorbisenc.h>
|
||||
#include <vorbis/codec.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
#endif
|
||||
}
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_OggVorbisAudioFormat.h"
|
||||
#include "../../application/juce_Application.h"
|
||||
#include "../../core/juce_Random.h"
|
||||
#include "../../io/files/juce_FileInputStream.h"
|
||||
#include "../../text/juce_LocalisedStrings.h"
|
||||
|
||||
using namespace OggVorbisNamespace;
|
||||
|
||||
//==============================================================================
|
||||
#define oggFormatName TRANS("Ogg-Vorbis file")
|
||||
static const tchar* const oggExtensions[] = { T(".ogg"), 0 };
|
||||
|
||||
|
||||
//==============================================================================
|
||||
class OggReader : public AudioFormatReader
|
||||
{
|
||||
OggVorbis_File ovFile;
|
||||
ov_callbacks callbacks;
|
||||
AudioSampleBuffer reservoir;
|
||||
int reservoirStart, samplesInReservoir;
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
OggReader (InputStream* const inp)
|
||||
: AudioFormatReader (inp, oggFormatName),
|
||||
reservoir (2, 4096),
|
||||
reservoirStart (0),
|
||||
samplesInReservoir (0)
|
||||
{
|
||||
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);
|
||||
lengthInSamples = (uint32) ov_pcm_total (&ovFile, -1);
|
||||
numChannels = info->channels;
|
||||
bitsPerSample = 16;
|
||||
sampleRate = info->rate;
|
||||
|
||||
reservoir.setSize (numChannels,
|
||||
(int) jmin (lengthInSamples, (int64) reservoir.getNumSamples()));
|
||||
}
|
||||
}
|
||||
|
||||
~OggReader()
|
||||
{
|
||||
ov_clear (&ovFile);
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
while (numSamples > 0)
|
||||
{
|
||||
const int numAvailable = 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] != 0)
|
||||
memcpy (destSamples[i] + startOffsetInDestBuffer,
|
||||
reservoir.getSampleData (i, (int) (startSampleInFile - reservoirStart)),
|
||||
sizeof (float) * 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) ov_pcm_tell (&ovFile))
|
||||
ov_pcm_seek (&ovFile, reservoirStart);
|
||||
|
||||
int offset = 0;
|
||||
int numToRead = samplesInReservoir;
|
||||
|
||||
while (numToRead > 0)
|
||||
{
|
||||
float** dataIn = 0;
|
||||
|
||||
const int samps = ov_read_float (&ovFile, &dataIn, numToRead, &bitStream);
|
||||
if (samps == 0)
|
||||
break;
|
||||
|
||||
jassert (samps <= numToRead);
|
||||
|
||||
for (int i = jmin (numChannels, reservoir.getNumChannels()); --i >= 0;)
|
||||
{
|
||||
memcpy (reservoir.getSampleData (i, offset),
|
||||
dataIn[i],
|
||||
sizeof (float) * samps);
|
||||
}
|
||||
|
||||
numToRead -= samps;
|
||||
offset += samps;
|
||||
}
|
||||
|
||||
if (numToRead > 0)
|
||||
reservoir.clear (offset, numToRead);
|
||||
}
|
||||
}
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != 0)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer,
|
||||
sizeof (int) * numSamples);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
static size_t oggReadCallback (void* ptr, size_t size, size_t nmemb, void* datasource)
|
||||
{
|
||||
return (size_t) (((InputStream*) datasource)->read (ptr, (int) (size * nmemb)) / size);
|
||||
}
|
||||
|
||||
static int oggSeekCallback (void* datasource, ogg_int64_t offset, int whence)
|
||||
{
|
||||
InputStream* const in = (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) ((InputStream*) datasource)->getPosition();
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class OggWriter : public AudioFormatWriter
|
||||
{
|
||||
ogg_stream_state os;
|
||||
ogg_page og;
|
||||
ogg_packet op;
|
||||
vorbis_info vi;
|
||||
vorbis_comment vc;
|
||||
vorbis_dsp_state vd;
|
||||
vorbis_block vb;
|
||||
|
||||
public:
|
||||
bool ok;
|
||||
|
||||
//==============================================================================
|
||||
OggWriter (OutputStream* const out,
|
||||
const double sampleRate,
|
||||
const int numChannels,
|
||||
const int bitsPerSample,
|
||||
const int qualityIndex)
|
||||
: AudioFormatWriter (out, oggFormatName,
|
||||
sampleRate,
|
||||
numChannels,
|
||||
bitsPerSample)
|
||||
{
|
||||
ok = false;
|
||||
|
||||
vorbis_info_init (&vi);
|
||||
|
||||
if (vorbis_encode_init_vbr (&vi,
|
||||
numChannels,
|
||||
(int) sampleRate,
|
||||
jlimit (0.0f, 1.0f, qualityIndex * 0.5f)) == 0)
|
||||
{
|
||||
vorbis_comment_init (&vc);
|
||||
|
||||
if (JUCEApplication::getInstance() != 0)
|
||||
vorbis_comment_add_tag (&vc, "ENCODER",
|
||||
(char*) (const char*) JUCEApplication::getInstance()->getApplicationName());
|
||||
|
||||
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, og.header_len);
|
||||
output->write (og.body, og.body_len);
|
||||
}
|
||||
|
||||
ok = true;
|
||||
}
|
||||
}
|
||||
|
||||
~OggWriter()
|
||||
{
|
||||
if (ok)
|
||||
{
|
||||
// write a zero-length packet to show ogg that we're finished..
|
||||
write (0, 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 = 0; // 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)
|
||||
{
|
||||
if (! ok)
|
||||
return false;
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
const double gain = 1.0 / 0x80000000u;
|
||||
float** const vorbisBuffer = vorbis_analysis_buffer (&vd, numSamples);
|
||||
|
||||
for (int i = numChannels; --i >= 0;)
|
||||
{
|
||||
float* const dst = vorbisBuffer[i];
|
||||
const int* const src = samplesToWrite [i];
|
||||
|
||||
if (src != 0 && dst != 0)
|
||||
{
|
||||
for (int j = 0; j < numSamples; ++j)
|
||||
dst[j] = (float) (src[j] * gain);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, og.header_len);
|
||||
output->write (og.body, og.body_len);
|
||||
|
||||
if (ogg_page_eos (&og))
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
OggVorbisAudioFormat::OggVorbisAudioFormat()
|
||||
: AudioFormat (oggFormatName, (const tchar**) oggExtensions)
|
||||
{
|
||||
}
|
||||
|
||||
OggVorbisAudioFormat::~OggVorbisAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
const Array <int> OggVorbisAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 22050, 32000, 44100, 48000, 0 };
|
||||
return Array <int> (rates);
|
||||
}
|
||||
|
||||
const Array <int> OggVorbisAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
Array <int> depths;
|
||||
depths.add (32);
|
||||
return depths;
|
||||
}
|
||||
|
||||
bool OggVorbisAudioFormat::canDoStereo()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool OggVorbisAudioFormat::canDoMono()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioFormatReader* OggVorbisAudioFormat::createReaderFor (InputStream* in,
|
||||
const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
OggReader* r = new OggReader (in);
|
||||
|
||||
if (r->sampleRate == 0)
|
||||
{
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = 0;
|
||||
|
||||
deleteAndZero (r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
AudioFormatWriter* OggVorbisAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int qualityOptionIndex)
|
||||
{
|
||||
OggWriter* w = new OggWriter (out,
|
||||
sampleRate,
|
||||
numChannels,
|
||||
bitsPerSample,
|
||||
qualityOptionIndex);
|
||||
|
||||
if (! w->ok)
|
||||
deleteAndZero (w);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
bool OggVorbisAudioFormat::isCompressed()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
const StringArray OggVorbisAudioFormat::getQualityOptions()
|
||||
{
|
||||
StringArray s;
|
||||
s.add ("Low Quality");
|
||||
s.add ("Medium Quality");
|
||||
s.add ("High Quality");
|
||||
return s;
|
||||
}
|
||||
|
||||
int OggVorbisAudioFormat::estimateOggFileQuality (const File& source)
|
||||
{
|
||||
FileInputStream* const in = source.createInputStream();
|
||||
|
||||
if (in != 0)
|
||||
{
|
||||
AudioFormatReader* const r = createReaderFor (in, true);
|
||||
|
||||
if (r != 0)
|
||||
{
|
||||
const int64 numSamps = r->lengthInSamples;
|
||||
delete r;
|
||||
|
||||
const int64 fileNumSamps = source.getSize() / 4;
|
||||
const double ratio = numSamps / (double) fileNumSamps;
|
||||
|
||||
if (ratio > 12.0)
|
||||
return 0;
|
||||
else if (ratio > 6.0)
|
||||
return 1;
|
||||
else
|
||||
return 2;
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
#endif
|
||||
88
src/audio/audio_file_formats/juce_OggVorbisAudioFormat.h
Normal file
88
src/audio/audio_file_formats/juce_OggVorbisAudioFormat.h
Normal file
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_OGGVORBISAUDIOFORMAT_JUCEHEADER__
|
||||
#define __JUCE_OGGVORBISAUDIOFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormat.h" // (must keep this outside the conditional define)
|
||||
|
||||
#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 in juce_Config.h,
|
||||
and make sure your include search path and library search path are set up to find
|
||||
the Vorbis and Ogg header files and static libraries.
|
||||
|
||||
@see AudioFormat,
|
||||
*/
|
||||
class JUCE_API OggVorbisAudioFormat : public AudioFormat
|
||||
{
|
||||
public:
|
||||
//==============================================================================
|
||||
OggVorbisAudioFormat();
|
||||
~OggVorbisAudioFormat();
|
||||
|
||||
//==============================================================================
|
||||
const Array <int> getPossibleSampleRates();
|
||||
const Array <int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
bool isCompressed();
|
||||
const StringArray getQualityOptions();
|
||||
|
||||
//==============================================================================
|
||||
/** 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);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // __JUCE_OGGVORBISAUDIOFORMAT_JUCEHEADER__
|
||||
407
src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp
Normal file
407
src/audio/audio_file_formats/juce_QuickTimeAudioFormat.cpp
Normal file
|
|
@ -0,0 +1,407 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../../juce_Config.h"
|
||||
|
||||
#if JUCE_QUICKTIME
|
||||
|
||||
#if ! defined (_WIN32)
|
||||
#include <QuickTime/Movies.h>
|
||||
#include <QuickTime/QTML.h>
|
||||
#include <QuickTime/QuickTimeComponents.h>
|
||||
#include <QuickTime/MediaHandlers.h>
|
||||
#include <QuickTime/ImageCodec.h>
|
||||
#else
|
||||
#ifdef _MSC_VER
|
||||
#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 turn off the JUC_QUICKTIME
|
||||
flag in juce_Config.h
|
||||
*/
|
||||
#include <Movies.h>
|
||||
#include <QTML.h>
|
||||
#include <QuickTimeComponents.h>
|
||||
#include <MediaHandlers.h>
|
||||
#include <ImageCodec.h>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (pop)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
#if ! (JUCE_MAC && JUCE_64BIT)
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_QuickTimeAudioFormat.h"
|
||||
#include "../../text/juce_LocalisedStrings.h"
|
||||
#include "../../threads/juce_Thread.h"
|
||||
#include "../../io/network/juce_URL.h"
|
||||
|
||||
bool juce_OpenQuickTimeMovieFromStream (InputStream* input, Movie& movie, Handle& dataHandle);
|
||||
|
||||
#define quickTimeFormatName TRANS("QuickTime file")
|
||||
static const tchar* const quickTimeExtensions[] = { T(".mov"), T(".mp3"), T(".mp4"), 0 };
|
||||
|
||||
//==============================================================================
|
||||
class QTAudioReader : public AudioFormatReader
|
||||
{
|
||||
public:
|
||||
QTAudioReader (InputStream* const input_, const int trackNum_)
|
||||
: AudioFormatReader (input_, quickTimeFormatName),
|
||||
ok (false),
|
||||
movie (0),
|
||||
trackNum (trackNum_),
|
||||
extractor (0),
|
||||
lastSampleRead (0),
|
||||
lastThreadId (0),
|
||||
dataHandle (0)
|
||||
{
|
||||
bufferList = (AudioBufferList*) juce_calloc (256);
|
||||
|
||||
#ifdef WIN32
|
||||
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);
|
||||
|
||||
OSStatus err = MovieAudioExtractionBegin (movie, 0, &extractor);
|
||||
|
||||
unsigned long output_layout_size;
|
||||
err = MovieAudioExtractionGetPropertyInfo (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
|
||||
0, &output_layout_size, 0);
|
||||
if (err != noErr)
|
||||
return;
|
||||
|
||||
AudioChannelLayout* const qt_audio_channel_layout
|
||||
= (AudioChannelLayout*) juce_calloc (output_layout_size);
|
||||
|
||||
err = MovieAudioExtractionGetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
|
||||
output_layout_size, qt_audio_channel_layout, 0);
|
||||
|
||||
qt_audio_channel_layout->mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
|
||||
|
||||
err = MovieAudioExtractionSetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Audio,
|
||||
kQTMovieAudioExtractionAudioPropertyID_AudioChannelLayout,
|
||||
sizeof (qt_audio_channel_layout),
|
||||
qt_audio_channel_layout);
|
||||
|
||||
juce_free (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 (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 = (UInt32) (samplesPerFrame * inputStreamDesc.mBytesPerFrame) + 16;
|
||||
bufferList->mBuffers[0].mData = malloc (bufferList->mBuffers[0].mDataByteSize);
|
||||
|
||||
sampleRate = inputStreamDesc.mSampleRate;
|
||||
bitsPerSample = 16;
|
||||
numChannels = inputStreamDesc.mChannelsPerFrame;
|
||||
|
||||
detachThread();
|
||||
ok = true;
|
||||
}
|
||||
|
||||
~QTAudioReader()
|
||||
{
|
||||
if (dataHandle != 0)
|
||||
DisposeHandle (dataHandle);
|
||||
|
||||
if (extractor != 0)
|
||||
{
|
||||
MovieAudioExtractionEnd (extractor);
|
||||
extractor = 0;
|
||||
}
|
||||
|
||||
checkThreadIsAttached();
|
||||
DisposeMovie (movie);
|
||||
|
||||
juce_free (bufferList->mBuffers[0].mData);
|
||||
juce_free (bufferList);
|
||||
|
||||
#if JUCE_MAC
|
||||
ExitMoviesOnThread ();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
checkThreadIsAttached();
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
if (! loadFrame ((int) startSampleInFile))
|
||||
return false;
|
||||
|
||||
const int numToDo = jmin (numSamples, samplesPerFrame);
|
||||
|
||||
for (int j = numDestChannels; --j >= 0;)
|
||||
{
|
||||
if (destSamples[j] != 0)
|
||||
{
|
||||
const short* const src = ((const short*) bufferList->mBuffers[0].mData) + j;
|
||||
|
||||
for (int i = 0; i < numToDo; ++i)
|
||||
destSamples[j][startOffsetInDestBuffer + i] = src [i << 1] << 16;
|
||||
}
|
||||
}
|
||||
|
||||
startOffsetInDestBuffer += numToDo;
|
||||
startSampleInFile += numToDo;
|
||||
numSamples -= numToDo;
|
||||
}
|
||||
|
||||
detachThread();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool loadFrame (const int sampleNum)
|
||||
{
|
||||
if (lastSampleRead != sampleNum)
|
||||
{
|
||||
TimeRecord time;
|
||||
time.scale = (TimeScale) inputStreamDesc.mSampleRate;
|
||||
time.base = 0;
|
||||
time.value.hi = 0;
|
||||
time.value.lo = (UInt32) sampleNum;
|
||||
|
||||
OSStatus err = MovieAudioExtractionSetProperty (extractor,
|
||||
kQTPropertyClass_MovieAudioExtraction_Movie,
|
||||
kQTMovieAudioExtractionMoviePropertyID_CurrentTime,
|
||||
sizeof (time), &time);
|
||||
|
||||
if (err != noErr)
|
||||
return false;
|
||||
}
|
||||
|
||||
bufferList->mBuffers[0].mDataByteSize = inputStreamDesc.mBytesPerFrame * samplesPerFrame;
|
||||
|
||||
UInt32 outFlags = 0;
|
||||
UInt32 actualNumSamples = samplesPerFrame;
|
||||
OSStatus err = MovieAudioExtractionFillBuffer (extractor, &actualNumSamples,
|
||||
bufferList, &outFlags);
|
||||
|
||||
lastSampleRead = sampleNum + samplesPerFrame;
|
||||
|
||||
return err == noErr;
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
|
||||
bool ok;
|
||||
|
||||
private:
|
||||
Movie movie;
|
||||
Media media;
|
||||
Track track;
|
||||
const int trackNum;
|
||||
double trackUnitsPerFrame;
|
||||
int samplesPerFrame;
|
||||
int lastSampleRead;
|
||||
Thread::ThreadID lastThreadId;
|
||||
MovieAudioExtractionRef extractor;
|
||||
AudioStreamBasicDescription inputStreamDesc;
|
||||
AudioBufferList* bufferList;
|
||||
Handle dataHandle;
|
||||
|
||||
/*OSErr readMovieStream (long offset, long size, void* dataPtr)
|
||||
{
|
||||
input->setPosition (offset);
|
||||
input->read (dataPtr, size);
|
||||
return noErr;
|
||||
}
|
||||
|
||||
static OSErr readMovieStreamProc (long offset, long size, void* dataPtr, void* userRef)
|
||||
{
|
||||
return ((QTAudioReader*) userRef)->readMovieStream (offset, size, dataPtr);
|
||||
}*/
|
||||
|
||||
//==============================================================================
|
||||
void checkThreadIsAttached()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
if (Thread::getCurrentThreadId() != lastThreadId)
|
||||
EnterMoviesOnThread (0);
|
||||
AttachMovieToCurrentThread (movie);
|
||||
#endif
|
||||
}
|
||||
|
||||
void detachThread()
|
||||
{
|
||||
#if JUCE_MAC
|
||||
DetachMovieFromCurrentThread (movie);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//==============================================================================
|
||||
QuickTimeAudioFormat::QuickTimeAudioFormat()
|
||||
: AudioFormat (quickTimeFormatName, (const tchar**) quickTimeExtensions)
|
||||
{
|
||||
}
|
||||
|
||||
QuickTimeAudioFormat::~QuickTimeAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
const Array <int> QuickTimeAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
return Array<int>();
|
||||
}
|
||||
|
||||
const 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)
|
||||
{
|
||||
QTAudioReader* r = new QTAudioReader (sourceStream, 0);
|
||||
|
||||
if (! r->ok)
|
||||
{
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = 0;
|
||||
|
||||
deleteAndZero (r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
AudioFormatWriter* QuickTimeAudioFormat::createWriterFor (OutputStream* /*streamToWriteTo*/,
|
||||
double /*sampleRateToUse*/,
|
||||
unsigned int /*numberOfChannels*/,
|
||||
int /*bitsPerSample*/,
|
||||
const StringPairArray& /*metadataValues*/,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
jassertfalse // not yet implemented!
|
||||
return 0;
|
||||
}
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
|
||||
#endif
|
||||
#endif
|
||||
76
src/audio/audio_file_formats/juce_QuickTimeAudioFormat.h
Normal file
76
src/audio/audio_file_formats/juce_QuickTimeAudioFormat.h
Normal file
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__
|
||||
#define __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormat.h"
|
||||
#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();
|
||||
|
||||
//==============================================================================
|
||||
const Array <int> getPossibleSampleRates();
|
||||
const Array <int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex);
|
||||
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
#endif // __JUCE_QUICKTIMEAUDIOFORMAT_JUCEHEADER__
|
||||
863
src/audio/audio_file_formats/juce_WavAudioFormat.cpp
Normal file
863
src/audio/audio_file_formats/juce_WavAudioFormat.cpp
Normal file
|
|
@ -0,0 +1,863 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#include "../../core/juce_StandardHeader.h"
|
||||
|
||||
BEGIN_JUCE_NAMESPACE
|
||||
|
||||
#include "juce_WavAudioFormat.h"
|
||||
#include "../../io/streams/juce_BufferedInputStream.h"
|
||||
#include "../../text/juce_LocalisedStrings.h"
|
||||
#include "../../io/files/juce_FileInputStream.h"
|
||||
#include "../../io/files/juce_FileOutputStream.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#define wavFormatName TRANS("WAV file")
|
||||
static const tchar* const wavExtensions[] = { T(".wav"), T(".bwf"), 0 };
|
||||
|
||||
|
||||
//==============================================================================
|
||||
const tchar* const WavAudioFormat::bwavDescription = T("bwav description");
|
||||
const tchar* const WavAudioFormat::bwavOriginator = T("bwav originator");
|
||||
const tchar* const WavAudioFormat::bwavOriginatorRef = T("bwav originator ref");
|
||||
const tchar* const WavAudioFormat::bwavOriginationDate = T("bwav origination date");
|
||||
const tchar* const WavAudioFormat::bwavOriginationTime = T("bwav origination time");
|
||||
const tchar* const WavAudioFormat::bwavTimeReference = T("bwav time reference");
|
||||
const tchar* const WavAudioFormat::bwavCodingHistory = T("bwav coding history");
|
||||
|
||||
const StringPairArray WavAudioFormat::createBWAVMetadata (const String& description,
|
||||
const String& originator,
|
||||
const String& originatorRef,
|
||||
const Time& date,
|
||||
const int64 timeReferenceSamples,
|
||||
const String& codingHistory)
|
||||
{
|
||||
StringPairArray m;
|
||||
|
||||
m.set (bwavDescription, description);
|
||||
m.set (bwavOriginator, originator);
|
||||
m.set (bwavOriginatorRef, originatorRef);
|
||||
m.set (bwavOriginationDate, date.formatted (T("%Y-%m-%d")));
|
||||
m.set (bwavOriginationTime, date.formatted (T("%H:%M:%S")));
|
||||
m.set (bwavTimeReference, String (timeReferenceSamples));
|
||||
m.set (bwavCodingHistory, codingHistory);
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
//==============================================================================
|
||||
#if JUCE_MSVC
|
||||
#pragma pack (push, 1)
|
||||
#define PACKED
|
||||
#elif defined (JUCE_GCC)
|
||||
#define PACKED __attribute__((packed))
|
||||
#else
|
||||
#define PACKED
|
||||
#endif
|
||||
|
||||
struct BWAVChunk
|
||||
{
|
||||
uint8 description [256];
|
||||
uint8 originator [32];
|
||||
uint8 originatorRef [32];
|
||||
uint8 originationDate [10];
|
||||
uint8 originationTime [8];
|
||||
uint32 timeRefLow;
|
||||
uint32 timeRefHigh;
|
||||
uint16 version;
|
||||
uint8 umid[64];
|
||||
uint8 reserved[190];
|
||||
uint8 codingHistory[1];
|
||||
|
||||
void copyTo (StringPairArray& values) const
|
||||
{
|
||||
values.set (WavAudioFormat::bwavDescription, String::fromUTF8 (description, 256));
|
||||
values.set (WavAudioFormat::bwavOriginator, String::fromUTF8 (originator, 32));
|
||||
values.set (WavAudioFormat::bwavOriginatorRef, String::fromUTF8 (originatorRef, 32));
|
||||
values.set (WavAudioFormat::bwavOriginationDate, String::fromUTF8 (originationDate, 10));
|
||||
values.set (WavAudioFormat::bwavOriginationTime, String::fromUTF8 (originationTime, 8));
|
||||
|
||||
const uint32 timeLow = swapIfBigEndian (timeRefLow);
|
||||
const uint32 timeHigh = swapIfBigEndian (timeRefHigh);
|
||||
const int64 time = (((int64)timeHigh) << 32) + timeLow;
|
||||
|
||||
values.set (WavAudioFormat::bwavTimeReference, String (time));
|
||||
values.set (WavAudioFormat::bwavCodingHistory, String::fromUTF8 (codingHistory));
|
||||
}
|
||||
|
||||
static MemoryBlock createFrom (const StringPairArray& values)
|
||||
{
|
||||
const int sizeNeeded = sizeof (BWAVChunk) + values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (0) - 1;
|
||||
MemoryBlock data ((sizeNeeded + 3) & ~3);
|
||||
data.fillWith (0);
|
||||
|
||||
BWAVChunk* b = (BWAVChunk*) data.getData();
|
||||
|
||||
// Allow these calls to overwrite an extra byte at the end, which is fine as long
|
||||
// as they get called in the right order..
|
||||
values [WavAudioFormat::bwavDescription].copyToUTF8 (b->description, 257);
|
||||
values [WavAudioFormat::bwavOriginator].copyToUTF8 (b->originator, 33);
|
||||
values [WavAudioFormat::bwavOriginatorRef].copyToUTF8 (b->originatorRef, 33);
|
||||
values [WavAudioFormat::bwavOriginationDate].copyToUTF8 (b->originationDate, 11);
|
||||
values [WavAudioFormat::bwavOriginationTime].copyToUTF8 (b->originationTime, 9);
|
||||
|
||||
const int64 time = values [WavAudioFormat::bwavTimeReference].getLargeIntValue();
|
||||
b->timeRefLow = swapIfBigEndian ((uint32) (time & 0xffffffff));
|
||||
b->timeRefHigh = swapIfBigEndian ((uint32) (time >> 32));
|
||||
|
||||
values [WavAudioFormat::bwavCodingHistory].copyToUTF8 (b->codingHistory);
|
||||
|
||||
if (b->description[0] != 0
|
||||
|| b->originator[0] != 0
|
||||
|| b->originationDate[0] != 0
|
||||
|| b->originationTime[0] != 0
|
||||
|| b->codingHistory[0] != 0
|
||||
|| time != 0)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
|
||||
return MemoryBlock();
|
||||
}
|
||||
|
||||
} PACKED;
|
||||
|
||||
|
||||
//==============================================================================
|
||||
struct SMPLChunk
|
||||
{
|
||||
struct SampleLoop
|
||||
{
|
||||
uint32 identifier;
|
||||
uint32 type;
|
||||
uint32 start;
|
||||
uint32 end;
|
||||
uint32 fraction;
|
||||
uint32 playCount;
|
||||
} PACKED;
|
||||
|
||||
uint32 manufacturer;
|
||||
uint32 product;
|
||||
uint32 samplePeriod;
|
||||
uint32 midiUnityNote;
|
||||
uint32 midiPitchFraction;
|
||||
uint32 smpteFormat;
|
||||
uint32 smpteOffset;
|
||||
uint32 numSampleLoops;
|
||||
uint32 samplerData;
|
||||
SampleLoop loops[1];
|
||||
|
||||
void copyTo (StringPairArray& values, const int totalSize) const
|
||||
{
|
||||
values.set (T("Manufacturer"), String (swapIfBigEndian (manufacturer)));
|
||||
values.set (T("Product"), String (swapIfBigEndian (product)));
|
||||
values.set (T("SamplePeriod"), String (swapIfBigEndian (samplePeriod)));
|
||||
values.set (T("MidiUnityNote"), String (swapIfBigEndian (midiUnityNote)));
|
||||
values.set (T("MidiPitchFraction"), String (swapIfBigEndian (midiPitchFraction)));
|
||||
values.set (T("SmpteFormat"), String (swapIfBigEndian (smpteFormat)));
|
||||
values.set (T("SmpteOffset"), String (swapIfBigEndian (smpteOffset)));
|
||||
values.set (T("NumSampleLoops"), String (swapIfBigEndian (numSampleLoops)));
|
||||
values.set (T("SamplerData"), String (swapIfBigEndian (samplerData)));
|
||||
|
||||
for (uint32 i = 0; i < numSampleLoops; ++i)
|
||||
{
|
||||
if ((uint8*) (loops + (i + 1)) > ((uint8*) this) + totalSize)
|
||||
break;
|
||||
|
||||
values.set (String::formatted (T("Loop%dIdentifier"), i), String (swapIfBigEndian (loops[i].identifier)));
|
||||
values.set (String::formatted (T("Loop%dType"), i), String (swapIfBigEndian (loops[i].type)));
|
||||
values.set (String::formatted (T("Loop%dStart"), i), String (swapIfBigEndian (loops[i].start)));
|
||||
values.set (String::formatted (T("Loop%dEnd"), i), String (swapIfBigEndian (loops[i].end)));
|
||||
values.set (String::formatted (T("Loop%dFraction"), i), String (swapIfBigEndian (loops[i].fraction)));
|
||||
values.set (String::formatted (T("Loop%dPlayCount"), i), String (swapIfBigEndian (loops[i].playCount)));
|
||||
}
|
||||
}
|
||||
} PACKED;
|
||||
|
||||
#if JUCE_MSVC
|
||||
#pragma pack (pop)
|
||||
#endif
|
||||
|
||||
#undef PACKED
|
||||
|
||||
#undef chunkName
|
||||
#define chunkName(a) ((int) littleEndianInt(a))
|
||||
|
||||
//==============================================================================
|
||||
class WavAudioFormatReader : public AudioFormatReader
|
||||
{
|
||||
int bytesPerFrame;
|
||||
int64 dataChunkStart, dataLength;
|
||||
|
||||
WavAudioFormatReader (const WavAudioFormatReader&);
|
||||
const WavAudioFormatReader& operator= (const WavAudioFormatReader&);
|
||||
|
||||
public:
|
||||
int64 bwavChunkStart, bwavSize;
|
||||
|
||||
//==============================================================================
|
||||
WavAudioFormatReader (InputStream* const in)
|
||||
: AudioFormatReader (in, wavFormatName),
|
||||
dataLength (0),
|
||||
bwavChunkStart (0),
|
||||
bwavSize (0)
|
||||
{
|
||||
if (input->readInt() == chunkName ("RIFF"))
|
||||
{
|
||||
const uint32 len = (uint32) input->readInt();
|
||||
const int64 end = input->getPosition() + len;
|
||||
bool hasGotType = false;
|
||||
bool hasGotData = false;
|
||||
|
||||
if (input->readInt() == chunkName ("WAVE"))
|
||||
{
|
||||
while (input->getPosition() < end
|
||||
&& ! input->isExhausted())
|
||||
{
|
||||
const int chunkType = input->readInt();
|
||||
uint32 length = (uint32) input->readInt();
|
||||
const int64 chunkEnd = input->getPosition() + length + (length & 1);
|
||||
|
||||
if (chunkType == chunkName ("fmt "))
|
||||
{
|
||||
// read the format chunk
|
||||
const short format = input->readShort();
|
||||
const short numChans = input->readShort();
|
||||
sampleRate = input->readInt();
|
||||
const int bytesPerSec = input->readInt();
|
||||
|
||||
numChannels = numChans;
|
||||
bytesPerFrame = bytesPerSec / (int)sampleRate;
|
||||
bitsPerSample = 8 * bytesPerFrame / numChans;
|
||||
|
||||
if (format == 3)
|
||||
usesFloatingPointData = true;
|
||||
else if (format != 1)
|
||||
bytesPerFrame = 0;
|
||||
|
||||
hasGotType = true;
|
||||
}
|
||||
else if (chunkType == chunkName ("data"))
|
||||
{
|
||||
// get the data chunk's position
|
||||
dataLength = length;
|
||||
dataChunkStart = input->getPosition();
|
||||
lengthInSamples = (bytesPerFrame > 0) ? (dataLength / bytesPerFrame) : 0;
|
||||
|
||||
hasGotData = true;
|
||||
}
|
||||
else if (chunkType == chunkName ("bext"))
|
||||
{
|
||||
bwavChunkStart = input->getPosition();
|
||||
bwavSize = length;
|
||||
|
||||
// Broadcast-wav extension chunk..
|
||||
BWAVChunk* const bwav = (BWAVChunk*) juce_calloc (jmax (length + 1, (int) sizeof (BWAVChunk)));
|
||||
input->read (bwav, length);
|
||||
bwav->copyTo (metadataValues);
|
||||
juce_free (bwav);
|
||||
}
|
||||
else if (chunkType == chunkName ("smpl"))
|
||||
{
|
||||
SMPLChunk* const smpl = (SMPLChunk*) juce_calloc (jmax (length + 1, (int) sizeof (SMPLChunk)));
|
||||
input->read (smpl, length);
|
||||
smpl->copyTo (metadataValues, length);
|
||||
juce_free (smpl);
|
||||
}
|
||||
else if (chunkEnd <= input->getPosition())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
input->setPosition (chunkEnd);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
~WavAudioFormatReader()
|
||||
{
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,
|
||||
int64 startSampleInFile, int numSamples)
|
||||
{
|
||||
numSamples = (int) jmin ((int64) numSamples, lengthInSamples - startSampleInFile);
|
||||
|
||||
if (numSamples <= 0)
|
||||
return true;
|
||||
|
||||
input->setPosition (dataChunkStart + startSampleInFile * bytesPerFrame);
|
||||
|
||||
const int tempBufSize = 480 * 3 * 4; // (keep this a multiple of 3)
|
||||
char tempBuffer [tempBufSize];
|
||||
|
||||
while (numSamples > 0)
|
||||
{
|
||||
int* left = destSamples[0];
|
||||
if (left != 0)
|
||||
left += startOffsetInDestBuffer;
|
||||
|
||||
int* right = numDestChannels > 1 ? destSamples[1] : 0;
|
||||
if (right != 0)
|
||||
right += startOffsetInDestBuffer;
|
||||
|
||||
const int numThisTime = jmin (tempBufSize / bytesPerFrame, numSamples);
|
||||
const int bytesRead = input->read (tempBuffer, numThisTime * bytesPerFrame);
|
||||
|
||||
if (bytesRead < numThisTime * bytesPerFrame)
|
||||
zeromem (tempBuffer + bytesRead, numThisTime * bytesPerFrame - bytesRead);
|
||||
|
||||
if (bitsPerSample == 16)
|
||||
{
|
||||
const short* src = (const short*) tempBuffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
*right++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = (int) swapIfBigEndian ((unsigned short) *src++) << 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 24)
|
||||
{
|
||||
const char* src = (const char*) tempBuffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
src += 3;
|
||||
*right++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = littleEndian24Bit (src) << 8;
|
||||
src += 6;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numThisTime; ++i)
|
||||
{
|
||||
*left++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
*right++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numThisTime; ++i)
|
||||
{
|
||||
*left++ = littleEndian24Bit (src) << 8;
|
||||
src += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 32)
|
||||
{
|
||||
const unsigned int* src = (const unsigned int*) tempBuffer;
|
||||
unsigned int* l = (unsigned int*) left;
|
||||
unsigned int* r = (unsigned int*) right;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (l == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*r++ = swapIfBigEndian (*src++);
|
||||
}
|
||||
}
|
||||
else if (r == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfBigEndian (*src++);
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfBigEndian (*src++);
|
||||
*r++ = swapIfBigEndian (*src++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*l++ = swapIfBigEndian (*src++);
|
||||
}
|
||||
}
|
||||
|
||||
left = (int*)l;
|
||||
right = (int*)r;
|
||||
}
|
||||
else if (bitsPerSample == 8)
|
||||
{
|
||||
const unsigned char* src = (const unsigned char*) tempBuffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
if (left == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
++src;
|
||||
*right++ = ((int) *src++ - 128) << 24;
|
||||
}
|
||||
}
|
||||
else if (right == 0)
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = ((int) *src++ - 128) << 24;
|
||||
++src;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = ((int) *src++ - 128) << 24;
|
||||
*right++ = ((int) *src++ - 128) << 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numThisTime; --i >= 0;)
|
||||
{
|
||||
*left++ = ((int)*src++ - 128) << 24;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
startOffsetInDestBuffer += numThisTime;
|
||||
numSamples -= numThisTime;
|
||||
}
|
||||
|
||||
if (numSamples > 0)
|
||||
{
|
||||
for (int i = numDestChannels; --i >= 0;)
|
||||
if (destSamples[i] != 0)
|
||||
zeromem (destSamples[i] + startOffsetInDestBuffer,
|
||||
sizeof (int) * numSamples);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
class WavAudioFormatWriter : public AudioFormatWriter
|
||||
{
|
||||
MemoryBlock tempBlock, bwavChunk;
|
||||
uint32 lengthInSamples, bytesWritten;
|
||||
int64 headerPosition;
|
||||
bool writeFailed;
|
||||
|
||||
WavAudioFormatWriter (const WavAudioFormatWriter&);
|
||||
const WavAudioFormatWriter& operator= (const WavAudioFormatWriter&);
|
||||
|
||||
void writeHeader()
|
||||
{
|
||||
const bool seekedOk = output->setPosition (headerPosition);
|
||||
(void) seekedOk;
|
||||
|
||||
// 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 (seekedOk);
|
||||
|
||||
const int bytesPerFrame = numChannels * bitsPerSample / 8;
|
||||
output->writeInt (chunkName ("RIFF"));
|
||||
output->writeInt (lengthInSamples * bytesPerFrame
|
||||
+ ((bwavChunk.getSize() > 0) ? (44 + bwavChunk.getSize()) : 36));
|
||||
|
||||
output->writeInt (chunkName ("WAVE"));
|
||||
output->writeInt (chunkName ("fmt "));
|
||||
output->writeInt (16);
|
||||
output->writeShort ((bitsPerSample < 32) ? (short) 1 /*WAVE_FORMAT_PCM*/
|
||||
: (short) 3 /*WAVE_FORMAT_IEEE_FLOAT*/);
|
||||
output->writeShort ((short) numChannels);
|
||||
output->writeInt ((int) sampleRate);
|
||||
output->writeInt (bytesPerFrame * (int) sampleRate);
|
||||
output->writeShort ((short) bytesPerFrame);
|
||||
output->writeShort ((short) bitsPerSample);
|
||||
|
||||
if (bwavChunk.getSize() > 0)
|
||||
{
|
||||
output->writeInt (chunkName ("bext"));
|
||||
output->writeInt (bwavChunk.getSize());
|
||||
output->write (bwavChunk.getData(), bwavChunk.getSize());
|
||||
}
|
||||
|
||||
output->writeInt (chunkName ("data"));
|
||||
output->writeInt (lengthInSamples * bytesPerFrame);
|
||||
|
||||
usesFloatingPointData = (bitsPerSample == 32);
|
||||
}
|
||||
|
||||
public:
|
||||
//==============================================================================
|
||||
WavAudioFormatWriter (OutputStream* const out,
|
||||
const double sampleRate,
|
||||
const unsigned int numChannels_,
|
||||
const int bits,
|
||||
const StringPairArray& metadataValues)
|
||||
: AudioFormatWriter (out,
|
||||
wavFormatName,
|
||||
sampleRate,
|
||||
numChannels_,
|
||||
bits),
|
||||
lengthInSamples (0),
|
||||
bytesWritten (0),
|
||||
writeFailed (false)
|
||||
{
|
||||
if (metadataValues.size() > 0)
|
||||
bwavChunk = BWAVChunk::createFrom (metadataValues);
|
||||
|
||||
headerPosition = out->getPosition();
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
~WavAudioFormatWriter()
|
||||
{
|
||||
writeHeader();
|
||||
}
|
||||
|
||||
//==============================================================================
|
||||
bool write (const int** data, int numSamples)
|
||||
{
|
||||
if (writeFailed)
|
||||
return false;
|
||||
|
||||
const int bytes = numChannels * numSamples * bitsPerSample / 8;
|
||||
tempBlock.ensureSize (bytes, false);
|
||||
char* buffer = (char*) tempBlock.getData();
|
||||
|
||||
const int* left = data[0];
|
||||
const int* right = data[1];
|
||||
if (right == 0)
|
||||
right = left;
|
||||
|
||||
if (bitsPerSample == 16)
|
||||
{
|
||||
short* b = (short*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (short) swapIfBigEndian ((unsigned short) (*left++ >> 16));
|
||||
*b++ = (short) swapIfBigEndian ((unsigned short) (*right++ >> 16));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (short) swapIfBigEndian ((unsigned short) (*left++ >> 16));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 24)
|
||||
{
|
||||
char* b = (char*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
littleEndian24BitToChars ((*left++) >> 8, b);
|
||||
b += 3;
|
||||
littleEndian24BitToChars ((*right++) >> 8, b);
|
||||
b += 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
littleEndian24BitToChars ((*left++) >> 8, b);
|
||||
b += 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 32)
|
||||
{
|
||||
unsigned int* b = (unsigned int*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = swapIfBigEndian ((unsigned int) *left++);
|
||||
*b++ = swapIfBigEndian ((unsigned int) *right++);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = swapIfBigEndian ((unsigned int) *left++);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (bitsPerSample == 8)
|
||||
{
|
||||
unsigned char* b = (unsigned char*) buffer;
|
||||
|
||||
if (numChannels > 1)
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (unsigned char) (128 + (*left++ >> 24));
|
||||
*b++ = (unsigned char) (128 + (*right++ >> 24));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = numSamples; --i >= 0;)
|
||||
{
|
||||
*b++ = (unsigned char) (128 + (*left++ >> 24));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bytesWritten + bytes >= (uint32) 0xfff00000
|
||||
|| ! output->write (buffer, 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 += numSamples;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
//==============================================================================
|
||||
WavAudioFormat::WavAudioFormat()
|
||||
: AudioFormat (wavFormatName, (const tchar**) wavExtensions)
|
||||
{
|
||||
}
|
||||
|
||||
WavAudioFormat::~WavAudioFormat()
|
||||
{
|
||||
}
|
||||
|
||||
const Array <int> WavAudioFormat::getPossibleSampleRates()
|
||||
{
|
||||
const int rates[] = { 22050, 32000, 44100, 48000, 88200, 96000, 176400, 192000, 0 };
|
||||
return Array <int> (rates);
|
||||
}
|
||||
|
||||
const Array <int> WavAudioFormat::getPossibleBitDepths()
|
||||
{
|
||||
const int depths[] = { 8, 16, 24, 32, 0 };
|
||||
return Array <int> (depths);
|
||||
}
|
||||
|
||||
bool WavAudioFormat::canDoStereo()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
bool WavAudioFormat::canDoMono()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
AudioFormatReader* WavAudioFormat::createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails)
|
||||
{
|
||||
WavAudioFormatReader* r = new WavAudioFormatReader (sourceStream);
|
||||
|
||||
if (r->sampleRate == 0)
|
||||
{
|
||||
if (! deleteStreamIfOpeningFails)
|
||||
r->input = 0;
|
||||
|
||||
deleteAndZero (r);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
AudioFormatWriter* WavAudioFormat::createWriterFor (OutputStream* out,
|
||||
double sampleRate,
|
||||
unsigned int numChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int /*qualityOptionIndex*/)
|
||||
{
|
||||
if (getPossibleBitDepths().contains (bitsPerSample))
|
||||
{
|
||||
return new WavAudioFormatWriter (out,
|
||||
sampleRate,
|
||||
numChannels,
|
||||
bitsPerSample,
|
||||
metadataValues);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool juce_slowCopyOfWavFileWithNewMetadata (const File& file, const StringPairArray& metadata)
|
||||
{
|
||||
bool ok = false;
|
||||
WavAudioFormat wav;
|
||||
|
||||
const File dest (file.getNonexistentSibling());
|
||||
|
||||
OutputStream* outStream = dest.createOutputStream();
|
||||
|
||||
if (outStream != 0)
|
||||
{
|
||||
AudioFormatReader* reader = wav.createReaderFor (file.createInputStream(), true);
|
||||
|
||||
if (reader != 0)
|
||||
{
|
||||
AudioFormatWriter* writer = wav.createWriterFor (outStream, reader->sampleRate,
|
||||
reader->numChannels, reader->bitsPerSample,
|
||||
metadata, 0);
|
||||
|
||||
if (writer != 0)
|
||||
{
|
||||
ok = writer->writeFromAudioReader (*reader, 0, -1);
|
||||
|
||||
outStream = 0;
|
||||
delete writer;
|
||||
}
|
||||
|
||||
delete reader;
|
||||
}
|
||||
|
||||
delete outStream;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
ok = dest.moveFileTo (file);
|
||||
|
||||
if (! ok)
|
||||
dest.deleteFile();
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool WavAudioFormat::replaceMetadataInFile (const File& wavFile, const StringPairArray& newMetadata)
|
||||
{
|
||||
WavAudioFormatReader* reader = (WavAudioFormatReader*) createReaderFor (wavFile.createInputStream(), true);
|
||||
|
||||
if (reader != 0)
|
||||
{
|
||||
const int64 bwavPos = reader->bwavChunkStart;
|
||||
const int64 bwavSize = reader->bwavSize;
|
||||
delete reader;
|
||||
|
||||
if (bwavSize > 0)
|
||||
{
|
||||
MemoryBlock chunk = BWAVChunk::createFrom (newMetadata);
|
||||
|
||||
if (chunk.getSize() <= bwavSize)
|
||||
{
|
||||
// the new one will fit in the space available, so write it directly..
|
||||
const int64 oldSize = wavFile.getSize();
|
||||
|
||||
FileOutputStream* out = wavFile.createOutputStream();
|
||||
out->setPosition (bwavPos);
|
||||
out->write (chunk.getData(), chunk.getSize());
|
||||
out->setPosition (oldSize);
|
||||
delete out;
|
||||
|
||||
jassert (wavFile.getSize() == oldSize);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return juce_slowCopyOfWavFileWithNewMetadata (wavFile, newMetadata);
|
||||
}
|
||||
|
||||
|
||||
END_JUCE_NAMESPACE
|
||||
151
src/audio/audio_file_formats/juce_WavAudioFormat.h
Normal file
151
src/audio/audio_file_formats/juce_WavAudioFormat.h
Normal file
|
|
@ -0,0 +1,151 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
#ifndef __JUCE_WAVAUDIOFORMAT_JUCEHEADER__
|
||||
#define __JUCE_WAVAUDIOFORMAT_JUCEHEADER__
|
||||
|
||||
#include "juce_AudioFormat.h"
|
||||
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
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 tchar* 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 tchar* 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 tchar* 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 tchar* 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 tchar* 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 tchar* const bwavTimeReference;
|
||||
|
||||
/** Metadata property name used by wav readers and writers for adding
|
||||
a BWAV chunk to the file.
|
||||
|
||||
This is a
|
||||
|
||||
@see AudioFormatReader::metadataValues, createWriterFor
|
||||
*/
|
||||
static const tchar* 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 const StringPairArray createBWAVMetadata (const String& description,
|
||||
const String& originator,
|
||||
const String& originatorRef,
|
||||
const Time& dateAndTime,
|
||||
const int64 timeReferenceSamples,
|
||||
const String& codingHistory);
|
||||
|
||||
//==============================================================================
|
||||
const Array <int> getPossibleSampleRates();
|
||||
const Array <int> getPossibleBitDepths();
|
||||
bool canDoStereo();
|
||||
bool canDoMono();
|
||||
|
||||
//==============================================================================
|
||||
AudioFormatReader* createReaderFor (InputStream* sourceStream,
|
||||
const bool deleteStreamIfOpeningFails);
|
||||
|
||||
AudioFormatWriter* createWriterFor (OutputStream* streamToWriteTo,
|
||||
double sampleRateToUse,
|
||||
unsigned int numberOfChannels,
|
||||
int bitsPerSample,
|
||||
const StringPairArray& metadataValues,
|
||||
int qualityOptionIndex);
|
||||
|
||||
//==============================================================================
|
||||
/** 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);
|
||||
|
||||
//==============================================================================
|
||||
juce_UseDebuggingNewOperator
|
||||
};
|
||||
|
||||
|
||||
#endif // __JUCE_WAVAUDIOFORMAT_JUCEHEADER__
|
||||
|
|
@ -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.
|
||||
789
src/audio/audio_file_formats/oggvorbis/bitwise.c
Normal file
789
src/audio/audio_file_formats/oggvorbis/bitwise.c
Normal file
|
|
@ -0,0 +1,789 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 "juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
#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
|
||||
|
||||
#endif
|
||||
239
src/audio/audio_file_formats/oggvorbis/codec.h
Normal file
239
src/audio/audio_file_formats/oggvorbis/codec.h
Normal file
|
|
@ -0,0 +1,239 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec.h,v 1.1 2007/06/07 17:48:18 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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 independant from other vorbis_blocks belonging to
|
||||
that logical bitstream. *************************************************/
|
||||
|
||||
struct alloc_chain{
|
||||
void *ptr;
|
||||
struct alloc_chain *next;
|
||||
};
|
||||
|
||||
/* vorbis_info contains all the setup information specific to the
|
||||
specific compression/decompression mode in progress (eg,
|
||||
psychoacoustic settings, channel setup, options, codebook
|
||||
etc). vorbis_info and substructures are in backends.h.
|
||||
*********************************************************************/
|
||||
|
||||
/* the comments are not part of vorbis_info so that vorbis_info can be
|
||||
static storage */
|
||||
typedef struct vorbis_comment{
|
||||
/* unlimited user comment fields. libvorbis writes 'libvorbis'
|
||||
whatever vendor is set to in encode */
|
||||
char **user_comments;
|
||||
int *comment_lengths;
|
||||
int comments;
|
||||
char *vendor;
|
||||
|
||||
} vorbis_comment;
|
||||
|
||||
|
||||
/* libvorbis encodes in two abstraction layers; first we perform DSP
|
||||
and produce a packet (see docs/analysis.txt). The packet is then
|
||||
coded into a framed OggSquish bitstream by the second layer (see
|
||||
docs/framing.txt). Decode is the reverse process; we sync/frame
|
||||
the bitstream and extract individual packets, then decode the
|
||||
packet back into PCM audio.
|
||||
|
||||
The extra framing/packetizing is used in streaming formats, such as
|
||||
files. Over the net (such as with UDP), the framing and
|
||||
packetization aren't necessary as they're provided by the transport
|
||||
and the streaming layer is not used */
|
||||
|
||||
/* Vorbis PRIMITIVES: general ***************************************/
|
||||
|
||||
extern void vorbis_info_init(vorbis_info *vi);
|
||||
extern void vorbis_info_clear(vorbis_info *vi);
|
||||
extern int vorbis_info_blocksize(vorbis_info *vi,int zo);
|
||||
extern void vorbis_comment_init(vorbis_comment *vc);
|
||||
extern void vorbis_comment_add(vorbis_comment *vc, char *comment);
|
||||
extern void vorbis_comment_add_tag(vorbis_comment *vc,
|
||||
const char *tag, char *contents);
|
||||
extern char *vorbis_comment_query(vorbis_comment *vc, char *tag, int count);
|
||||
extern int vorbis_comment_query_count(vorbis_comment *vc, char *tag);
|
||||
extern void vorbis_comment_clear(vorbis_comment *vc);
|
||||
|
||||
extern int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb);
|
||||
extern int vorbis_block_clear(vorbis_block *vb);
|
||||
extern void vorbis_dsp_clear(vorbis_dsp_state *v);
|
||||
extern double vorbis_granule_time(vorbis_dsp_state *v,
|
||||
ogg_int64_t granulepos);
|
||||
|
||||
/* Vorbis PRIMITIVES: analysis/DSP layer ****************************/
|
||||
|
||||
extern int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi);
|
||||
extern int vorbis_commentheader_out(vorbis_comment *vc, ogg_packet *op);
|
||||
extern int vorbis_analysis_headerout(vorbis_dsp_state *v,
|
||||
vorbis_comment *vc,
|
||||
ogg_packet *op,
|
||||
ogg_packet *op_comm,
|
||||
ogg_packet *op_code);
|
||||
extern float **vorbis_analysis_buffer(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_wrote(vorbis_dsp_state *v,int vals);
|
||||
extern int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb);
|
||||
extern int vorbis_analysis(vorbis_block *vb,ogg_packet *op);
|
||||
|
||||
extern int vorbis_bitrate_addblock(vorbis_block *vb);
|
||||
extern int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,
|
||||
ogg_packet *op);
|
||||
|
||||
/* Vorbis PRIMITIVES: synthesis layer *******************************/
|
||||
extern int vorbis_synthesis_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
|
||||
10
src/audio/audio_file_formats/oggvorbis/config_types.h
Normal file
10
src/audio/audio_file_formats/oggvorbis/config_types.h
Normal file
|
|
@ -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
|
||||
1801
src/audio/audio_file_formats/oggvorbis/framing.c
Normal file
1801
src/audio/audio_file_formats/oggvorbis/framing.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
==============================================================================
|
||||
|
||||
This file is part of the JUCE library - "Jules' Utility Class Extensions"
|
||||
Copyright 2004-9 by Raw Material Software Ltd.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
JUCE can be redistributed and/or modified under the terms of the GNU General
|
||||
Public License (Version 2), as published by the Free Software Foundation.
|
||||
A copy of the license is included in the JUCE distribution, or can be found
|
||||
online 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.rawmaterialsoftware.com/juce for more information.
|
||||
|
||||
==============================================================================
|
||||
*/
|
||||
|
||||
// This file is included at the start of each Ogg-Vorbis .c file, just to do a few housekeeping
|
||||
// tasks..
|
||||
|
||||
|
||||
#include "../../../../juce_Config.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning (disable: 4267 4127 4244 4996 4100 4701 4702 4013 4133 4206 4305 4189 4706)
|
||||
#endif
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
Monty <monty@xiph.org>
|
||||
|
||||
and the rest of the Xiph.org Foundation.
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
Copyright (c) 2002-2004 Xiph.org Foundation
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions
|
||||
are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Xiph.org Foundation nor the names of its
|
||||
contributors may be used to endorse or promote products derived from
|
||||
this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION
|
||||
OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
132
src/audio/audio_file_formats/oggvorbis/libvorbis-1.1.2/README
Normal file
132
src/audio/audio_file_formats/oggvorbis/libvorbis-1.1.2/README
Normal file
|
|
@ -0,0 +1,132 @@
|
|||
********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2004 *
|
||||
* by the Xiph.org Foundation, http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
Vorbis is a general purpose audio and music encoding format
|
||||
contemporary to MPEG-4's AAC and TwinVQ, the next generation beyond
|
||||
MPEG audio layer 3. Unlike the MPEG sponsored formats (and other
|
||||
proprietary formats such as RealAudio G2 and Windows' flavor of the
|
||||
month), the Vorbis CODEC specification belongs to the public domain.
|
||||
All the technical details are published and documented, and any
|
||||
software entity may make full use of the format without license
|
||||
fee, royalty or patent concerns.
|
||||
|
||||
This package contains:
|
||||
|
||||
* libvorbis, a BSD-style license software implementation of
|
||||
the Vorbis specification by the Xiph.Org Foundation
|
||||
(http://www.xiph.org/)
|
||||
|
||||
* libvorbisfile, a BSD-style license convenience library
|
||||
built on Vorbis designed to simplify common uses
|
||||
|
||||
* libvorbisenc, a BSD-style license library that provides a simple,
|
||||
programmatic encoding setup interface
|
||||
|
||||
* example code making use of libogg, libvorbis, libvorbisfile and
|
||||
libvorbisenc
|
||||
|
||||
WHAT'S HERE:
|
||||
|
||||
This source distribution includes libvorbis and an example
|
||||
encoder/player to demonstrate use of libvorbis as well as
|
||||
documentation on the Ogg Vorbis audio coding format.
|
||||
|
||||
You'll need libogg (distributed separately) to compile this library.
|
||||
A more comprehensive set of utilities is available in the vorbis-tools
|
||||
package.
|
||||
|
||||
Directory:
|
||||
|
||||
./lib The source for the libraries, a BSD-license implementation
|
||||
of the public domain Ogg Vorbis audio encoding format.
|
||||
|
||||
./include Library API headers
|
||||
|
||||
./debian Rules/spec files for building Debian .deb packages
|
||||
|
||||
./doc Vorbis documentation
|
||||
|
||||
./examples Example code illustrating programmatic use of libvorbis,
|
||||
libvorbisfile and libvorbisenc
|
||||
|
||||
./mac Codewarrior project files and build tweaks for MacOS.
|
||||
|
||||
./macosx Project files for MacOS X.
|
||||
|
||||
./win32 Win32 projects files and build automation
|
||||
|
||||
./vq Internal utilities for training/building new LSP/residue
|
||||
and auxiliary codebooks.
|
||||
|
||||
CONTACT:
|
||||
|
||||
The Ogg homepage is located at 'http://www.xiph.org/ogg/'.
|
||||
Vorbis's homepage is located at 'http://www.xiph.org/vorbis/'.
|
||||
Up to date technical documents, contact information, source code and
|
||||
pre-built utilities may be found there.
|
||||
|
||||
The user website for Ogg Vorbis software and audio is http://vorbis.com/
|
||||
|
||||
BUILDING FROM TRUNK:
|
||||
|
||||
Development source is under subversion revision control at
|
||||
http://svn.xiph.org/trunk/vorbis/. You will also need the
|
||||
newest versions of autoconf, automake, and libtool in order
|
||||
to compile vorbis from development source. A configure script
|
||||
is provided for you in the source tarball distributions.
|
||||
|
||||
[update or checkout latest source]
|
||||
./autogen.sh
|
||||
make
|
||||
|
||||
and as root if desired:
|
||||
|
||||
make install
|
||||
|
||||
This will install the vorbis libraries (static and shared) into
|
||||
/usr/local/lib, includes into /usr/local/include and API manpages
|
||||
(once we write some) into /usr/local/man.
|
||||
|
||||
BUILDING FROM TARBALL DISTRIBUTIONS:
|
||||
|
||||
./configure
|
||||
make
|
||||
|
||||
and optionally (as root):
|
||||
make install
|
||||
|
||||
BUILDING RPMS:
|
||||
|
||||
after normal configuring:
|
||||
|
||||
make dist
|
||||
rpm -ta libvorbis-<version>.tar.gz
|
||||
|
||||
BUILDING ON MACOS 9:
|
||||
|
||||
Vorbis on MacOS 9 is built using Metroworks CodeWarrior. To build it,
|
||||
first verify that the Ogg libraries are already built following the
|
||||
instructions in the Ogg module README. Open vorbis/mac/libvorbis.mcp,
|
||||
switch to the "Targets" pane, select everything, and make the project.
|
||||
Do the same thing to build libvorbisenc.mcp, and libvorbisfile.mcp (in
|
||||
that order). In vorbis/mac/Output you will now have both debug and final
|
||||
versions of Vorbis shared libraries to link your projects against.
|
||||
|
||||
To build a project using Ogg Vorbis, add access paths to your
|
||||
CodeWarrior project for the ogg/include, ogg/mac/Output,
|
||||
vorbis/include, and vorbis/mac/Output folders. Be sure that
|
||||
"interpret DOS and Unix paths" is turned on in your project; it can
|
||||
be found in the "access paths" pane in your project settings. Now
|
||||
simply add the shared libraries you need to your project (OggLib and
|
||||
VorbisLib at least) and #include "ogg/ogg.h" and "vorbis/codec.h"
|
||||
wherever you need to access Ogg and Vorbis functionality.
|
||||
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: single-block PCM analysis mode dispatch
|
||||
last mod: $Id: analysis.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
#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"
|
||||
|
||||
int analysis_noisy=1;
|
||||
|
||||
/* decides between modes, dispatches to the appropriate mapping. */
|
||||
int vorbis_analysis(vorbis_block *vb, ogg_packet *op){
|
||||
int ret,i;
|
||||
vorbis_block_internal *vbi=(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);
|
||||
}
|
||||
|
||||
/* there was no great place to put this.... */
|
||||
void _analysis_output_always(const char *base,int i,float *v,int n,int bark,int dB,ogg_int64_t off){
|
||||
int j;
|
||||
FILE *of;
|
||||
char buffer[80];
|
||||
|
||||
/* if(i==5870){*/
|
||||
sprintf(buffer,"%s_%d.m",base,i);
|
||||
of=fopen(buffer,"w");
|
||||
|
||||
if(!of)perror("failed to open data dump file");
|
||||
|
||||
for(j=0;j<n;j++){
|
||||
if(bark){
|
||||
float b=toBARK((4000.f*j/n)+.25);
|
||||
fprintf(of,"%f ",b);
|
||||
}else
|
||||
if(off!=0)
|
||||
fprintf(of,"%f ",(double)(j+off)/8000.);
|
||||
else
|
||||
fprintf(of,"%f ",(double)j);
|
||||
|
||||
if(dB){
|
||||
float val;
|
||||
if(v[j]==0.)
|
||||
val=-140.;
|
||||
else
|
||||
val=todB(v+j);
|
||||
fprintf(of,"%f\n",val);
|
||||
}else{
|
||||
fprintf(of,"%f\n",v[j]);
|
||||
}
|
||||
}
|
||||
fclose(of);
|
||||
/* } */
|
||||
}
|
||||
|
||||
void _analysis_output(char *base,int i,float *v,int n,int bark,int dB,
|
||||
ogg_int64_t off){
|
||||
if(analysis_noisy)_analysis_output_always(base,i,v,n,bark,dB,off);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -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-2002 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis backend and mapping structures; needed for
|
||||
static mode headers
|
||||
last mod: $Id: backends.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
/* 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 *,
|
||||
float **,int *,int);
|
||||
int (*forward) (oggpack_buffer *,struct vorbis_block *,
|
||||
vorbis_look_residue *,
|
||||
float **,float **,int *,int,long **);
|
||||
int (*inverse) (struct vorbis_block *,vorbis_look_residue *,
|
||||
float **,int *,int);
|
||||
} vorbis_func_residue;
|
||||
|
||||
typedef struct vorbis_info_residue0{
|
||||
/* block-partitioned VQ coded straight residue */
|
||||
long begin;
|
||||
long end;
|
||||
|
||||
/* first stage (lossless partitioning) */
|
||||
int grouping; /* group n vectors per partition */
|
||||
int partitions; /* possible codebooks for a partition */
|
||||
int groupbook; /* huffbook for partitioning */
|
||||
int secondstages[64]; /* expanded out to pointers in lookup */
|
||||
int booklist[256]; /* list of second stage books */
|
||||
|
||||
float classmetric1[64];
|
||||
float classmetric2[64];
|
||||
|
||||
} vorbis_info_residue0;
|
||||
|
||||
/* Mapping backend generic *****************************************/
|
||||
typedef struct{
|
||||
void (*pack) (vorbis_info *,vorbis_info_mapping *,
|
||||
oggpack_buffer *);
|
||||
vorbis_info_mapping *(*unpack)(vorbis_info *,oggpack_buffer *);
|
||||
void (*free_info) (vorbis_info_mapping *);
|
||||
int (*forward) (struct vorbis_block *vb);
|
||||
int (*inverse) (struct vorbis_block *vb,vorbis_info_mapping *);
|
||||
} vorbis_func_mapping;
|
||||
|
||||
typedef struct vorbis_info_mapping0{
|
||||
int submaps; /* <= 16 */
|
||||
int chmuxlist[256]; /* up to 256 channels in a Vorbis stream */
|
||||
|
||||
int floorsubmap[16]; /* [mux] submap to floors */
|
||||
int residuesubmap[16]; /* [mux] submap to residue */
|
||||
|
||||
int coupling_steps;
|
||||
int coupling_mag[256];
|
||||
int coupling_ang[256];
|
||||
|
||||
} vorbis_info_mapping0;
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,259 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
last mod: $Id: bitrate.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
|
||||
#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= rint(1.*bi->avg_rate*halfsamples/ratesamples);
|
||||
bm->min_bitsper= rint(1.*bi->min_rate*halfsamples/ratesamples);
|
||||
bm->max_bitsper= rint(1.*bi->max_rate*halfsamples/ratesamples);
|
||||
|
||||
bm->avgfloat=PACKETBLOBS/2;
|
||||
|
||||
/* not a necessary fix, but one that leads to a more balanced
|
||||
typical initialization */
|
||||
{
|
||||
long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
bm->avg_reservoir=desired_fill;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void vorbis_bitrate_clear(bitrate_manager_state *bm){
|
||||
memset(bm,0,sizeof(*bm));
|
||||
return;
|
||||
}
|
||||
|
||||
int vorbis_bitrate_managed(vorbis_block *vb){
|
||||
vorbis_dsp_state *vd=vb->vd;
|
||||
private_state *b=(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=rint(bm->avgfloat);
|
||||
long this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
long min_target_bits=(vb->W?bm->min_bitsper*bm->short_per_long:bm->min_bitsper);
|
||||
long max_target_bits=(vb->W?bm->max_bitsper*bm->short_per_long:bm->max_bitsper);
|
||||
int samples=ci->blocksizes[vb->W]>>1;
|
||||
long desired_fill=bi->reservoir_bits*bi->reservoir_bias;
|
||||
if(!bm->managed){
|
||||
/* not a bitrate managed stream, but for API simplicity, we'll
|
||||
buffer the packet to keep the code path clean */
|
||||
|
||||
if(bm->vb)return(-1); /* one has been submitted without
|
||||
being claimed */
|
||||
bm->vb=vb;
|
||||
return(0);
|
||||
}
|
||||
|
||||
bm->vb=vb;
|
||||
|
||||
/* look ahead for avg floater */
|
||||
if(bm->avg_bitsper>0){
|
||||
double slew=0.;
|
||||
long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
|
||||
double slewlimit= 15./bi->slew_damp;
|
||||
|
||||
/* choosing a new floater:
|
||||
if we're over target, we slew down
|
||||
if we're under target, we slew up
|
||||
|
||||
choose slew as follows: look through packetblobs of this frame
|
||||
and set slew as the first in the appropriate direction that
|
||||
gives us the slew we want. This may mean no slew if delta is
|
||||
already favorable.
|
||||
|
||||
Then limit slew to slew max */
|
||||
|
||||
if(bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
|
||||
while(choice>0 && this_bits>avg_target_bits &&
|
||||
bm->avg_reservoir+(this_bits-avg_target_bits)>desired_fill){
|
||||
choice--;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}else if(bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
|
||||
while(choice+1<PACKETBLOBS && this_bits<avg_target_bits &&
|
||||
bm->avg_reservoir+(this_bits-avg_target_bits)<desired_fill){
|
||||
choice++;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
|
||||
slew=rint(choice-bm->avgfloat)/samples*vi->rate;
|
||||
if(slew<-slewlimit)slew=-slewlimit;
|
||||
if(slew>slewlimit)slew=slewlimit;
|
||||
choice=rint(bm->avgfloat+= slew/vi->rate*samples);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* enforce min(if used) on the current floater (if used) */
|
||||
if(bm->min_bitsper>0){
|
||||
/* do we need to force the bitrate up? */
|
||||
if(this_bits<min_target_bits){
|
||||
while(bm->minmax_reservoir-(min_target_bits-this_bits)<0){
|
||||
choice++;
|
||||
if(choice>=PACKETBLOBS)break;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* enforce max (if used) on the current floater (if used) */
|
||||
if(bm->max_bitsper>0){
|
||||
/* do we need to force the bitrate down? */
|
||||
if(this_bits>max_target_bits){
|
||||
while(bm->minmax_reservoir+(this_bits-max_target_bits)>bi->reservoir_bits){
|
||||
choice--;
|
||||
if(choice<0)break;
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Choice of packetblobs now made based on floater, and min/max
|
||||
requirements. Now boundary check extreme choices */
|
||||
|
||||
if(choice<0){
|
||||
/* choosing a smaller packetblob is insufficient to trim bitrate.
|
||||
frame will need to be truncated */
|
||||
long maxsize=(max_target_bits+(bi->reservoir_bits-bm->minmax_reservoir))/8;
|
||||
bm->choice=choice=0;
|
||||
|
||||
if(oggpack_bytes(vbi->packetblob[choice])>maxsize){
|
||||
|
||||
oggpack_writetrunc(vbi->packetblob[choice],maxsize*8);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
}
|
||||
}else{
|
||||
long minsize=(min_target_bits-bm->minmax_reservoir+7)/8;
|
||||
if(choice>=PACKETBLOBS)
|
||||
choice=PACKETBLOBS-1;
|
||||
|
||||
bm->choice=choice;
|
||||
|
||||
/* prop up bitrate according to demand. pad this frame out with zeroes */
|
||||
minsize-=oggpack_bytes(vbi->packetblob[choice]);
|
||||
while(minsize-->0)oggpack_write(vbi->packetblob[choice],0,8);
|
||||
this_bits=oggpack_bytes(vbi->packetblob[choice])*8;
|
||||
|
||||
}
|
||||
|
||||
/* now we have the final packet and the final packet size. Update statistics */
|
||||
/* min and max reservoir */
|
||||
if(bm->min_bitsper>0 || bm->max_bitsper>0){
|
||||
|
||||
if(max_target_bits>0 && this_bits>max_target_bits){
|
||||
bm->minmax_reservoir+=(this_bits-max_target_bits);
|
||||
}else if(min_target_bits>0 && this_bits<min_target_bits){
|
||||
bm->minmax_reservoir+=(this_bits-min_target_bits);
|
||||
}else{
|
||||
/* inbetween; we want to take reservoir toward but not past desired_fill */
|
||||
if(bm->minmax_reservoir>desired_fill){
|
||||
if(max_target_bits>0){ /* logical bulletproofing against initialization state */
|
||||
bm->minmax_reservoir+=(this_bits-max_target_bits);
|
||||
if(bm->minmax_reservoir<desired_fill)bm->minmax_reservoir=desired_fill;
|
||||
}else{
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
}
|
||||
}else{
|
||||
if(min_target_bits>0){ /* logical bulletproofing against initialization state */
|
||||
bm->minmax_reservoir+=(this_bits-min_target_bits);
|
||||
if(bm->minmax_reservoir>desired_fill)bm->minmax_reservoir=desired_fill;
|
||||
}else{
|
||||
bm->minmax_reservoir=desired_fill;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* avg reservoir */
|
||||
if(bm->avg_bitsper>0){
|
||||
long avg_target_bits=(vb->W?bm->avg_bitsper*bm->short_per_long:bm->avg_bitsper);
|
||||
bm->avg_reservoir+=this_bits-avg_target_bits;
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_bitrate_flushpacket(vorbis_dsp_state *vd,ogg_packet *op){
|
||||
private_state *b=(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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: bitrate tracking and management
|
||||
last mod: $Id: bitrate.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,983 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2003 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data vector blocking, windowing and dis/reassembly
|
||||
last mod: $Id: block.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
Handle windowing, overlap-add, etc of the PCM vectors. This is made
|
||||
more amusing by Vorbis' current two allowed block sizes.
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "../../ogg.h"
|
||||
#include "../../codec.h"
|
||||
#include "codec_internal.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "mdct.h"
|
||||
#include "lpc.h"
|
||||
#include "registry.h"
|
||||
#include "misc.h"
|
||||
|
||||
/* pcm accumulator examples (not exhaustive):
|
||||
|
||||
<-------------- lW ---------------->
|
||||
<--------------- W ---------------->
|
||||
: .....|..... _______________ |
|
||||
: .''' | '''_--- | |\ |
|
||||
:.....''' |_____--- '''......| | \_______|
|
||||
:.................|__________________|_______|__|______|
|
||||
|<------ Sl ------>| > Sr < |endW
|
||||
|beginSl |endSl | |endSr
|
||||
|beginW |endlW |beginSr
|
||||
|
||||
|
||||
|< lW >|
|
||||
<--------------- W ---------------->
|
||||
| | .. ______________ |
|
||||
| | ' `/ | ---_ |
|
||||
|___.'___/`. | ---_____|
|
||||
|_______|__|_______|_________________|
|
||||
| >|Sl|< |<------ Sr ----->|endW
|
||||
| | |endSl |beginSr |endSr
|
||||
|beginW | |endlW
|
||||
mult[0] |beginSl mult[n]
|
||||
|
||||
<-------------- lW ----------------->
|
||||
|<--W-->|
|
||||
: .............. ___ | |
|
||||
: .''' |`/ \ | |
|
||||
:.....''' |/`....\|...|
|
||||
:.........................|___|___|___|
|
||||
|Sl |Sr |endW
|
||||
| | |endSr
|
||||
| |beginSr
|
||||
| |endSl
|
||||
|beginSl
|
||||
|beginW
|
||||
*/
|
||||
|
||||
/* block abstraction setup *********************************************/
|
||||
|
||||
#ifndef WORD_ALIGN
|
||||
#define WORD_ALIGN 8
|
||||
#endif
|
||||
|
||||
int vorbis_block_init(vorbis_dsp_state *v, vorbis_block *vb){
|
||||
int i;
|
||||
memset(vb,0,sizeof(*vb));
|
||||
vb->vd=v;
|
||||
vb->localalloc=0;
|
||||
vb->localstore=NULL;
|
||||
if(v->analysisp){
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal*)
|
||||
(vb->internal=(vorbis_block_internal*)_ogg_calloc(1,sizeof(vorbis_block_internal)));
|
||||
vbi->ampmax=-9999;
|
||||
|
||||
for(i=0;i<PACKETBLOBS;i++){
|
||||
if(i==PACKETBLOBS/2){
|
||||
vbi->packetblob[i]=&vb->opb;
|
||||
}else{
|
||||
vbi->packetblob[i]=
|
||||
(oggpack_buffer*) _ogg_calloc(1,sizeof(oggpack_buffer));
|
||||
}
|
||||
oggpack_writeinit(vbi->packetblob[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void *_vorbis_block_alloc(vorbis_block *vb,long bytes){
|
||||
bytes=(bytes+(WORD_ALIGN-1)) & ~(WORD_ALIGN-1);
|
||||
if(bytes+vb->localtop>vb->localalloc){
|
||||
/* can't just _ogg_realloc... there are outstanding pointers */
|
||||
if(vb->localstore){
|
||||
struct alloc_chain *link=(struct alloc_chain*)_ogg_malloc(sizeof(*link));
|
||||
vb->totaluse+=vb->localtop;
|
||||
link->next=vb->reap;
|
||||
link->ptr=vb->localstore;
|
||||
vb->reap=link;
|
||||
}
|
||||
/* highly conservative */
|
||||
vb->localalloc=bytes;
|
||||
vb->localstore=_ogg_malloc(vb->localalloc);
|
||||
vb->localtop=0;
|
||||
}
|
||||
{
|
||||
void *ret=(void *)(((char *)vb->localstore)+vb->localtop);
|
||||
vb->localtop+=bytes;
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* reap the chain, pull the ripcord */
|
||||
void _vorbis_block_ripcord(vorbis_block *vb){
|
||||
/* reap the chain */
|
||||
struct alloc_chain *reap=vb->reap;
|
||||
while(reap){
|
||||
struct alloc_chain *next=reap->next;
|
||||
_ogg_free(reap->ptr);
|
||||
memset(reap,0,sizeof(*reap));
|
||||
_ogg_free(reap);
|
||||
reap=next;
|
||||
}
|
||||
/* consolidate storage */
|
||||
if(vb->totaluse){
|
||||
vb->localstore=_ogg_realloc(vb->localstore,vb->totaluse+vb->localalloc);
|
||||
vb->localalloc+=vb->totaluse;
|
||||
vb->totaluse=0;
|
||||
}
|
||||
|
||||
/* pull the ripcord */
|
||||
vb->localtop=0;
|
||||
vb->reap=NULL;
|
||||
}
|
||||
|
||||
int vorbis_block_clear(vorbis_block *vb){
|
||||
int i;
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal*)vb->internal;
|
||||
|
||||
_vorbis_block_ripcord(vb);
|
||||
if(vb->localstore)_ogg_free(vb->localstore);
|
||||
|
||||
if(vbi){
|
||||
for(i=0;i<PACKETBLOBS;i++){
|
||||
oggpack_writeclear(vbi->packetblob[i]);
|
||||
if(i!=PACKETBLOBS/2)_ogg_free(vbi->packetblob[i]);
|
||||
}
|
||||
_ogg_free(vbi);
|
||||
}
|
||||
memset(vb,0,sizeof(*vb));
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* Analysis side code, but directly related to blocking. Thus it's
|
||||
here and not in analysis.c (which is for analysis transforms only).
|
||||
The init is here because some of it is shared */
|
||||
|
||||
static int _vds_shared_init(vorbis_dsp_state *v,vorbis_info *vi,int encp){
|
||||
int i;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
private_state *b=NULL;
|
||||
int hs;
|
||||
|
||||
if(ci==NULL) return 1;
|
||||
hs=ci->halfrate_flag;
|
||||
|
||||
memset(v,0,sizeof(*v));
|
||||
b=(private_state*) (v->backend_state=(private_state*)_ogg_calloc(1,sizeof(*b)));
|
||||
|
||||
v->vi=vi;
|
||||
b->modebits=ilog2(ci->modes);
|
||||
|
||||
b->transform[0]=(vorbis_look_transform**)_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[0]));
|
||||
b->transform[1]=(vorbis_look_transform**)_ogg_calloc(VI_TRANSFORMB,sizeof(*b->transform[1]));
|
||||
|
||||
/* MDCT is tranform 0 */
|
||||
|
||||
b->transform[0][0]=_ogg_calloc(1,sizeof(mdct_lookup));
|
||||
b->transform[1][0]=_ogg_calloc(1,sizeof(mdct_lookup));
|
||||
mdct_init((mdct_lookup*)b->transform[0][0],ci->blocksizes[0]>>hs);
|
||||
mdct_init((mdct_lookup*)b->transform[1][0],ci->blocksizes[1]>>hs);
|
||||
|
||||
/* Vorbis I uses only window type 0 */
|
||||
b->window[0]=ilog2(ci->blocksizes[0])-6;
|
||||
b->window[1]=ilog2(ci->blocksizes[1])-6;
|
||||
|
||||
if(encp){ /* encode/decode differ here */
|
||||
|
||||
/* analysis always needs an fft */
|
||||
drft_init(&b->fft_look[0],ci->blocksizes[0]);
|
||||
drft_init(&b->fft_look[1],ci->blocksizes[1]);
|
||||
|
||||
/* finish the codebooks */
|
||||
if(!ci->fullbooks){
|
||||
ci->fullbooks=(codebook*) _ogg_calloc(ci->books,sizeof(*ci->fullbooks));
|
||||
for(i=0;i<ci->books;i++)
|
||||
vorbis_book_init_encode(ci->fullbooks+i,ci->book_param[i]);
|
||||
}
|
||||
|
||||
b->psy=(vorbis_look_psy*)_ogg_calloc(ci->psys,sizeof(*b->psy));
|
||||
for(i=0;i<ci->psys;i++){
|
||||
_vp_psy_init(b->psy+i,
|
||||
ci->psy_param[i],
|
||||
&ci->psy_g_param,
|
||||
ci->blocksizes[ci->psy_param[i]->blockflag]/2,
|
||||
vi->rate);
|
||||
}
|
||||
|
||||
v->analysisp=1;
|
||||
}else{
|
||||
/* finish the codebooks */
|
||||
if(!ci->fullbooks){
|
||||
ci->fullbooks=(codebook*) _ogg_calloc(ci->books,sizeof(*ci->fullbooks));
|
||||
for(i=0;i<ci->books;i++){
|
||||
vorbis_book_init_decode(ci->fullbooks+i,ci->book_param[i]);
|
||||
/* decode codebooks are now standalone after init */
|
||||
vorbis_staticbook_destroy(ci->book_param[i]);
|
||||
ci->book_param[i]=NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* initialize the storage vectors. blocksize[1] is small for encode,
|
||||
but the correct size for decode */
|
||||
v->pcm_storage=ci->blocksizes[1];
|
||||
v->pcm=(float**)_ogg_malloc(vi->channels*sizeof(*v->pcm));
|
||||
v->pcmret=(float**)_ogg_malloc(vi->channels*sizeof(*v->pcmret));
|
||||
{
|
||||
int i;
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcm[i]=(float*)_ogg_calloc(v->pcm_storage,sizeof(*v->pcm[i]));
|
||||
}
|
||||
|
||||
/* all 1 (large block) or 0 (small block) */
|
||||
/* explicitly set for the sake of clarity */
|
||||
v->lW=0; /* previous window size */
|
||||
v->W=0; /* current window size */
|
||||
|
||||
/* all vector indexes */
|
||||
v->centerW=ci->blocksizes[1]/2;
|
||||
|
||||
v->pcm_current=v->centerW;
|
||||
|
||||
/* initialize all the backend lookups */
|
||||
b->flr=(vorbis_look_floor**)_ogg_calloc(ci->floors,sizeof(*b->flr));
|
||||
b->residue=(vorbis_look_residue**)_ogg_calloc(ci->residues,sizeof(*b->residue));
|
||||
|
||||
for(i=0;i<ci->floors;i++)
|
||||
b->flr[i]=_floor_P[ci->floor_type[i]]->
|
||||
look(v,ci->floor_param[i]);
|
||||
|
||||
for(i=0;i<ci->residues;i++)
|
||||
b->residue[i]=_residue_P[ci->residue_type[i]]->
|
||||
look(v,ci->residue_param[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* arbitrary settings and spec-mandated numbers get filled in here */
|
||||
int vorbis_analysis_init(vorbis_dsp_state *v,vorbis_info *vi){
|
||||
private_state *b=NULL;
|
||||
|
||||
if(_vds_shared_init(v,vi,1))return 1;
|
||||
b=(private_state*)v->backend_state;
|
||||
b->psy_g_look=_vp_global_look(vi);
|
||||
|
||||
/* Initialize the envelope state storage */
|
||||
b->ve=(envelope_lookup*)_ogg_calloc(1,sizeof(*b->ve));
|
||||
_ve_envelope_init(b->ve,vi);
|
||||
|
||||
vorbis_bitrate_init(vi,&b->bms);
|
||||
|
||||
/* compressed audio packets start after the headers
|
||||
with sequence number 3 */
|
||||
v->sequence=3;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
void vorbis_dsp_clear(vorbis_dsp_state *v){
|
||||
int i;
|
||||
if(v){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)(vi?vi->codec_setup:NULL);
|
||||
private_state *b=(private_state*)v->backend_state;
|
||||
|
||||
if(b){
|
||||
|
||||
if(b->ve){
|
||||
_ve_envelope_clear(b->ve);
|
||||
_ogg_free(b->ve);
|
||||
}
|
||||
|
||||
if(b->transform[0]){
|
||||
mdct_clear((mdct_lookup*) b->transform[0][0]);
|
||||
_ogg_free(b->transform[0][0]);
|
||||
_ogg_free(b->transform[0]);
|
||||
}
|
||||
if(b->transform[1]){
|
||||
mdct_clear((mdct_lookup*) b->transform[1][0]);
|
||||
_ogg_free(b->transform[1][0]);
|
||||
_ogg_free(b->transform[1]);
|
||||
}
|
||||
|
||||
if(b->flr){
|
||||
for(i=0;i<ci->floors;i++)
|
||||
_floor_P[ci->floor_type[i]]->
|
||||
free_look(b->flr[i]);
|
||||
_ogg_free(b->flr);
|
||||
}
|
||||
if(b->residue){
|
||||
for(i=0;i<ci->residues;i++)
|
||||
_residue_P[ci->residue_type[i]]->
|
||||
free_look(b->residue[i]);
|
||||
_ogg_free(b->residue);
|
||||
}
|
||||
if(b->psy){
|
||||
for(i=0;i<ci->psys;i++)
|
||||
_vp_psy_clear(b->psy+i);
|
||||
_ogg_free(b->psy);
|
||||
}
|
||||
|
||||
if(b->psy_g_look)_vp_global_free(b->psy_g_look);
|
||||
vorbis_bitrate_clear(&b->bms);
|
||||
|
||||
drft_clear(&b->fft_look[0]);
|
||||
drft_clear(&b->fft_look[1]);
|
||||
|
||||
}
|
||||
|
||||
if(v->pcm){
|
||||
for(i=0;i<vi->channels;i++)
|
||||
if(v->pcm[i])_ogg_free(v->pcm[i]);
|
||||
_ogg_free(v->pcm);
|
||||
if(v->pcmret)_ogg_free(v->pcmret);
|
||||
}
|
||||
|
||||
if(b){
|
||||
/* free header, header1, header2 */
|
||||
if(b->header)_ogg_free(b->header);
|
||||
if(b->header1)_ogg_free(b->header1);
|
||||
if(b->header2)_ogg_free(b->header2);
|
||||
_ogg_free(b);
|
||||
}
|
||||
|
||||
memset(v,0,sizeof(*v));
|
||||
}
|
||||
}
|
||||
|
||||
float **vorbis_analysis_buffer(vorbis_dsp_state *v, int vals){
|
||||
int i;
|
||||
vorbis_info *vi=v->vi;
|
||||
private_state *b=(private_state*)v->backend_state;
|
||||
|
||||
/* free header, header1, header2 */
|
||||
if(b->header)_ogg_free(b->header);b->header=NULL;
|
||||
if(b->header1)_ogg_free(b->header1);b->header1=NULL;
|
||||
if(b->header2)_ogg_free(b->header2);b->header2=NULL;
|
||||
|
||||
/* Do we have enough storage space for the requested buffer? If not,
|
||||
expand the PCM (and envelope) storage */
|
||||
|
||||
if(v->pcm_current+vals>=v->pcm_storage){
|
||||
v->pcm_storage=v->pcm_current+vals*2;
|
||||
|
||||
for(i=0;i<vi->channels;i++){
|
||||
v->pcm[i]=(float*)_ogg_realloc(v->pcm[i],v->pcm_storage*sizeof(*v->pcm[i]));
|
||||
}
|
||||
}
|
||||
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcmret[i]=v->pcm[i]+v->pcm_current;
|
||||
|
||||
return(v->pcmret);
|
||||
}
|
||||
|
||||
static void _preextrapolate_helper(vorbis_dsp_state *v){
|
||||
int i;
|
||||
int order=32;
|
||||
float *lpc=(float*)alloca(order*sizeof(*lpc));
|
||||
float *work=(float*)alloca(v->pcm_current*sizeof(*work));
|
||||
long j;
|
||||
v->preextrapolate=1;
|
||||
|
||||
if(v->pcm_current-v->centerW>order*2){ /* safety */
|
||||
for(i=0;i<v->vi->channels;i++){
|
||||
/* need to run the extrapolation in reverse! */
|
||||
for(j=0;j<v->pcm_current;j++)
|
||||
work[j]=v->pcm[i][v->pcm_current-j-1];
|
||||
|
||||
/* prime as above */
|
||||
vorbis_lpc_from_data(work,lpc,v->pcm_current-v->centerW,order);
|
||||
|
||||
/* run the predictor filter */
|
||||
vorbis_lpc_predict(lpc,work+v->pcm_current-v->centerW-order,
|
||||
order,
|
||||
work+v->pcm_current-v->centerW,
|
||||
v->centerW);
|
||||
|
||||
for(j=0;j<v->pcm_current;j++)
|
||||
v->pcm[i][v->pcm_current-j-1]=work[j];
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* call with val<=0 to set eof */
|
||||
|
||||
int vorbis_analysis_wrote(vorbis_dsp_state *v, int vals){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
|
||||
if(vals<=0){
|
||||
int order=32;
|
||||
int i;
|
||||
float *lpc=(float*) alloca(order*sizeof(*lpc));
|
||||
|
||||
/* if it wasn't done earlier (very short sample) */
|
||||
if(!v->preextrapolate)
|
||||
_preextrapolate_helper(v);
|
||||
|
||||
/* We're encoding the end of the stream. Just make sure we have
|
||||
[at least] a few full blocks of zeroes at the end. */
|
||||
/* actually, we don't want zeroes; that could drop a large
|
||||
amplitude off a cliff, creating spread spectrum noise that will
|
||||
suck to encode. Extrapolate for the sake of cleanliness. */
|
||||
|
||||
vorbis_analysis_buffer(v,ci->blocksizes[1]*3);
|
||||
v->eofflag=v->pcm_current;
|
||||
v->pcm_current+=ci->blocksizes[1]*3;
|
||||
|
||||
for(i=0;i<vi->channels;i++){
|
||||
if(v->eofflag>order*2){
|
||||
/* extrapolate with LPC to fill in */
|
||||
long n;
|
||||
|
||||
/* make a predictor filter */
|
||||
n=v->eofflag;
|
||||
if(n>ci->blocksizes[1])n=ci->blocksizes[1];
|
||||
vorbis_lpc_from_data(v->pcm[i]+v->eofflag-n,lpc,n,order);
|
||||
|
||||
/* run the predictor filter */
|
||||
vorbis_lpc_predict(lpc,v->pcm[i]+v->eofflag-order,order,
|
||||
v->pcm[i]+v->eofflag,v->pcm_current-v->eofflag);
|
||||
}else{
|
||||
/* not enough data to extrapolate (unlikely to happen due to
|
||||
guarding the overlap, but bulletproof in case that
|
||||
assumtion goes away). zeroes will do. */
|
||||
memset(v->pcm[i]+v->eofflag,0,
|
||||
(v->pcm_current-v->eofflag)*sizeof(*v->pcm[i]));
|
||||
|
||||
}
|
||||
}
|
||||
}else{
|
||||
|
||||
if(v->pcm_current+vals>v->pcm_storage)
|
||||
return(OV_EINVAL);
|
||||
|
||||
v->pcm_current+=vals;
|
||||
|
||||
/* we may want to reverse extrapolate the beginning of a stream
|
||||
too... in case we're beginning on a cliff! */
|
||||
/* clumsy, but simple. It only runs once, so simple is good. */
|
||||
if(!v->preextrapolate && v->pcm_current-v->centerW>ci->blocksizes[1])
|
||||
_preextrapolate_helper(v);
|
||||
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* do the deltas, envelope shaping, pre-echo and determine the size of
|
||||
the next block on which to continue analysis */
|
||||
int vorbis_analysis_blockout(vorbis_dsp_state *v,vorbis_block *vb){
|
||||
int i;
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
private_state *b=(private_state*)v->backend_state;
|
||||
vorbis_look_psy_global *g=b->psy_g_look;
|
||||
long beginW=v->centerW-ci->blocksizes[v->W]/2,centerNext;
|
||||
vorbis_block_internal *vbi=(vorbis_block_internal *)vb->internal;
|
||||
|
||||
/* check to see if we're started... */
|
||||
if(!v->preextrapolate)return(0);
|
||||
|
||||
/* check to see if we're done... */
|
||||
if(v->eofflag==-1)return(0);
|
||||
|
||||
/* By our invariant, we have lW, W and centerW set. Search for
|
||||
the next boundary so we can determine nW (the next window size)
|
||||
which lets us compute the shape of the current block's window */
|
||||
|
||||
/* we do an envelope search even on a single blocksize; we may still
|
||||
be throwing more bits at impulses, and envelope search handles
|
||||
marking impulses too. */
|
||||
{
|
||||
long bp=_ve_envelope_search(v);
|
||||
if(bp==-1){
|
||||
|
||||
if(v->eofflag==0)return(0); /* not enough data currently to search for a
|
||||
full long block */
|
||||
v->nW=0;
|
||||
}else{
|
||||
|
||||
if(ci->blocksizes[0]==ci->blocksizes[1])
|
||||
v->nW=0;
|
||||
else
|
||||
v->nW=bp;
|
||||
}
|
||||
}
|
||||
|
||||
centerNext=v->centerW+ci->blocksizes[v->W]/4+ci->blocksizes[v->nW]/4;
|
||||
|
||||
{
|
||||
/* center of next block + next block maximum right side. */
|
||||
|
||||
long blockbound=centerNext+ci->blocksizes[v->nW]/2;
|
||||
if(v->pcm_current<blockbound)return(0); /* not enough data yet;
|
||||
although this check is
|
||||
less strict that the
|
||||
_ve_envelope_search,
|
||||
the search is not run
|
||||
if we only use one
|
||||
block size */
|
||||
|
||||
|
||||
}
|
||||
|
||||
/* fill in the block. Note that for a short window, lW and nW are *short*
|
||||
regardless of actual settings in the stream */
|
||||
|
||||
_vorbis_block_ripcord(vb);
|
||||
vb->lW=v->lW;
|
||||
vb->W=v->W;
|
||||
vb->nW=v->nW;
|
||||
|
||||
if(v->W){
|
||||
if(!v->lW || !v->nW){
|
||||
vbi->blocktype=BLOCKTYPE_TRANSITION;
|
||||
/*fprintf(stderr,"-");*/
|
||||
}else{
|
||||
vbi->blocktype=BLOCKTYPE_LONG;
|
||||
/*fprintf(stderr,"_");*/
|
||||
}
|
||||
}else{
|
||||
if(_ve_envelope_mark(v)){
|
||||
vbi->blocktype=BLOCKTYPE_IMPULSE;
|
||||
/*fprintf(stderr,"|");*/
|
||||
|
||||
}else{
|
||||
vbi->blocktype=BLOCKTYPE_PADDING;
|
||||
/*fprintf(stderr,".");*/
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
vb->vd=v;
|
||||
vb->sequence=v->sequence++;
|
||||
vb->granulepos=v->granulepos;
|
||||
vb->pcmend=ci->blocksizes[v->W];
|
||||
|
||||
/* copy the vectors; this uses the local storage in vb */
|
||||
|
||||
/* this tracks 'strongest peak' for later psychoacoustics */
|
||||
/* moved to the global psy state; clean this mess up */
|
||||
if(vbi->ampmax>g->ampmax)g->ampmax=vbi->ampmax;
|
||||
g->ampmax=_vp_ampmax_decay(g->ampmax,v);
|
||||
vbi->ampmax=g->ampmax;
|
||||
|
||||
vb->pcm=(float**)_vorbis_block_alloc(vb,sizeof(*vb->pcm)*vi->channels);
|
||||
vbi->pcmdelay=(float**)_vorbis_block_alloc(vb,sizeof(*vbi->pcmdelay)*vi->channels);
|
||||
for(i=0;i<vi->channels;i++){
|
||||
vbi->pcmdelay[i]=
|
||||
(float*) _vorbis_block_alloc(vb,(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
|
||||
memcpy(vbi->pcmdelay[i],v->pcm[i],(vb->pcmend+beginW)*sizeof(*vbi->pcmdelay[i]));
|
||||
vb->pcm[i]=vbi->pcmdelay[i]+beginW;
|
||||
|
||||
/* before we added the delay
|
||||
vb->pcm[i]=_vorbis_block_alloc(vb,vb->pcmend*sizeof(*vb->pcm[i]));
|
||||
memcpy(vb->pcm[i],v->pcm[i]+beginW,ci->blocksizes[v->W]*sizeof(*vb->pcm[i]));
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/* handle eof detection: eof==0 means that we've not yet received EOF
|
||||
eof>0 marks the last 'real' sample in pcm[]
|
||||
eof<0 'no more to do'; doesn't get here */
|
||||
|
||||
if(v->eofflag){
|
||||
if(v->centerW>=v->eofflag){
|
||||
v->eofflag=-1;
|
||||
vb->eofflag=1;
|
||||
return(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* advance storage vectors and clean up */
|
||||
{
|
||||
int new_centerNext=ci->blocksizes[1]/2;
|
||||
int movementW=centerNext-new_centerNext;
|
||||
|
||||
if(movementW>0){
|
||||
|
||||
_ve_envelope_shift(b->ve,movementW);
|
||||
v->pcm_current-=movementW;
|
||||
|
||||
for(i=0;i<vi->channels;i++)
|
||||
memmove(v->pcm[i],v->pcm[i]+movementW,
|
||||
v->pcm_current*sizeof(*v->pcm[i]));
|
||||
|
||||
|
||||
v->lW=v->W;
|
||||
v->W=v->nW;
|
||||
v->centerW=new_centerNext;
|
||||
|
||||
if(v->eofflag){
|
||||
v->eofflag-=movementW;
|
||||
if(v->eofflag<=0)v->eofflag=-1;
|
||||
/* do not add padding to end of stream! */
|
||||
if(v->centerW>=v->eofflag){
|
||||
v->granulepos+=movementW-(v->centerW-v->eofflag);
|
||||
}else{
|
||||
v->granulepos+=movementW;
|
||||
}
|
||||
}else{
|
||||
v->granulepos+=movementW;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* done */
|
||||
return(1);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_restart(vorbis_dsp_state *v){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci;
|
||||
int hs;
|
||||
|
||||
if(!v->backend_state)return -1;
|
||||
if(!vi)return -1;
|
||||
ci=(codec_setup_info*) vi->codec_setup;
|
||||
if(!ci)return -1;
|
||||
hs=ci->halfrate_flag;
|
||||
|
||||
v->centerW=ci->blocksizes[1]>>(hs+1);
|
||||
v->pcm_current=v->centerW>>hs;
|
||||
|
||||
v->pcm_returned=-1;
|
||||
v->granulepos=-1;
|
||||
v->sequence=-1;
|
||||
v->eofflag=0;
|
||||
((private_state *)(v->backend_state))->sample_count=-1;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_init(vorbis_dsp_state *v,vorbis_info *vi){
|
||||
if(_vds_shared_init(v,vi,0)) return 1;
|
||||
vorbis_synthesis_restart(v);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Unlike in analysis, the window is only partially applied for each
|
||||
block. The time domain envelope is not yet handled at the point of
|
||||
calling (as it relies on the previous block). */
|
||||
|
||||
int vorbis_synthesis_blockin(vorbis_dsp_state *v,vorbis_block *vb){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*)vi->codec_setup;
|
||||
private_state *b=(private_state*)v->backend_state;
|
||||
int hs=ci->halfrate_flag;
|
||||
int i,j;
|
||||
|
||||
if(!vb)return(OV_EINVAL);
|
||||
if(v->pcm_current>v->pcm_returned && v->pcm_returned!=-1)return(OV_EINVAL);
|
||||
|
||||
v->lW=v->W;
|
||||
v->W=vb->W;
|
||||
v->nW=-1;
|
||||
|
||||
if((v->sequence==-1)||
|
||||
(v->sequence+1 != vb->sequence)){
|
||||
v->granulepos=-1; /* out of sequence; lose count */
|
||||
b->sample_count=-1;
|
||||
}
|
||||
|
||||
v->sequence=vb->sequence;
|
||||
|
||||
if(vb->pcm){ /* no pcm to process if vorbis_synthesis_trackonly
|
||||
was called on block */
|
||||
int n=ci->blocksizes[v->W]>>(hs+1);
|
||||
int n0=ci->blocksizes[0]>>(hs+1);
|
||||
int n1=ci->blocksizes[1]>>(hs+1);
|
||||
|
||||
int thisCenter;
|
||||
int prevCenter;
|
||||
|
||||
v->glue_bits+=vb->glue_bits;
|
||||
v->time_bits+=vb->time_bits;
|
||||
v->floor_bits+=vb->floor_bits;
|
||||
v->res_bits+=vb->res_bits;
|
||||
|
||||
if(v->centerW){
|
||||
thisCenter=n1;
|
||||
prevCenter=0;
|
||||
}else{
|
||||
thisCenter=0;
|
||||
prevCenter=n1;
|
||||
}
|
||||
|
||||
/* v->pcm is now used like a two-stage double buffer. We don't want
|
||||
to have to constantly shift *or* adjust memory usage. Don't
|
||||
accept a new block until the old is shifted out */
|
||||
|
||||
for(j=0;j<vi->channels;j++){
|
||||
/* the overlap/add section */
|
||||
if(v->lW){
|
||||
if(v->W){
|
||||
/* large/large */
|
||||
float *w=_vorbis_window_get(b->window[1]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter;
|
||||
float *p=vb->pcm[j];
|
||||
for(i=0;i<n1;i++)
|
||||
pcm[i]=pcm[i]*w[n1-i-1] + p[i]*w[i];
|
||||
}else{
|
||||
/* large/small */
|
||||
float *w=_vorbis_window_get(b->window[0]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter+n1/2-n0/2;
|
||||
float *p=vb->pcm[j];
|
||||
for(i=0;i<n0;i++)
|
||||
pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
|
||||
}
|
||||
}else{
|
||||
if(v->W){
|
||||
/* small/large */
|
||||
float *w=_vorbis_window_get(b->window[0]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter;
|
||||
float *p=vb->pcm[j]+n1/2-n0/2;
|
||||
for(i=0;i<n0;i++)
|
||||
pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
|
||||
for(;i<n1/2+n0/2;i++)
|
||||
pcm[i]=p[i];
|
||||
}else{
|
||||
/* small/small */
|
||||
float *w=_vorbis_window_get(b->window[0]-hs);
|
||||
float *pcm=v->pcm[j]+prevCenter;
|
||||
float *p=vb->pcm[j];
|
||||
for(i=0;i<n0;i++)
|
||||
pcm[i]=pcm[i]*w[n0-i-1] +p[i]*w[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* the copy section */
|
||||
{
|
||||
float *pcm=v->pcm[j]+thisCenter;
|
||||
float *p=vb->pcm[j]+n;
|
||||
for(i=0;i<n;i++)
|
||||
pcm[i]=p[i];
|
||||
}
|
||||
}
|
||||
|
||||
if(v->centerW)
|
||||
v->centerW=0;
|
||||
else
|
||||
v->centerW=n1;
|
||||
|
||||
/* deal with initial packet state; we do this using the explicit
|
||||
pcm_returned==-1 flag otherwise we're sensitive to first block
|
||||
being short or long */
|
||||
|
||||
if(v->pcm_returned==-1){
|
||||
v->pcm_returned=thisCenter;
|
||||
v->pcm_current=thisCenter;
|
||||
}else{
|
||||
v->pcm_returned=prevCenter;
|
||||
v->pcm_current=prevCenter+
|
||||
((ci->blocksizes[v->lW]/4+
|
||||
ci->blocksizes[v->W]/4)>>hs);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* track the frame number... This is for convenience, but also
|
||||
making sure our last packet doesn't end with added padding. If
|
||||
the last packet is partial, the number of samples we'll have to
|
||||
return will be past the vb->granulepos.
|
||||
|
||||
This is not foolproof! It will be confused if we begin
|
||||
decoding at the last page after a seek or hole. In that case,
|
||||
we don't have a starting point to judge where the last frame
|
||||
is. For this reason, vorbisfile will always try to make sure
|
||||
it reads the last two marked pages in proper sequence */
|
||||
|
||||
if(b->sample_count==-1){
|
||||
b->sample_count=0;
|
||||
}else{
|
||||
b->sample_count+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
|
||||
}
|
||||
|
||||
if(v->granulepos==-1){
|
||||
if(vb->granulepos!=-1){ /* only set if we have a position to set to */
|
||||
|
||||
v->granulepos=vb->granulepos;
|
||||
|
||||
/* is this a short page? */
|
||||
if(b->sample_count>v->granulepos){
|
||||
/* corner case; if this is both the first and last audio page,
|
||||
then spec says the end is cut, not beginning */
|
||||
if(vb->eofflag){
|
||||
/* trim the end */
|
||||
/* no preceeding granulepos; assume we started at zero (we'd
|
||||
have to in a short single-page stream) */
|
||||
/* granulepos could be -1 due to a seek, but that would result
|
||||
in a long count, not short count */
|
||||
|
||||
v->pcm_current-=(b->sample_count-v->granulepos)>>hs;
|
||||
}else{
|
||||
/* trim the beginning */
|
||||
v->pcm_returned+=(b->sample_count-v->granulepos)>>hs;
|
||||
if(v->pcm_returned>v->pcm_current)
|
||||
v->pcm_returned=v->pcm_current;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}else{
|
||||
v->granulepos+=ci->blocksizes[v->lW]/4+ci->blocksizes[v->W]/4;
|
||||
if(vb->granulepos!=-1 && v->granulepos!=vb->granulepos){
|
||||
|
||||
if(v->granulepos>vb->granulepos){
|
||||
long extra=v->granulepos-vb->granulepos;
|
||||
|
||||
if(extra)
|
||||
if(vb->eofflag){
|
||||
/* partial last frame. Strip the extra samples off */
|
||||
v->pcm_current-=extra>>hs;
|
||||
} /* else {Shouldn't happen *unless* the bitstream is out of
|
||||
spec. Either way, believe the bitstream } */
|
||||
} /* else {Shouldn't happen *unless* the bitstream is out of
|
||||
spec. Either way, believe the bitstream } */
|
||||
v->granulepos=vb->granulepos;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update, cleanup */
|
||||
|
||||
if(vb->eofflag)v->eofflag=1;
|
||||
return(0);
|
||||
|
||||
}
|
||||
|
||||
/* pcm==NULL indicates we just want the pending samples, no more */
|
||||
int vorbis_synthesis_pcmout(vorbis_dsp_state *v,float ***pcm){
|
||||
vorbis_info *vi=v->vi;
|
||||
|
||||
if(v->pcm_returned>-1 && v->pcm_returned<v->pcm_current){
|
||||
if(pcm){
|
||||
int i;
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
|
||||
*pcm=v->pcmret;
|
||||
}
|
||||
return(v->pcm_current-v->pcm_returned);
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
int vorbis_synthesis_read(vorbis_dsp_state *v,int n){
|
||||
if(n && v->pcm_returned+n>v->pcm_current)return(OV_EINVAL);
|
||||
v->pcm_returned+=n;
|
||||
return(0);
|
||||
}
|
||||
|
||||
/* intended for use with a specific vorbisfile feature; we want access
|
||||
to the [usually synthetic/postextrapolated] buffer and lapping at
|
||||
the end of a decode cycle, specifically, a half-short-block worth.
|
||||
This funtion works like pcmout above, except it will also expose
|
||||
this implicit buffer data not normally decoded. */
|
||||
int vorbis_synthesis_lapout(vorbis_dsp_state *v,float ***pcm){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info *)vi->codec_setup;
|
||||
int hs=ci->halfrate_flag;
|
||||
|
||||
int n=ci->blocksizes[v->W]>>(hs+1);
|
||||
int n0=ci->blocksizes[0]>>(hs+1);
|
||||
int n1=ci->blocksizes[1]>>(hs+1);
|
||||
int i,j;
|
||||
|
||||
if(v->pcm_returned<0)return 0;
|
||||
|
||||
/* our returned data ends at pcm_returned; because the synthesis pcm
|
||||
buffer is a two-fragment ring, that means our data block may be
|
||||
fragmented by buffering, wrapping or a short block not filling
|
||||
out a buffer. To simplify things, we unfragment if it's at all
|
||||
possibly needed. Otherwise, we'd need to call lapout more than
|
||||
once as well as hold additional dsp state. Opt for
|
||||
simplicity. */
|
||||
|
||||
/* centerW was advanced by blockin; it would be the center of the
|
||||
*next* block */
|
||||
if(v->centerW==n1){
|
||||
/* the data buffer wraps; swap the halves */
|
||||
/* slow, sure, small */
|
||||
for(j=0;j<vi->channels;j++){
|
||||
float *p=v->pcm[j];
|
||||
for(i=0;i<n1;i++){
|
||||
float temp=p[i];
|
||||
p[i]=p[i+n1];
|
||||
p[i+n1]=temp;
|
||||
}
|
||||
}
|
||||
|
||||
v->pcm_current-=n1;
|
||||
v->pcm_returned-=n1;
|
||||
v->centerW=0;
|
||||
}
|
||||
|
||||
/* solidify buffer into contiguous space */
|
||||
if((v->lW^v->W)==1){
|
||||
/* long/short or short/long */
|
||||
for(j=0;j<vi->channels;j++){
|
||||
float *s=v->pcm[j];
|
||||
float *d=v->pcm[j]+(n1-n0)/2;
|
||||
for(i=(n1+n0)/2-1;i>=0;--i)
|
||||
d[i]=s[i];
|
||||
}
|
||||
v->pcm_returned+=(n1-n0)/2;
|
||||
v->pcm_current+=(n1-n0)/2;
|
||||
}else{
|
||||
if(v->lW==0){
|
||||
/* short/short */
|
||||
for(j=0;j<vi->channels;j++){
|
||||
float *s=v->pcm[j];
|
||||
float *d=v->pcm[j]+n1-n0;
|
||||
for(i=n0-1;i>=0;--i)
|
||||
d[i]=s[i];
|
||||
}
|
||||
v->pcm_returned+=n1-n0;
|
||||
v->pcm_current+=n1-n0;
|
||||
}
|
||||
}
|
||||
|
||||
if(pcm){
|
||||
int i;
|
||||
for(i=0;i<vi->channels;i++)
|
||||
v->pcmret[i]=v->pcm[i]+v->pcm_returned;
|
||||
*pcm=v->pcmret;
|
||||
}
|
||||
|
||||
return(n1+n-v->pcm_returned);
|
||||
|
||||
}
|
||||
|
||||
float *vorbis_window(vorbis_dsp_state *v,int W){
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(codec_setup_info*) vi->codec_setup;
|
||||
int hs=ci->halfrate_flag;
|
||||
private_state *b=(private_state*)v->backend_state;
|
||||
|
||||
if(b->window[W]-1<0)return NULL;
|
||||
return _vorbis_window_get(b->window[W]-hs);
|
||||
}
|
||||
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,614 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic codebook pack/unpack/code/decode operations
|
||||
last mod: $Id: codebook.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
|
||||
#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 *************/
|
||||
int vorbis_staticbook_unpack(oggpack_buffer *opb,static_codebook *s){
|
||||
long i,j;
|
||||
memset(s,0,sizeof(*s));
|
||||
s->allocedp=1;
|
||||
|
||||
/* make sure alignment is correct */
|
||||
if(oggpack_read(opb,24)!=0x564342)goto _eofout;
|
||||
|
||||
/* first the basic parameters */
|
||||
s->dim=oggpack_read(opb,16);
|
||||
s->entries=oggpack_read(opb,24);
|
||||
if(s->entries==-1)goto _eofout;
|
||||
|
||||
/* codeword ordering.... length ordered or unordered? */
|
||||
switch((int)oggpack_read(opb,1)){
|
||||
case 0:
|
||||
/* unordered */
|
||||
s->lengthlist=(long*)_ogg_malloc(sizeof(*s->lengthlist)*s->entries);
|
||||
|
||||
/* allocated but unused entries? */
|
||||
if(oggpack_read(opb,1)){
|
||||
/* yes, unused entries */
|
||||
|
||||
for(i=0;i<s->entries;i++){
|
||||
if(oggpack_read(opb,1)){
|
||||
long num=oggpack_read(opb,5);
|
||||
if(num==-1)goto _eofout;
|
||||
s->lengthlist[i]=num+1;
|
||||
}else
|
||||
s->lengthlist[i]=0;
|
||||
}
|
||||
}else{
|
||||
/* all entries used; no tagging */
|
||||
for(i=0;i<s->entries;i++){
|
||||
long num=oggpack_read(opb,5);
|
||||
if(num==-1)goto _eofout;
|
||||
s->lengthlist[i]=num+1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
/* ordered */
|
||||
{
|
||||
long length=oggpack_read(opb,5)+1;
|
||||
s->lengthlist=(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;
|
||||
for(j=0;j<num && i<s->entries;j++,i++)
|
||||
s->lengthlist[i]=length;
|
||||
length++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
/* EOF */
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* Do we have a mapping to unpack? */
|
||||
switch((s->maptype=oggpack_read(opb,4))){
|
||||
case 0:
|
||||
/* no mapping */
|
||||
break;
|
||||
case 1: case 2:
|
||||
/* implicitly populated value mapping */
|
||||
/* explicitly populated value mapping */
|
||||
|
||||
s->q_min=oggpack_read(opb,32);
|
||||
s->q_delta=oggpack_read(opb,32);
|
||||
s->q_quant=oggpack_read(opb,4)+1;
|
||||
s->q_sequencep=oggpack_read(opb,1);
|
||||
|
||||
{
|
||||
int quantvals=0;
|
||||
switch(s->maptype){
|
||||
case 1:
|
||||
quantvals=_book_maptype1_quantvals(s);
|
||||
break;
|
||||
case 2:
|
||||
quantvals=s->entries*s->dim;
|
||||
break;
|
||||
}
|
||||
|
||||
/* quantized values */
|
||||
s->quantlist=(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(0);
|
||||
|
||||
_errout:
|
||||
_eofout:
|
||||
vorbis_staticbook_clear(s);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
/* returns the number of bits ************************************************/
|
||||
int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b){
|
||||
oggpack_write(b,book->codelist[a],book->c->lengthlist[a]);
|
||||
return(book->c->lengthlist[a]);
|
||||
}
|
||||
|
||||
/* One the encode side, our vector writers are each designed for a
|
||||
specific purpose, and the encoder is not flexible without modification:
|
||||
|
||||
The LSP vector coder uses a single stage nearest-match with no
|
||||
interleave, so no step and no error return. This is specced by floor0
|
||||
and doesn't change.
|
||||
|
||||
Residue0 encoding interleaves, uses multiple stages, and each stage
|
||||
peels of a specific amount of resolution from a lattice (thus we want
|
||||
to match by threshold, not nearest match). Residue doesn't *have* to
|
||||
be encoded that way, but to change it, one will need to add more
|
||||
infrastructure on the encode side (decode side is specced and simpler) */
|
||||
|
||||
/* floor0 LSP (single stage, non interleaved, nearest match) */
|
||||
/* returns entry number and *modifies a* to the quantization value *****/
|
||||
int vorbis_book_errorv(codebook *book,float *a){
|
||||
int dim=book->dim,k;
|
||||
int best=_best(book,a,1);
|
||||
for(k=0;k<dim;k++)
|
||||
a[k]=(book->valuelist+best*dim)[k];
|
||||
return(best);
|
||||
}
|
||||
|
||||
/* returns the number of bits and *modifies a* to the quantization value *****/
|
||||
int vorbis_book_encodev(codebook *book,int best,float *a,oggpack_buffer *b){
|
||||
int k,dim=book->dim;
|
||||
for(k=0;k<dim;k++)
|
||||
a[k]=(book->valuelist+best*dim)[k];
|
||||
return(vorbis_book_encode(book,best,b));
|
||||
}
|
||||
|
||||
/* the 'eliminate the decode tree' optimization actually requires the
|
||||
codewords to be MSb first, not LSb. This is an annoying inelegancy
|
||||
(and one of the first places where carefully thought out design
|
||||
turned out to be wrong; Vorbis II and future Ogg codecs should go
|
||||
to an MSb bitpacker), but not actually the huge hit it appears to
|
||||
be. The first-stage decode table catches most words so that
|
||||
bitreverse is not in the main execution path. */
|
||||
|
||||
|
||||
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=ogg_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){
|
||||
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(packed_entry);
|
||||
}
|
||||
|
||||
/* returns 0 on OK or -1 on eof *************************************/
|
||||
long vorbis_book_decodevs_add(codebook *book,float *a,oggpack_buffer *b,int n){
|
||||
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){
|
||||
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){
|
||||
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++];
|
||||
}
|
||||
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;
|
||||
|
||||
for(i=offset/ch;i<(offset+n)/ch;){
|
||||
entry = decode_packed_entry_number(book,b);
|
||||
if(entry==-1)return(-1);
|
||||
{
|
||||
const float *t = book->valuelist+entry*book->dim;
|
||||
for (j=0;j<book->dim;j++){
|
||||
a[chptr++][i]+=t[j];
|
||||
if(chptr==ch){
|
||||
chptr=0;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return(0);
|
||||
}
|
||||
|
||||
#ifdef _V_SELFTEST
|
||||
/* Simple enough; pack a few candidate codebooks, unpack them. Code a
|
||||
number of vectors through (keeping track of the quantized values),
|
||||
and decode using the unpacked book. quantized version of in should
|
||||
exactly equal out */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "vorbis/book/lsp20_0.vqh"
|
||||
#include "vorbis/book/res0a_13.vqh"
|
||||
#define TESTSIZE 40
|
||||
|
||||
float test1[TESTSIZE]={
|
||||
0.105939f,
|
||||
0.215373f,
|
||||
0.429117f,
|
||||
0.587974f,
|
||||
|
||||
0.181173f,
|
||||
0.296583f,
|
||||
0.515707f,
|
||||
0.715261f,
|
||||
|
||||
0.162327f,
|
||||
0.263834f,
|
||||
0.342876f,
|
||||
0.406025f,
|
||||
|
||||
0.103571f,
|
||||
0.223561f,
|
||||
0.368513f,
|
||||
0.540313f,
|
||||
|
||||
0.136672f,
|
||||
0.395882f,
|
||||
0.587183f,
|
||||
0.652476f,
|
||||
|
||||
0.114338f,
|
||||
0.417300f,
|
||||
0.525486f,
|
||||
0.698679f,
|
||||
|
||||
0.147492f,
|
||||
0.324481f,
|
||||
0.643089f,
|
||||
0.757582f,
|
||||
|
||||
0.139556f,
|
||||
0.215795f,
|
||||
0.324559f,
|
||||
0.399387f,
|
||||
|
||||
0.120236f,
|
||||
0.267420f,
|
||||
0.446940f,
|
||||
0.608760f,
|
||||
|
||||
0.115587f,
|
||||
0.287234f,
|
||||
0.571081f,
|
||||
0.708603f,
|
||||
};
|
||||
|
||||
float test3[TESTSIZE]={
|
||||
0,1,-2,3,4,-5,6,7,8,9,
|
||||
8,-2,7,-1,4,6,8,3,1,-9,
|
||||
10,11,12,13,14,15,26,17,18,19,
|
||||
30,-25,-30,-1,-5,-32,4,3,-2,0};
|
||||
|
||||
static_codebook *testlist[]={&_vq_book_lsp20_0,
|
||||
&_vq_book_res0a_13,NULL};
|
||||
float *testvec[]={test1,test3};
|
||||
|
||||
int main(){
|
||||
oggpack_buffer write;
|
||||
oggpack_buffer read;
|
||||
long ptr=0,i;
|
||||
oggpack_writeinit(&write);
|
||||
|
||||
fprintf(stderr,"Testing codebook abstraction...:\n");
|
||||
|
||||
while(testlist[ptr]){
|
||||
codebook c;
|
||||
static_codebook s;
|
||||
float *qv=alloca(sizeof(*qv)*TESTSIZE);
|
||||
float *iv=alloca(sizeof(*iv)*TESTSIZE);
|
||||
memcpy(qv,testvec[ptr],sizeof(*qv)*TESTSIZE);
|
||||
memset(iv,0,sizeof(*iv)*TESTSIZE);
|
||||
|
||||
fprintf(stderr,"\tpacking/coding %ld... ",ptr);
|
||||
|
||||
/* pack the codebook, write the testvector */
|
||||
oggpack_reset(&write);
|
||||
vorbis_book_init_encode(&c,testlist[ptr]); /* get it into memory
|
||||
we can write */
|
||||
vorbis_staticbook_pack(testlist[ptr],&write);
|
||||
fprintf(stderr,"Codebook size %ld bytes... ",oggpack_bytes(&write));
|
||||
for(i=0;i<TESTSIZE;i+=c.dim){
|
||||
int best=_best(&c,qv+i,1);
|
||||
vorbis_book_encodev(&c,best,qv+i,&write);
|
||||
}
|
||||
vorbis_book_clear(&c);
|
||||
|
||||
fprintf(stderr,"OK.\n");
|
||||
fprintf(stderr,"\tunpacking/decoding %ld... ",ptr);
|
||||
|
||||
/* transfer the write data to a read buffer and unpack/read */
|
||||
oggpack_readinit(&read,oggpack_get_buffer(&write),oggpack_bytes(&write));
|
||||
if(vorbis_staticbook_unpack(&read,&s)){
|
||||
fprintf(stderr,"Error unpacking codebook.\n");
|
||||
exit(1);
|
||||
}
|
||||
if(vorbis_book_init_decode(&c,&s)){
|
||||
fprintf(stderr,"Error initializing codebook.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
for(i=0;i<TESTSIZE;i+=c.dim)
|
||||
if(vorbis_book_decodev_set(&c,iv+i,&read,c.dim)==-1){
|
||||
fprintf(stderr,"Error reading codebook test data (EOP).\n");
|
||||
exit(1);
|
||||
}
|
||||
for(i=0;i<TESTSIZE;i++)
|
||||
if(fabs(qv[i]-iv[i])>.000001){
|
||||
fprintf(stderr,"read (%g) != written (%g) at position (%ld)\n",
|
||||
iv[i],qv[i],i);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
fprintf(stderr,"OK\n");
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* The above is the trivial stuff; now try unquantizing a log scale codebook */
|
||||
|
||||
exit(0);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,160 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: basic shared codebook operations
|
||||
last mod: $Id: codebook.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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
|
||||
*/
|
||||
|
||||
/* encode helpers ********************************************************/
|
||||
struct encode_aux_nearestmatch *nearest_tree;
|
||||
struct encode_aux_threshmatch *thresh_tree;
|
||||
struct encode_aux_pigeonhole *pigeon_tree;
|
||||
|
||||
int allocedp;
|
||||
} static_codebook;
|
||||
|
||||
/* this structures an arbitrary trained book to quickly find the
|
||||
nearest cell match */
|
||||
typedef struct encode_aux_nearestmatch{
|
||||
/* pre-calculated partitioning tree */
|
||||
long *ptr0;
|
||||
long *ptr1;
|
||||
|
||||
long *p; /* decision points (each is an entry) */
|
||||
long *q; /* decision points (each is an entry) */
|
||||
long aux; /* number of tree entries */
|
||||
long alloc;
|
||||
} encode_aux_nearestmatch;
|
||||
|
||||
/* assumes a maptype of 1; encode side only, so that's OK */
|
||||
typedef struct encode_aux_threshmatch{
|
||||
float *quantthresh;
|
||||
long *quantmap;
|
||||
int quantvals;
|
||||
int threshvals;
|
||||
} encode_aux_threshmatch;
|
||||
|
||||
typedef struct encode_aux_pigeonhole{
|
||||
float min;
|
||||
float del;
|
||||
|
||||
int mapentries;
|
||||
int quantvals;
|
||||
long *pigeonmap;
|
||||
|
||||
long fittotal;
|
||||
long *fitlist;
|
||||
long *fitmap;
|
||||
long *fitlength;
|
||||
} encode_aux_pigeonhole;
|
||||
|
||||
typedef struct codebook{
|
||||
long dim; /* codebook dimensions (elements per vector) */
|
||||
long entries; /* codebook entries */
|
||||
long used_entries; /* populated codebook entries */
|
||||
const static_codebook *c;
|
||||
|
||||
/* for encode, the below are entry-ordered, fully populated */
|
||||
/* for decode, the below are ordered by bitreversed codeword and only
|
||||
used entries are populated */
|
||||
float *valuelist; /* list of dim*entries actual entry values */
|
||||
ogg_uint32_t *codelist; /* list of bitstream codewords for each entry */
|
||||
|
||||
int *dec_index; /* only used if sparseness collapsed */
|
||||
char *dec_codelengths;
|
||||
ogg_uint32_t *dec_firsttable;
|
||||
int dec_firsttablen;
|
||||
int dec_maxlength;
|
||||
|
||||
} codebook;
|
||||
|
||||
extern void vorbis_staticbook_clear(static_codebook *b);
|
||||
extern void vorbis_staticbook_destroy(static_codebook *b);
|
||||
extern int vorbis_book_init_encode(codebook *dest,const static_codebook *source);
|
||||
extern int vorbis_book_init_decode(codebook *dest,const static_codebook *source);
|
||||
extern void vorbis_book_clear(codebook *b);
|
||||
|
||||
extern float *_book_unquantize(const static_codebook *b,int n,int *map);
|
||||
extern float *_book_logdist(const static_codebook *b,float *vals);
|
||||
extern float _float32_unpack(long val);
|
||||
extern long _float32_pack(float val);
|
||||
extern int _best(codebook *book, float *a, int step);
|
||||
extern int _ilog(unsigned int v);
|
||||
extern long _book_maptype1_quantvals(const static_codebook *b);
|
||||
|
||||
extern int vorbis_book_besterror(codebook *book,float *a,int step,int addmul);
|
||||
extern long vorbis_book_codeword(codebook *book,int entry);
|
||||
extern long vorbis_book_codelen(codebook *book,int entry);
|
||||
|
||||
|
||||
|
||||
extern int vorbis_staticbook_pack(const static_codebook *c,oggpack_buffer *b);
|
||||
extern int vorbis_staticbook_unpack(oggpack_buffer *b,static_codebook *c);
|
||||
|
||||
extern int vorbis_book_encode(codebook *book, int a, oggpack_buffer *b);
|
||||
extern int vorbis_book_errorv(codebook *book, float *a);
|
||||
extern int vorbis_book_encodev(codebook *book, int best,float *a,
|
||||
oggpack_buffer *b);
|
||||
|
||||
extern long vorbis_book_decode(codebook *book, oggpack_buffer *b);
|
||||
extern long vorbis_book_decodevs_add(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodev_set(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodev_add(codebook *book, float *a,
|
||||
oggpack_buffer *b,int n);
|
||||
extern long vorbis_book_decodevv_add(codebook *book, float **a,
|
||||
long off,int ch,
|
||||
oggpack_buffer *b,int n);
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: libvorbis codec headers
|
||||
last mod: $Id: codec_internal.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#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);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,383 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis
|
||||
last mod: $Id: envelope.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
|
||||
#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 pos){
|
||||
long n=ve->winlength;
|
||||
int ret=0;
|
||||
long i,j;
|
||||
float decay;
|
||||
|
||||
/* we want to have a 'minimum bar' for energy, else we're just
|
||||
basing blocks on quantization noise that outweighs the signal
|
||||
itself (for low power signals) */
|
||||
|
||||
float minV=ve->minenergy;
|
||||
float *vec=(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,j);
|
||||
}
|
||||
|
||||
ve->mark[j+VE_POST]=0;
|
||||
if(ret&1){
|
||||
ve->mark[j]=1;
|
||||
ve->mark[j+1]=1;
|
||||
}
|
||||
|
||||
if(ret&2){
|
||||
ve->mark[j]=1;
|
||||
if(j>0)ve->mark[j-1]=1;
|
||||
}
|
||||
|
||||
if(ret&4)ve->stretch=-1;
|
||||
}
|
||||
|
||||
ve->current=last*ve->searchstep;
|
||||
|
||||
{
|
||||
long centerW=v->centerW;
|
||||
long testW=
|
||||
centerW+
|
||||
ci->blocksizes[v->W]/4+
|
||||
ci->blocksizes[1]/2+
|
||||
ci->blocksizes[0]/4;
|
||||
|
||||
j=ve->cursor;
|
||||
|
||||
while(j<ve->current-(ve->searchstep)){/* account for postecho
|
||||
working back one window */
|
||||
if(j>=testW)return(1);
|
||||
|
||||
ve->cursor=j;
|
||||
|
||||
if(ve->mark[j/ve->searchstep]){
|
||||
if(j>centerW){
|
||||
|
||||
#if 0
|
||||
if(j>ve->curmark){
|
||||
float *marker=alloca(v->pcm_current*sizeof(*marker));
|
||||
int l,m;
|
||||
memset(marker,0,sizeof(*marker)*v->pcm_current);
|
||||
fprintf(stderr,"mark! seq=%d, cursor:%fs time:%fs\n",
|
||||
seq,
|
||||
(totalshift+ve->cursor)/44100.,
|
||||
(totalshift+j)/44100.);
|
||||
_analysis_output_always("pcmL",seq,v->pcm[0],v->pcm_current,0,0,totalshift);
|
||||
_analysis_output_always("pcmR",seq,v->pcm[1],v->pcm_current,0,0,totalshift);
|
||||
|
||||
_analysis_output_always("markL",seq,v->pcm[0],j,0,0,totalshift);
|
||||
_analysis_output_always("markR",seq,v->pcm[1],j,0,0,totalshift);
|
||||
|
||||
for(m=0;m<VE_BANDS;m++){
|
||||
char buf[80];
|
||||
sprintf(buf,"delL%d",m);
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m].markers[l]*.1;
|
||||
_analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
|
||||
}
|
||||
|
||||
for(m=0;m<VE_BANDS;m++){
|
||||
char buf[80];
|
||||
sprintf(buf,"delR%d",m);
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->filter[m+VE_BANDS].markers[l]*.1;
|
||||
_analysis_output_always(buf,seq,marker,v->pcm_current,0,0,totalshift);
|
||||
}
|
||||
|
||||
for(l=0;l<last;l++)marker[l*ve->searchstep]=ve->mark[l]*.4;
|
||||
_analysis_output_always("mark",seq,marker,v->pcm_current,0,0,totalshift);
|
||||
|
||||
|
||||
seq++;
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
ve->curmark=j;
|
||||
if(j>=testW)return(1);
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
j+=ve->searchstep;
|
||||
}
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
int _ve_envelope_mark(vorbis_dsp_state *v){
|
||||
envelope_lookup *ve=((private_state *)(v->backend_state))->ve;
|
||||
vorbis_info *vi=v->vi;
|
||||
codec_setup_info *ci=(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;
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -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-2002 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: PCM data envelope analysis and manipulation
|
||||
last mod: $Id: envelope.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_ENVELOPE_
|
||||
#define _V_ENVELOPE_
|
||||
|
||||
#include "mdct.h"
|
||||
|
||||
#define VE_PRE 16
|
||||
#define VE_WIN 4
|
||||
#define VE_POST 2
|
||||
#define VE_AMP (VE_PRE+VE_POST-1)
|
||||
|
||||
#define VE_BANDS 7
|
||||
#define VE_NEARDC 15
|
||||
|
||||
#define VE_MINSTRETCH 2 /* a bit less than short block */
|
||||
#define VE_MAXSTRETCH 12 /* one-third full block */
|
||||
|
||||
typedef struct {
|
||||
float ampbuf[VE_AMP];
|
||||
int ampptr;
|
||||
|
||||
float nearDC[VE_NEARDC];
|
||||
float nearDC_acc;
|
||||
float nearDC_partialacc;
|
||||
int nearptr;
|
||||
|
||||
} envelope_filter_state;
|
||||
|
||||
typedef struct {
|
||||
int begin;
|
||||
int end;
|
||||
float *window;
|
||||
float total;
|
||||
} envelope_band;
|
||||
|
||||
typedef struct {
|
||||
int ch;
|
||||
int winlength;
|
||||
int searchstep;
|
||||
float minenergy;
|
||||
|
||||
mdct_lookup mdct;
|
||||
float *mdct_win;
|
||||
|
||||
envelope_band band[VE_BANDS];
|
||||
envelope_filter_state *filter;
|
||||
int stretch;
|
||||
|
||||
int *mark;
|
||||
|
||||
long storage;
|
||||
long current;
|
||||
long curmark;
|
||||
long cursor;
|
||||
} envelope_lookup;
|
||||
|
||||
extern void _ve_envelope_init(envelope_lookup *e,vorbis_info *vi);
|
||||
extern void _ve_envelope_clear(envelope_lookup *e);
|
||||
extern long _ve_envelope_search(vorbis_dsp_state *v);
|
||||
extern void _ve_envelope_shift(envelope_lookup *e,long shift);
|
||||
extern int _ve_envelope_mark(vorbis_dsp_state *v);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: floor backend 0 implementation
|
||||
last mod: $Id: floor0.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
|
||||
#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;
|
||||
}
|
||||
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 */
|
||||
vorbis_func_floor floor0_exportbundle={
|
||||
NULL,&floor0_unpack,&floor0_look,&floor0_free_info,
|
||||
&floor0_free_look,&floor0_inverse1,&floor0_inverse2
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
1074
src/audio/audio_file_formats/oggvorbis/libvorbis-1.1.2/lib/floor1.c
Normal file
1074
src/audio/audio_file_formats/oggvorbis/libvorbis-1.1.2/lib/floor1.c
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -0,0 +1,56 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: highlevel encoder setup struct seperated out for vorbisenc clarity
|
||||
last mod: $Id: highlevel.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
typedef struct highlevel_byblocktype {
|
||||
double tone_mask_setting;
|
||||
double tone_peaklimit_setting;
|
||||
double noise_bias_setting;
|
||||
double noise_compand_setting;
|
||||
} highlevel_byblocktype;
|
||||
|
||||
typedef struct highlevel_encode_setup {
|
||||
void *setup;
|
||||
int set_in_stone;
|
||||
|
||||
double base_setting;
|
||||
double long_setting;
|
||||
double short_setting;
|
||||
double impulse_noisetune;
|
||||
|
||||
int managed;
|
||||
long bitrate_min;
|
||||
long bitrate_av;
|
||||
double bitrate_av_damp;
|
||||
long bitrate_max;
|
||||
long bitrate_reservoir;
|
||||
double bitrate_reservoir_bias;
|
||||
|
||||
int impulse_block_p;
|
||||
int noise_normalize_p;
|
||||
|
||||
double stereo_point_setting;
|
||||
double lowpass_kHz;
|
||||
|
||||
double ath_floating_dB;
|
||||
double ath_absolute_dB;
|
||||
|
||||
double amplitude_track_dBpersec;
|
||||
double trigger_setting;
|
||||
|
||||
highlevel_byblocktype block[4]; /* padding, impulse, transition, long */
|
||||
|
||||
} highlevel_encode_setup;
|
||||
|
|
@ -0,0 +1,602 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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-2003 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: maintain the info structure, info <-> header packets
|
||||
last mod: $Id: info.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
/* 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"
|
||||
|
||||
|
||||
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,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, 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, 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, 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;
|
||||
for(i=0;i<vc->comments;i++)
|
||||
if(vc->user_comments[i])_ogg_free(vc->user_comments[i]);
|
||||
if(vc->user_comments)_ogg_free(vc->user_comments);
|
||||
if(vc->comment_lengths)_ogg_free(vc->comment_lengths);
|
||||
if(vc->vendor)_ogg_free(vc->vendor);
|
||||
}
|
||||
memset(vc,0,sizeof(*vc));
|
||||
}
|
||||
|
||||
/* blocksize 0 is guaranteed to be short, 1 is guarantted 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 */
|
||||
_mapping_P[ci->map_type[i]]->free_info(ci->map_param[i]);
|
||||
|
||||
for(i=0;i<ci->floors;i++) /* unpack does the range checking */
|
||||
_floor_P[ci->floor_type[i]]->free_info(ci->floor_param[i]);
|
||||
|
||||
for(i=0;i<ci->residues;i++) /* unpack does the range checking */
|
||||
_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]<8)goto err_out;
|
||||
if(ci->blocksizes[1]<ci->blocksizes[0])goto err_out;
|
||||
|
||||
if(oggpack_read(opb,1)!=1)goto err_out; /* EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_info_clear(vi);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
static int _vorbis_unpack_comment(vorbis_comment *vc,oggpack_buffer *opb){
|
||||
int i;
|
||||
int vendorlen=oggpack_read(opb,32);
|
||||
if(vendorlen<0)goto err_out;
|
||||
vc->vendor=(char*)_ogg_calloc(vendorlen+1,1);
|
||||
_v_readstring(opb,vc->vendor,vendorlen);
|
||||
vc->comments=oggpack_read(opb,32);
|
||||
if(vc->comments<0)goto err_out;
|
||||
vc->user_comments=(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;
|
||||
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;
|
||||
/*ci->book_param=_ogg_calloc(ci->books,sizeof(*ci->book_param));*/
|
||||
for(i=0;i<ci->books;i++){
|
||||
ci->book_param[i]=(static_codebook*)_ogg_calloc(1,sizeof(*ci->book_param[i]));
|
||||
if(vorbis_staticbook_unpack(opb,ci->book_param[i]))goto err_out;
|
||||
}
|
||||
|
||||
/* time backend settings; hooks are unused */
|
||||
{
|
||||
int times=oggpack_read(opb,6)+1;
|
||||
for(i=0;i<times;i++){
|
||||
int test=oggpack_read(opb,16);
|
||||
if(test<0 || test>=VI_TIMEB)goto err_out;
|
||||
}
|
||||
}
|
||||
|
||||
/* floor backend settings */
|
||||
ci->floors=oggpack_read(opb,6)+1;
|
||||
/*ci->floor_type=_ogg_malloc(ci->floors*sizeof(*ci->floor_type));*/
|
||||
/*ci->floor_param=_ogg_calloc(ci->floors,sizeof(void *));*/
|
||||
for(i=0;i<ci->floors;i++){
|
||||
ci->floor_type[i]=oggpack_read(opb,16);
|
||||
if(ci->floor_type[i]<0 || ci->floor_type[i]>=VI_FLOORB)goto err_out;
|
||||
ci->floor_param[i]=_floor_P[ci->floor_type[i]]->unpack(vi,opb);
|
||||
if(!ci->floor_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* residue backend settings */
|
||||
ci->residues=oggpack_read(opb,6)+1;
|
||||
/*ci->residue_type=_ogg_malloc(ci->residues*sizeof(*ci->residue_type));*/
|
||||
/*ci->residue_param=_ogg_calloc(ci->residues,sizeof(void *));*/
|
||||
for(i=0;i<ci->residues;i++){
|
||||
ci->residue_type[i]=oggpack_read(opb,16);
|
||||
if(ci->residue_type[i]<0 || ci->residue_type[i]>=VI_RESB)goto err_out;
|
||||
ci->residue_param[i]=_residue_P[ci->residue_type[i]]->unpack(vi,opb);
|
||||
if(!ci->residue_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* map backend settings */
|
||||
ci->maps=oggpack_read(opb,6)+1;
|
||||
/*ci->map_type=_ogg_malloc(ci->maps*sizeof(*ci->map_type));*/
|
||||
/*ci->map_param=_ogg_calloc(ci->maps,sizeof(void *));*/
|
||||
for(i=0;i<ci->maps;i++){
|
||||
ci->map_type[i]=oggpack_read(opb,16);
|
||||
if(ci->map_type[i]<0 || ci->map_type[i]>=VI_MAPB)goto err_out;
|
||||
ci->map_param[i]=_mapping_P[ci->map_type[i]]->unpack(vi,opb);
|
||||
if(!ci->map_param[i])goto err_out;
|
||||
}
|
||||
|
||||
/* mode settings */
|
||||
ci->modes=oggpack_read(opb,6)+1;
|
||||
/*vi->mode_param=_ogg_calloc(vi->modes,sizeof(void *));*/
|
||||
for(i=0;i<ci->modes;i++){
|
||||
ci->mode_param[i]=(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(oggpack_read(opb,1)!=1)goto err_out; /* top level EOP check */
|
||||
|
||||
return(0);
|
||||
err_out:
|
||||
vorbis_info_clear(vi);
|
||||
return(OV_EBADHEADER);
|
||||
}
|
||||
|
||||
/* 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){
|
||||
char temp[]="Xiph.Org libVorbis I 20050304";
|
||||
int bytes = strlen(temp);
|
||||
|
||||
/* preamble */
|
||||
oggpack_write(opb,0x03,8);
|
||||
_v_writestring(opb,"vorbis", 6);
|
||||
|
||||
/* vendor */
|
||||
oggpack_write(opb,bytes,32);
|
||||
_v_writestring(opb,temp, bytes);
|
||||
|
||||
/* comments */
|
||||
|
||||
oggpack_write(opb,vc->comments,32);
|
||||
if(vc->comments){
|
||||
int i;
|
||||
for(i=0;i<vc->comments;i++){
|
||||
if(vc->user_comments[i]){
|
||||
oggpack_write(opb,vc->comment_lengths[i],32);
|
||||
_v_writestring(opb,vc->user_comments[i], vc->comment_lengths[i]);
|
||||
}else{
|
||||
oggpack_write(opb,0,32);
|
||||
}
|
||||
}
|
||||
}
|
||||
oggpack_write(opb,1,1);
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
static int _vorbis_pack_books(oggpack_buffer *opb,vorbis_info *vi){
|
||||
codec_setup_info *ci=(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:
|
||||
oggpack_writeclear(&opb);
|
||||
memset(op,0,sizeof(*op));
|
||||
memset(op_comm,0,sizeof(*op_comm));
|
||||
memset(op_code,0,sizeof(*op_code));
|
||||
|
||||
if(b->header)_ogg_free(b->header);
|
||||
if(b->header1)_ogg_free(b->header1);
|
||||
if(b->header2)_ogg_free(b->header2);
|
||||
b->header=NULL;
|
||||
b->header1=NULL;
|
||||
b->header2=NULL;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
double vorbis_granule_time(vorbis_dsp_state *v,ogg_int64_t granulepos){
|
||||
if(granulepos>=0)
|
||||
return((double)granulepos/v->vi->rate);
|
||||
return(-1);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
last mod: $Id: lookup.c,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#include "../../juce_OggVorbisHeader.h"
|
||||
#if JUCE_USE_OGGVORBIS
|
||||
|
||||
#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
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,32 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup based functions
|
||||
last mod: $Id: lookup.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
extern float vorbis_coslook(float a);
|
||||
extern float vorbis_invsqlook(float a);
|
||||
extern float vorbis_invsq2explook(int a);
|
||||
extern float vorbis_fromdBlook(float a);
|
||||
#endif
|
||||
#ifdef INT_LOOKUP
|
||||
extern long vorbis_invsqlook_i(long a,long e);
|
||||
extern long vorbis_coslook_i(long a);
|
||||
extern float vorbis_fromdBlook_i(long a);
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,189 @@
|
|||
/********************************************************************
|
||||
* *
|
||||
* THIS FILE IS PART OF THE OggVorbis SOFTWARE CODEC SOURCE CODE. *
|
||||
* USE, DISTRIBUTION AND REPRODUCTION OF THIS LIBRARY SOURCE IS *
|
||||
* GOVERNED BY A BSD-STYLE SOURCE LICENSE INCLUDED WITH THIS SOURCE *
|
||||
* IN 'COPYING'. PLEASE READ THESE TERMS BEFORE DISTRIBUTING. *
|
||||
* *
|
||||
* THE OggVorbis SOURCE CODE IS (C) COPYRIGHT 1994-2002 *
|
||||
* by the XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup data; generated by lookups.pl; edit there
|
||||
last mod: $Id: lookup_data.h,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_DATA_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
#define COS_LOOKUP_SZ 128
|
||||
static float COS_LOOKUP[COS_LOOKUP_SZ+1]={
|
||||
+1.0000000000000f,+0.9996988186962f,+0.9987954562052f,+0.9972904566787f,
|
||||
+0.9951847266722f,+0.9924795345987f,+0.9891765099648f,+0.9852776423889f,
|
||||
+0.9807852804032f,+0.9757021300385f,+0.9700312531945f,+0.9637760657954f,
|
||||
+0.9569403357322f,+0.9495281805930f,+0.9415440651830f,+0.9329927988347f,
|
||||
+0.9238795325113f,+0.9142097557035f,+0.9039892931234f,+0.8932243011955f,
|
||||
+0.8819212643484f,+0.8700869911087f,+0.8577286100003f,+0.8448535652497f,
|
||||
+0.8314696123025f,+0.8175848131516f,+0.8032075314806f,+0.7883464276266f,
|
||||
+0.7730104533627f,+0.7572088465065f,+0.7409511253550f,+0.7242470829515f,
|
||||
+0.7071067811865f,+0.6895405447371f,+0.6715589548470f,+0.6531728429538f,
|
||||
+0.6343932841636f,+0.6152315905806f,+0.5956993044924f,+0.5758081914178f,
|
||||
+0.5555702330196f,+0.5349976198871f,+0.5141027441932f,+0.4928981922298f,
|
||||
+0.4713967368260f,+0.4496113296546f,+0.4275550934303f,+0.4052413140050f,
|
||||
+0.3826834323651f,+0.3598950365350f,+0.3368898533922f,+0.3136817403989f,
|
||||
+0.2902846772545f,+0.2667127574749f,+0.2429801799033f,+0.2191012401569f,
|
||||
+0.1950903220161f,+0.1709618887603f,+0.1467304744554f,+0.1224106751992f,
|
||||
+0.0980171403296f,+0.0735645635997f,+0.0490676743274f,+0.0245412285229f,
|
||||
+0.0000000000000f,-0.0245412285229f,-0.0490676743274f,-0.0735645635997f,
|
||||
-0.0980171403296f,-0.1224106751992f,-0.1467304744554f,-0.1709618887603f,
|
||||
-0.1950903220161f,-0.2191012401569f,-0.2429801799033f,-0.2667127574749f,
|
||||
-0.2902846772545f,-0.3136817403989f,-0.3368898533922f,-0.3598950365350f,
|
||||
-0.3826834323651f,-0.4052413140050f,-0.4275550934303f,-0.4496113296546f,
|
||||
-0.4713967368260f,-0.4928981922298f,-0.5141027441932f,-0.5349976198871f,
|
||||
-0.5555702330196f,-0.5758081914178f,-0.5956993044924f,-0.6152315905806f,
|
||||
-0.6343932841636f,-0.6531728429538f,-0.6715589548470f,-0.6895405447371f,
|
||||
-0.7071067811865f,-0.7242470829515f,-0.7409511253550f,-0.7572088465065f,
|
||||
-0.7730104533627f,-0.7883464276266f,-0.8032075314806f,-0.8175848131516f,
|
||||
-0.8314696123025f,-0.8448535652497f,-0.8577286100003f,-0.8700869911087f,
|
||||
-0.8819212643484f,-0.8932243011955f,-0.9039892931234f,-0.9142097557035f,
|
||||
-0.9238795325113f,-0.9329927988347f,-0.9415440651830f,-0.9495281805930f,
|
||||
-0.9569403357322f,-0.9637760657954f,-0.9700312531945f,-0.9757021300385f,
|
||||
-0.9807852804032f,-0.9852776423889f,-0.9891765099648f,-0.9924795345987f,
|
||||
-0.9951847266722f,-0.9972904566787f,-0.9987954562052f,-0.9996988186962f,
|
||||
-1.0000000000000f,
|
||||
};
|
||||
|
||||
#define INVSQ_LOOKUP_SZ 32
|
||||
static float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={
|
||||
1.414213562373f,1.392621247646f,1.371988681140f,1.352246807566f,
|
||||
1.333333333333f,1.315191898443f,1.297771369046f,1.281025230441f,
|
||||
1.264911064067f,1.249390095109f,1.234426799697f,1.219988562661f,
|
||||
1.206045378311f,1.192569588000f,1.179535649239f,1.166919931983f,
|
||||
1.154700538379f,1.142857142857f,1.131370849898f,1.120224067222f,
|
||||
1.109400392450f,1.098884511590f,1.088662107904f,1.078719779941f,
|
||||
1.069044967650f,1.059625885652f,1.050451462878f,1.041511287847f,
|
||||
1.032795558989f,1.024295039463f,1.016001016002f,1.007905261358f,
|
||||
1.000000000000f,
|
||||
};
|
||||
|
||||
#define INVSQ2EXP_LOOKUP_MIN (-32)
|
||||
#define INVSQ2EXP_LOOKUP_MAX 32
|
||||
static float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\
|
||||
INVSQ2EXP_LOOKUP_MIN+1]={
|
||||
65536.f, 46340.95001f, 32768.f, 23170.47501f,
|
||||
16384.f, 11585.2375f, 8192.f, 5792.618751f,
|
||||
4096.f, 2896.309376f, 2048.f, 1448.154688f,
|
||||
1024.f, 724.0773439f, 512.f, 362.038672f,
|
||||
256.f, 181.019336f, 128.f, 90.50966799f,
|
||||
64.f, 45.254834f, 32.f, 22.627417f,
|
||||
16.f, 11.3137085f, 8.f, 5.656854249f,
|
||||
4.f, 2.828427125f, 2.f, 1.414213562f,
|
||||
1.f, 0.7071067812f, 0.5f, 0.3535533906f,
|
||||
0.25f, 0.1767766953f, 0.125f, 0.08838834765f,
|
||||
0.0625f, 0.04419417382f, 0.03125f, 0.02209708691f,
|
||||
0.015625f, 0.01104854346f, 0.0078125f, 0.005524271728f,
|
||||
0.00390625f, 0.002762135864f, 0.001953125f, 0.001381067932f,
|
||||
0.0009765625f, 0.000690533966f, 0.00048828125f, 0.000345266983f,
|
||||
0.000244140625f,0.0001726334915f,0.0001220703125f,8.631674575e-05f,
|
||||
6.103515625e-05f,4.315837288e-05f,3.051757812e-05f,2.157918644e-05f,
|
||||
1.525878906e-05f,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#define FROMdB_LOOKUP_SZ 35
|
||||
#define FROMdB2_LOOKUP_SZ 32
|
||||
#define FROMdB_SHIFT 5
|
||||
#define FROMdB2_SHIFT 3
|
||||
#define FROMdB2_MASK 31
|
||||
static float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={
|
||||
1.f, 0.6309573445f, 0.3981071706f, 0.2511886432f,
|
||||
0.1584893192f, 0.1f, 0.06309573445f, 0.03981071706f,
|
||||
0.02511886432f, 0.01584893192f, 0.01f, 0.006309573445f,
|
||||
0.003981071706f, 0.002511886432f, 0.001584893192f, 0.001f,
|
||||
0.0006309573445f,0.0003981071706f,0.0002511886432f,0.0001584893192f,
|
||||
0.0001f,6.309573445e-05f,3.981071706e-05f,2.511886432e-05f,
|
||||
1.584893192e-05f, 1e-05f,6.309573445e-06f,3.981071706e-06f,
|
||||
2.511886432e-06f,1.584893192e-06f, 1e-06f,6.309573445e-07f,
|
||||
3.981071706e-07f,2.511886432e-07f,1.584893192e-07f,
|
||||
};
|
||||
|
||||
static float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={
|
||||
0.9928302478f, 0.9786445908f, 0.9646616199f, 0.9508784391f,
|
||||
0.9372921937f, 0.92390007f, 0.9106992942f, 0.8976871324f,
|
||||
0.8848608897f, 0.8722179097f, 0.8597555737f, 0.8474713009f,
|
||||
0.835362547f, 0.8234268041f, 0.8116616003f, 0.8000644989f,
|
||||
0.7886330981f, 0.7773650302f, 0.7662579617f, 0.755309592f,
|
||||
0.7445176537f, 0.7338799116f, 0.7233941627f, 0.7130582353f,
|
||||
0.7028699885f, 0.6928273125f, 0.6829281272f, 0.6731703824f,
|
||||
0.6635520573f, 0.6540711597f, 0.6447257262f, 0.6355138211f,
|
||||
};
|
||||
|
||||
#ifdef INT_LOOKUP
|
||||
|
||||
#define INVSQ_LOOKUP_I_SHIFT 10
|
||||
#define INVSQ_LOOKUP_I_MASK 1023
|
||||
static long INVSQ_LOOKUP_I[64+1]={
|
||||
92682l, 91966l, 91267l, 90583l,
|
||||
89915l, 89261l, 88621l, 87995l,
|
||||
87381l, 86781l, 86192l, 85616l,
|
||||
85051l, 84497l, 83953l, 83420l,
|
||||
82897l, 82384l, 81880l, 81385l,
|
||||
80899l, 80422l, 79953l, 79492l,
|
||||
79039l, 78594l, 78156l, 77726l,
|
||||
77302l, 76885l, 76475l, 76072l,
|
||||
75674l, 75283l, 74898l, 74519l,
|
||||
74146l, 73778l, 73415l, 73058l,
|
||||
72706l, 72359l, 72016l, 71679l,
|
||||
71347l, 71019l, 70695l, 70376l,
|
||||
70061l, 69750l, 69444l, 69141l,
|
||||
68842l, 68548l, 68256l, 67969l,
|
||||
67685l, 67405l, 67128l, 66855l,
|
||||
66585l, 66318l, 66054l, 65794l,
|
||||
65536l,
|
||||
};
|
||||
|
||||
#define COS_LOOKUP_I_SHIFT 9
|
||||
#define COS_LOOKUP_I_MASK 511
|
||||
#define COS_LOOKUP_I_SZ 128
|
||||
static long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={
|
||||
16384l, 16379l, 16364l, 16340l,
|
||||
16305l, 16261l, 16207l, 16143l,
|
||||
16069l, 15986l, 15893l, 15791l,
|
||||
15679l, 15557l, 15426l, 15286l,
|
||||
15137l, 14978l, 14811l, 14635l,
|
||||
14449l, 14256l, 14053l, 13842l,
|
||||
13623l, 13395l, 13160l, 12916l,
|
||||
12665l, 12406l, 12140l, 11866l,
|
||||
11585l, 11297l, 11003l, 10702l,
|
||||
10394l, 10080l, 9760l, 9434l,
|
||||
9102l, 8765l, 8423l, 8076l,
|
||||
7723l, 7366l, 7005l, 6639l,
|
||||
6270l, 5897l, 5520l, 5139l,
|
||||
4756l, 4370l, 3981l, 3590l,
|
||||
3196l, 2801l, 2404l, 2006l,
|
||||
1606l, 1205l, 804l, 402l,
|
||||
0l, -401l, -803l, -1204l,
|
||||
-1605l, -2005l, -2403l, -2800l,
|
||||
-3195l, -3589l, -3980l, -4369l,
|
||||
-4755l, -5138l, -5519l, -5896l,
|
||||
-6269l, -6638l, -7004l, -7365l,
|
||||
-7722l, -8075l, -8422l, -8764l,
|
||||
-9101l, -9433l, -9759l, -10079l,
|
||||
-10393l, -10701l, -11002l, -11296l,
|
||||
-11584l, -11865l, -12139l, -12405l,
|
||||
-12664l, -12915l, -13159l, -13394l,
|
||||
-13622l, -13841l, -14052l, -14255l,
|
||||
-14448l, -14634l, -14810l, -14977l,
|
||||
-15136l, -15285l, -15425l, -15556l,
|
||||
-15678l, -15790l, -15892l, -15985l,
|
||||
-16068l, -16142l, -16206l, -16260l,
|
||||
-16304l, -16339l, -16363l, -16378l,
|
||||
-16383l,
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,142 @@
|
|||
#!/usr/bin/perl
|
||||
print <<'EOD';
|
||||
/********************************************************************
|
||||
* *
|
||||
* 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 XIPHOPHORUS Company http://www.xiph.org/ *
|
||||
* *
|
||||
********************************************************************
|
||||
|
||||
function: lookup data; generated by lookups.pl; edit there
|
||||
last mod: $Id: lookups.pl,v 1.1 2007/06/07 17:49:17 jules_rms Exp $
|
||||
|
||||
********************************************************************/
|
||||
|
||||
#ifndef _V_LOOKUP_DATA_H_
|
||||
|
||||
#ifdef FLOAT_LOOKUP
|
||||
EOD
|
||||
|
||||
$cos_sz=128;
|
||||
$invsq_sz=32;
|
||||
$invsq2exp_min=-32;
|
||||
$invsq2exp_max=32;
|
||||
|
||||
$fromdB_sz=35;
|
||||
$fromdB_shift=5;
|
||||
$fromdB2_shift=3;
|
||||
|
||||
$invsq_i_shift=10;
|
||||
$cos_i_shift=9;
|
||||
$delta_shift=6;
|
||||
|
||||
print "#define COS_LOOKUP_SZ $cos_sz\n";
|
||||
print "static float COS_LOOKUP[COS_LOOKUP_SZ+1]={\n";
|
||||
|
||||
for($i=0;$i<=$cos_sz;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<=$cos_sz;$j++){
|
||||
printf "%+.13f,", cos(3.14159265358979323846*($i++)/$cos_sz) ;
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n";
|
||||
|
||||
print "#define INVSQ_LOOKUP_SZ $invsq_sz\n";
|
||||
print "static float INVSQ_LOOKUP[INVSQ_LOOKUP_SZ+1]={\n";
|
||||
|
||||
for($i=0;$i<=$invsq_sz;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<=$invsq_sz;$j++){
|
||||
my$indexmap=$i++/$invsq_sz*.5+.5;
|
||||
printf "%.12f,", 1./sqrt($indexmap);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n";
|
||||
|
||||
print "#define INVSQ2EXP_LOOKUP_MIN $invsq2exp_min\n";
|
||||
print "#define INVSQ2EXP_LOOKUP_MAX $invsq2exp_max\n";
|
||||
print "static float INVSQ2EXP_LOOKUP[INVSQ2EXP_LOOKUP_MAX-\\\n".
|
||||
" INVSQ2EXP_LOOKUP_MIN+1]={\n";
|
||||
|
||||
for($i=$invsq2exp_min;$i<=$invsq2exp_max;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<=$invsq2exp_max;$j++){
|
||||
printf "%15.10g,", 2**($i++*-.5);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n#endif\n\n";
|
||||
|
||||
|
||||
# 0 to -140 dB
|
||||
$fromdB2_sz=1<<$fromdB_shift;
|
||||
$fromdB_gran=1<<($fromdB_shift-$fromdB2_shift);
|
||||
print "#define FROMdB_LOOKUP_SZ $fromdB_sz\n";
|
||||
print "#define FROMdB2_LOOKUP_SZ $fromdB2_sz\n";
|
||||
print "#define FROMdB_SHIFT $fromdB_shift\n";
|
||||
print "#define FROMdB2_SHIFT $fromdB2_shift\n";
|
||||
print "#define FROMdB2_MASK ".((1<<$fromdB_shift)-1)."\n";
|
||||
|
||||
print "static float FROMdB_LOOKUP[FROMdB_LOOKUP_SZ]={\n";
|
||||
|
||||
for($i=0;$i<$fromdB_sz;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<$fromdB_sz;$j++){
|
||||
printf "%15.10g,", 10**(.05*(-$fromdB_gran*$i++));
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n";
|
||||
|
||||
print "static float FROMdB2_LOOKUP[FROMdB2_LOOKUP_SZ]={\n";
|
||||
|
||||
for($i=0;$i<$fromdB2_sz;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<$fromdB_sz;$j++){
|
||||
printf "%15.10g,", 10**(.05*(-$fromdB_gran/$fromdB2_sz*(.5+$i++)));
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n#ifdef INT_LOOKUP\n\n";
|
||||
|
||||
|
||||
$iisz=0x10000>>$invsq_i_shift;
|
||||
print "#define INVSQ_LOOKUP_I_SHIFT $invsq_i_shift\n";
|
||||
print "#define INVSQ_LOOKUP_I_MASK ".(0x0ffff>>(16-$invsq_i_shift))."\n";
|
||||
print "static long INVSQ_LOOKUP_I[$iisz+1]={\n";
|
||||
for($i=0;$i<=$iisz;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<=$iisz;$j++){
|
||||
my$indexmap=$i++/$iisz*.5+.5;
|
||||
printf "%8d,", int(1./sqrt($indexmap)*65536.+.5);
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n";
|
||||
|
||||
$cisz=0x10000>>$cos_i_shift;
|
||||
print "#define COS_LOOKUP_I_SHIFT $cos_i_shift\n";
|
||||
print "#define COS_LOOKUP_I_MASK ".(0x0ffff>>(16-$cos_i_shift))."\n";
|
||||
print "#define COS_LOOKUP_I_SZ $cisz\n";
|
||||
print "static long COS_LOOKUP_I[COS_LOOKUP_I_SZ+1]={\n";
|
||||
|
||||
for($i=0;$i<=$cisz;){
|
||||
print "\t";
|
||||
for($j=0;$j<4 && $i<=$cisz;$j++){
|
||||
printf "%8d,", int(cos(3.14159265358979323846*($i++)/$cos_sz)*16384.+.5) ;
|
||||
}
|
||||
print "\n";
|
||||
}
|
||||
print "};\n\n";
|
||||
|
||||
|
||||
print "#endif\n\n#endif\n";
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue