Initial revision
This commit is contained in:
commit
bb7f6b99d0
340
COPYING.GPL
Normal file
340
COPYING.GPL
Normal file
@ -0,0 +1,340 @@
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1989, 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
License is intended to guarantee your freedom to share and change free
|
||||
software--to make sure the software is free for all its users. This
|
||||
General Public License applies to most of the Free Software
|
||||
Foundation's software and to any other program whose authors commit to
|
||||
using it. (Some other Free Software Foundation software is covered by
|
||||
the GNU Library General Public License instead.) You can apply it to
|
||||
your programs, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if you
|
||||
distribute copies of the software, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of such a program, whether
|
||||
gratis or for a fee, you must give the recipients all the rights that
|
||||
you have. You must make sure that they, too, receive or can get the
|
||||
source code. And you must show them these terms so they know their
|
||||
rights.
|
||||
|
||||
We protect your rights with two steps: (1) copyright the software, and
|
||||
(2) offer you this license which gives you legal permission to copy,
|
||||
distribute and/or modify the software.
|
||||
|
||||
Also, for each author's protection and ours, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
software. If the software is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original, so
|
||||
that any problems introduced by others will not reflect on the original
|
||||
authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that redistributors of a free
|
||||
program will individually obtain patent licenses, in effect making the
|
||||
program proprietary. To prevent this, we have made it clear that any
|
||||
patent must be licensed for everyone's free use or not licensed at all.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow.
|
||||
|
||||
GNU GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License applies to any program or other work which contains
|
||||
a notice placed by the copyright holder saying it may be distributed
|
||||
under the terms of this General Public License. The "Program", below,
|
||||
refers to any such program or work, and a "work based on the Program"
|
||||
means either the Program or any derivative work under copyright law:
|
||||
that is to say, a work containing the Program or a portion of it,
|
||||
either verbatim or with modifications and/or translated into another
|
||||
language. (Hereinafter, translation is included without limitation in
|
||||
the term "modification".) Each licensee is addressed as "you".
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running the Program is not restricted, and the output from the Program
|
||||
is covered only if its contents constitute a work based on the
|
||||
Program (independent of having been made by running the Program).
|
||||
Whether that is true depends on what the Program does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Program's
|
||||
source code as you receive it, in any medium, provided that you
|
||||
conspicuously and appropriately publish on each copy an appropriate
|
||||
copyright notice and disclaimer of warranty; keep intact all the
|
||||
notices that refer to this License and to the absence of any warranty;
|
||||
and give any other recipients of the Program a copy of this License
|
||||
along with the Program.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy, and
|
||||
you may at your option offer warranty protection in exchange for a fee.
|
||||
|
||||
2. You may modify your copy or copies of the Program or any portion
|
||||
of it, thus forming a work based on the Program, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) You must cause the modified files to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
b) You must cause any work that you distribute or publish, that in
|
||||
whole or in part contains or is derived from the Program or any
|
||||
part thereof, to be licensed as a whole at no charge to all third
|
||||
parties under the terms of this License.
|
||||
|
||||
c) If the modified program normally reads commands interactively
|
||||
when run, you must cause it, when started running for such
|
||||
interactive use in the most ordinary way, to print or display an
|
||||
announcement including an appropriate copyright notice and a
|
||||
notice that there is no warranty (or else, saying that you provide
|
||||
a warranty) and that users may redistribute the program under
|
||||
these conditions, and telling the user how to view a copy of this
|
||||
License. (Exception: if the Program itself is interactive but
|
||||
does not normally print such an announcement, your work based on
|
||||
the Program is not required to print an announcement.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Program,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Program, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Program.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Program
|
||||
with the Program (or with a work based on the Program) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may copy and distribute the Program (or a work based on it,
|
||||
under Section 2) in object code or executable form under the terms of
|
||||
Sections 1 and 2 above provided that you also do one of the following:
|
||||
|
||||
a) Accompany it with the complete corresponding machine-readable
|
||||
source code, which must be distributed under the terms of Sections
|
||||
1 and 2 above on a medium customarily used for software interchange; or,
|
||||
|
||||
b) Accompany it with a written offer, valid for at least three
|
||||
years, to give any third party, for a charge no more than your
|
||||
cost of physically performing source distribution, a complete
|
||||
machine-readable copy of the corresponding source code, to be
|
||||
distributed under the terms of Sections 1 and 2 above on a medium
|
||||
customarily used for software interchange; or,
|
||||
|
||||
c) Accompany it with the information you received as to the offer
|
||||
to distribute corresponding source code. (This alternative is
|
||||
allowed only for noncommercial distribution and only if you
|
||||
received the program in object code or executable form with such
|
||||
an offer, in accord with Subsection b above.)
|
||||
|
||||
The source code for a work means the preferred form of the work for
|
||||
making modifications to it. For an executable work, complete source
|
||||
code means all the source code for all modules it contains, plus any
|
||||
associated interface definition files, plus the scripts used to
|
||||
control compilation and installation of the executable. However, as a
|
||||
special exception, the source code distributed need not include
|
||||
anything that is normally distributed (in either source or binary
|
||||
form) with the major components (compiler, kernel, and so on) of the
|
||||
operating system on which the executable runs, unless that component
|
||||
itself accompanies the executable.
|
||||
|
||||
If distribution of executable or object code is made by offering
|
||||
access to copy from a designated place, then offering equivalent
|
||||
access to copy the source code from the same place counts as
|
||||
distribution of the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
4. You may not copy, modify, sublicense, or distribute the Program
|
||||
except as expressly provided under this License. Any attempt
|
||||
otherwise to copy, modify, sublicense or distribute the Program is
|
||||
void, and will automatically terminate your rights under this License.
|
||||
However, parties who have received copies, or rights, from you under
|
||||
this License will not have their licenses terminated so long as such
|
||||
parties remain in full compliance.
|
||||
|
||||
5. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Program or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Program (or any work based on the
|
||||
Program), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Program or works based on it.
|
||||
|
||||
6. Each time you redistribute the Program (or any work based on the
|
||||
Program), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute or modify the Program subject to
|
||||
these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
7. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Program at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Program by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Program.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under
|
||||
any particular circumstance, the balance of the section is intended to
|
||||
apply and the section as a whole is intended to apply in other
|
||||
circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system, which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
8. If the distribution and/or use of the Program is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Program under this License
|
||||
may add an explicit geographical distribution limitation excluding
|
||||
those countries, so that distribution is permitted only in or among
|
||||
countries not thus excluded. In such case, this License incorporates
|
||||
the limitation as if written in the body of this License.
|
||||
|
||||
9. The Free Software Foundation may publish revised and/or new versions
|
||||
of the General Public License from time to time. Such new versions will
|
||||
be similar in spirit to the present version, but may differ in detail to
|
||||
address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Program
|
||||
specifies a version number of this License which applies to it and "any
|
||||
later version", you have the option of following the terms and conditions
|
||||
either of that version or of any later version published by the Free
|
||||
Software Foundation. If the Program does not specify a version number of
|
||||
this License, you may choose any version ever published by the Free Software
|
||||
Foundation.
|
||||
|
||||
10. If you wish to incorporate parts of the Program into other free
|
||||
programs whose distribution conditions are different, write to the author
|
||||
to ask for permission. For software which is copyrighted by the Free
|
||||
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||
make exceptions for this. Our decision will be guided by the two goals
|
||||
of preserving the free status of all derivatives of our free software and
|
||||
of promoting the sharing and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||
REPAIR OR CORRECTION.
|
||||
|
||||
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Programs
|
||||
|
||||
If you develop a new program, and you want it to be of the greatest
|
||||
possible use to the public, the best way to achieve this is to make it
|
||||
free software which everyone can redistribute and change under these terms.
|
||||
|
||||
To do so, attach the following notices to the program. It is safest
|
||||
to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least
|
||||
the "copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the program's name and a brief idea of what it does.>
|
||||
Copyright (C) 19yy <name of author>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program 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.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
If the program is interactive, make it output a short notice like this
|
||||
when it starts in an interactive mode:
|
||||
|
||||
Gnomovision version 69, Copyright (C) 19yy name of author
|
||||
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||
This is free software, and you are welcome to redistribute it
|
||||
under certain conditions; type `show c' for details.
|
||||
|
||||
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||
parts of the General Public License. Of course, the commands you use may
|
||||
be called something other than `show w' and `show c'; they could even be
|
||||
mouse-clicks or menu items--whatever suits your program.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1989
|
||||
Ty Coon, President of Vice
|
||||
|
||||
This General Public License does not permit incorporating your program into
|
||||
proprietary programs. If your program is a subroutine library, you may
|
||||
consider it more useful to permit linking proprietary applications with the
|
||||
library. If this is what you want to do, use the GNU Library General
|
||||
Public License instead of this License.
|
481
COPYING.LGPL
Normal file
481
COPYING.LGPL
Normal file
@ -0,0 +1,481 @@
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
Version 2, June 1991
|
||||
|
||||
Copyright (C) 1991 Free Software Foundation, Inc.
|
||||
59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
Everyone is permitted to copy and distribute verbatim copies
|
||||
of this license document, but changing it is not allowed.
|
||||
|
||||
[This is the first released version of the library GPL. It is
|
||||
numbered 2 because it goes with version 2 of the ordinary GPL.]
|
||||
|
||||
Preamble
|
||||
|
||||
The licenses for most software are designed to take away your
|
||||
freedom to share and change it. By contrast, the GNU General Public
|
||||
Licenses are intended to guarantee your freedom to share and change
|
||||
free software--to make sure the software is free for all its users.
|
||||
|
||||
This license, the Library General Public License, applies to some
|
||||
specially designated Free Software Foundation software, and to any
|
||||
other libraries whose authors decide to use it. You can use it for
|
||||
your libraries, too.
|
||||
|
||||
When we speak of free software, we are referring to freedom, not
|
||||
price. Our General Public Licenses are designed to make sure that you
|
||||
have the freedom to distribute copies of free software (and charge for
|
||||
this service if you wish), that you receive source code or can get it
|
||||
if you want it, that you can change the software or use pieces of it
|
||||
in new free programs; and that you know you can do these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
anyone to deny you these rights or to ask you to surrender the rights.
|
||||
These restrictions translate to certain responsibilities for you if
|
||||
you distribute copies of the library, or if you modify it.
|
||||
|
||||
For example, if you distribute copies of the library, whether gratis
|
||||
or for a fee, you must give the recipients all the rights that we gave
|
||||
you. You must make sure that they, too, receive or can get the source
|
||||
code. If you link a program with the library, you must provide
|
||||
complete object files to the recipients so that they can relink them
|
||||
with the library, after making changes to the library and recompiling
|
||||
it. And you must show them these terms so they know their rights.
|
||||
|
||||
Our method of protecting your rights has two steps: (1) copyright
|
||||
the library, and (2) offer you this license which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
Also, for each distributor's protection, we want to make certain
|
||||
that everyone understands that there is no warranty for this free
|
||||
library. If the library is modified by someone else and passed on, we
|
||||
want its recipients to know that what they have is not the original
|
||||
version, so that any problems introduced by others will not reflect on
|
||||
the original authors' reputations.
|
||||
|
||||
Finally, any free program is threatened constantly by software
|
||||
patents. We wish to avoid the danger that companies distributing free
|
||||
software will individually obtain patent licenses, thus in effect
|
||||
transforming the program into proprietary software. To prevent this,
|
||||
we have made it clear that any patent must be licensed for everyone's
|
||||
free use or not licensed at all.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the ordinary
|
||||
GNU General Public License, which was designed for utility programs. This
|
||||
license, the GNU Library General Public License, applies to certain
|
||||
designated libraries. This license is quite different from the ordinary
|
||||
one; be sure to read it in full, and don't assume that anything in it is
|
||||
the same as in the ordinary license.
|
||||
|
||||
The reason we have a separate public license for some libraries is that
|
||||
they blur the distinction we usually make between modifying or adding to a
|
||||
program and simply using it. Linking a program with a library, without
|
||||
changing the library, is in some sense simply using the library, and is
|
||||
analogous to running a utility program or application program. However, in
|
||||
a textual and legal sense, the linked executable is a combined work, a
|
||||
derivative of the original library, and the ordinary General Public License
|
||||
treats it as such.
|
||||
|
||||
Because of this blurred distinction, using the ordinary General
|
||||
Public License for libraries did not effectively promote software
|
||||
sharing, because most developers did not use the libraries. We
|
||||
concluded that weaker conditions might promote sharing better.
|
||||
|
||||
However, unrestricted linking of non-free programs would deprive the
|
||||
users of those programs of all benefit from the free status of the
|
||||
libraries themselves. This Library General Public License is intended to
|
||||
permit developers of non-free programs to use free libraries, while
|
||||
preserving your freedom as a user of such programs to change the free
|
||||
libraries that are incorporated in them. (We have not seen how to achieve
|
||||
this as regards changes in header files, but we have achieved it as regards
|
||||
changes in the actual functions of the Library.) The hope is that this
|
||||
will lead to faster development of free libraries.
|
||||
|
||||
The precise terms and conditions for copying, distribution and
|
||||
modification follow. Pay close attention to the difference between a
|
||||
"work based on the library" and a "work that uses the library". The
|
||||
former contains code derived from the library, while the latter only
|
||||
works together with the library.
|
||||
|
||||
Note that it is possible for a library to be covered by the ordinary
|
||||
General Public License rather than by this special one.
|
||||
|
||||
GNU LIBRARY GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library which
|
||||
contains a notice placed by the copyright holder or other authorized
|
||||
party saying it may be distributed under the terms of this Library
|
||||
General Public License (also called "this License"). Each licensee is
|
||||
addressed as "you".
|
||||
|
||||
A "library" means a collection of software functions and/or data
|
||||
prepared so as to be conveniently linked with application programs
|
||||
(which use some of those functions and data) to form executables.
|
||||
|
||||
The "Library", below, refers to any such software library or work
|
||||
which has been distributed under these terms. A "work based on the
|
||||
Library" means either the Library or any derivative work under
|
||||
copyright law: that is to say, a work containing the Library or a
|
||||
portion of it, either verbatim or with modifications and/or translated
|
||||
straightforwardly into another language. (Hereinafter, translation is
|
||||
included without limitation in the term "modification".)
|
||||
|
||||
"Source code" for a work means the preferred form of the work for
|
||||
making modifications to it. For a library, complete source code means
|
||||
all the source code for all modules it contains, plus any associated
|
||||
interface definition files, plus the scripts used to control compilation
|
||||
and installation of the library.
|
||||
|
||||
Activities other than copying, distribution and modification are not
|
||||
covered by this License; they are outside its scope. The act of
|
||||
running a program using the Library is not restricted, and output from
|
||||
such a program is covered only if its contents constitute a work based
|
||||
on the Library (independent of the use of the Library in a tool for
|
||||
writing it). Whether that is true depends on what the Library does
|
||||
and what the program that uses the Library does.
|
||||
|
||||
1. You may copy and distribute verbatim copies of the Library's
|
||||
complete source code as you receive it, in any medium, provided that
|
||||
you conspicuously and appropriately publish on each copy an
|
||||
appropriate copyright notice and disclaimer of warranty; keep intact
|
||||
all the notices that refer to this License and to the absence of any
|
||||
warranty; and distribute a copy of this License along with the
|
||||
Library.
|
||||
|
||||
You may charge a fee for the physical act of transferring a copy,
|
||||
and you may at your option offer warranty protection in exchange for a
|
||||
fee.
|
||||
|
||||
2. You may modify your copy or copies of the Library or any portion
|
||||
of it, thus forming a work based on the Library, and copy and
|
||||
distribute such modifications or work under the terms of Section 1
|
||||
above, provided that you also meet all of these conditions:
|
||||
|
||||
a) The modified work must itself be a software library.
|
||||
|
||||
b) You must cause the files modified to carry prominent notices
|
||||
stating that you changed the files and the date of any change.
|
||||
|
||||
c) You must cause the whole of the work to be licensed at no
|
||||
charge to all third parties under the terms of this License.
|
||||
|
||||
d) If a facility in the modified Library refers to a function or a
|
||||
table of data to be supplied by an application program that uses
|
||||
the facility, other than as an argument passed when the facility
|
||||
is invoked, then you must make a good faith effort to ensure that,
|
||||
in the event an application does not supply such function or
|
||||
table, the facility still operates, and performs whatever part of
|
||||
its purpose remains meaningful.
|
||||
|
||||
(For example, a function in a library to compute square roots has
|
||||
a purpose that is entirely well-defined independent of the
|
||||
application. Therefore, Subsection 2d requires that any
|
||||
application-supplied function or table used by this function must
|
||||
be optional: if the application does not supply it, the square
|
||||
root function must still compute square roots.)
|
||||
|
||||
These requirements apply to the modified work as a whole. If
|
||||
identifiable sections of that work are not derived from the Library,
|
||||
and can be reasonably considered independent and separate works in
|
||||
themselves, then this License, and its terms, do not apply to those
|
||||
sections when you distribute them as separate works. But when you
|
||||
distribute the same sections as part of a whole which is a work based
|
||||
on the Library, the distribution of the whole must be on the terms of
|
||||
this License, whose permissions for other licensees extend to the
|
||||
entire whole, and thus to each and every part regardless of who wrote
|
||||
it.
|
||||
|
||||
Thus, it is not the intent of this section to claim rights or contest
|
||||
your rights to work written entirely by you; rather, the intent is to
|
||||
exercise the right to control the distribution of derivative or
|
||||
collective works based on the Library.
|
||||
|
||||
In addition, mere aggregation of another work not based on the Library
|
||||
with the Library (or with a work based on the Library) on a volume of
|
||||
a storage or distribution medium does not bring the other work under
|
||||
the scope of this License.
|
||||
|
||||
3. You may opt to apply the terms of the ordinary GNU General Public
|
||||
License instead of this License to a given copy of the Library. To do
|
||||
this, you must alter all the notices that refer to this License, so
|
||||
that they refer to the ordinary GNU General Public License, version 2,
|
||||
instead of to this License. (If a newer version than version 2 of the
|
||||
ordinary GNU General Public License has appeared, then you can specify
|
||||
that version instead if you wish.) Do not make any other change in
|
||||
these notices.
|
||||
|
||||
Once this change is made in a given copy, it is irreversible for
|
||||
that copy, so the ordinary GNU General Public License applies to all
|
||||
subsequent copies and derivative works made from that copy.
|
||||
|
||||
This option is useful when you wish to copy part of the code of
|
||||
the Library into a program that is not a library.
|
||||
|
||||
4. You may copy and distribute the Library (or a portion or
|
||||
derivative of it, under Section 2) in object code or executable form
|
||||
under the terms of Sections 1 and 2 above provided that you accompany
|
||||
it with the complete corresponding machine-readable source code, which
|
||||
must be distributed under the terms of Sections 1 and 2 above on a
|
||||
medium customarily used for software interchange.
|
||||
|
||||
If distribution of object code is made by offering access to copy
|
||||
from a designated place, then offering equivalent access to copy the
|
||||
source code from the same place satisfies the requirement to
|
||||
distribute the source code, even though third parties are not
|
||||
compelled to copy the source along with the object code.
|
||||
|
||||
5. A program that contains no derivative of any portion of the
|
||||
Library, but is designed to work with the Library by being compiled or
|
||||
linked with it, is called a "work that uses the Library". Such a
|
||||
work, in isolation, is not a derivative work of the Library, and
|
||||
therefore falls outside the scope of this License.
|
||||
|
||||
However, linking a "work that uses the Library" with the Library
|
||||
creates an executable that is a derivative of the Library (because it
|
||||
contains portions of the Library), rather than a "work that uses the
|
||||
library". The executable is therefore covered by this License.
|
||||
Section 6 states terms for distribution of such executables.
|
||||
|
||||
When a "work that uses the Library" uses material from a header file
|
||||
that is part of the Library, the object code for the work may be a
|
||||
derivative work of the Library even though the source code is not.
|
||||
Whether this is true is especially significant if the work can be
|
||||
linked without the Library, or if the work is itself a library. The
|
||||
threshold for this to be true is not precisely defined by law.
|
||||
|
||||
If such an object file uses only numerical parameters, data
|
||||
structure layouts and accessors, and small macros and small inline
|
||||
functions (ten lines or less in length), then the use of the object
|
||||
file is unrestricted, regardless of whether it is legally a derivative
|
||||
work. (Executables containing this object code plus portions of the
|
||||
Library will still fall under Section 6.)
|
||||
|
||||
Otherwise, if the work is a derivative of the Library, you may
|
||||
distribute the object code for the work under the terms of Section 6.
|
||||
Any executables containing that work also fall under Section 6,
|
||||
whether or not they are linked directly with the Library itself.
|
||||
|
||||
6. As an exception to the Sections above, you may also compile or
|
||||
link a "work that uses the Library" with the Library to produce a
|
||||
work containing portions of the Library, and distribute that work
|
||||
under terms of your choice, provided that the terms permit
|
||||
modification of the work for the customer's own use and reverse
|
||||
engineering for debugging such modifications.
|
||||
|
||||
You must give prominent notice with each copy of the work that the
|
||||
Library is used in it and that the Library and its use are covered by
|
||||
this License. You must supply a copy of this License. If the work
|
||||
during execution displays copyright notices, you must include the
|
||||
copyright notice for the Library among them, as well as a reference
|
||||
directing the user to the copy of this License. Also, you must do one
|
||||
of these things:
|
||||
|
||||
a) Accompany the work with the complete corresponding
|
||||
machine-readable source code for the Library including whatever
|
||||
changes were used in the work (which must be distributed under
|
||||
Sections 1 and 2 above); and, if the work is an executable linked
|
||||
with the Library, with the complete machine-readable "work that
|
||||
uses the Library", as object code and/or source code, so that the
|
||||
user can modify the Library and then relink to produce a modified
|
||||
executable containing the modified Library. (It is understood
|
||||
that the user who changes the contents of definitions files in the
|
||||
Library will not necessarily be able to recompile the application
|
||||
to use the modified definitions.)
|
||||
|
||||
b) Accompany the work with a written offer, valid for at
|
||||
least three years, to give the same user the materials
|
||||
specified in Subsection 6a, above, for a charge no more
|
||||
than the cost of performing this distribution.
|
||||
|
||||
c) If distribution of the work is made by offering access to copy
|
||||
from a designated place, offer equivalent access to copy the above
|
||||
specified materials from the same place.
|
||||
|
||||
d) Verify that the user has already received a copy of these
|
||||
materials or that you have already sent this user a copy.
|
||||
|
||||
For an executable, the required form of the "work that uses the
|
||||
Library" must include any data and utility programs needed for
|
||||
reproducing the executable from it. However, as a special exception,
|
||||
the source code distributed need not include anything that is normally
|
||||
distributed (in either source or binary form) with the major
|
||||
components (compiler, kernel, and so on) of the operating system on
|
||||
which the executable runs, unless that component itself accompanies
|
||||
the executable.
|
||||
|
||||
It may happen that this requirement contradicts the license
|
||||
restrictions of other proprietary libraries that do not normally
|
||||
accompany the operating system. Such a contradiction means you cannot
|
||||
use both them and the Library together in an executable that you
|
||||
distribute.
|
||||
|
||||
7. You may place library facilities that are a work based on the
|
||||
Library side-by-side in a single library together with other library
|
||||
facilities not covered by this License, and distribute such a combined
|
||||
library, provided that the separate distribution of the work based on
|
||||
the Library and of the other library facilities is otherwise
|
||||
permitted, and provided that you do these two things:
|
||||
|
||||
a) Accompany the combined library with a copy of the same work
|
||||
based on the Library, uncombined with any other library
|
||||
facilities. This must be distributed under the terms of the
|
||||
Sections above.
|
||||
|
||||
b) Give prominent notice with the combined library of the fact
|
||||
that part of it is a work based on the Library, and explaining
|
||||
where to find the accompanying uncombined form of the same work.
|
||||
|
||||
8. You may not copy, modify, sublicense, link with, or distribute
|
||||
the Library except as expressly provided under this License. Any
|
||||
attempt otherwise to copy, modify, sublicense, link with, or
|
||||
distribute the Library is void, and will automatically terminate your
|
||||
rights under this License. However, parties who have received copies,
|
||||
or rights, from you under this License will not have their licenses
|
||||
terminated so long as such parties remain in full compliance.
|
||||
|
||||
9. You are not required to accept this License, since you have not
|
||||
signed it. However, nothing else grants you permission to modify or
|
||||
distribute the Library or its derivative works. These actions are
|
||||
prohibited by law if you do not accept this License. Therefore, by
|
||||
modifying or distributing the Library (or any work based on the
|
||||
Library), you indicate your acceptance of this License to do so, and
|
||||
all its terms and conditions for copying, distributing or modifying
|
||||
the Library or works based on it.
|
||||
|
||||
10. Each time you redistribute the Library (or any work based on the
|
||||
Library), the recipient automatically receives a license from the
|
||||
original licensor to copy, distribute, link with or modify the Library
|
||||
subject to these terms and conditions. You may not impose any further
|
||||
restrictions on the recipients' exercise of the rights granted herein.
|
||||
You are not responsible for enforcing compliance by third parties to
|
||||
this License.
|
||||
|
||||
11. If, as a consequence of a court judgment or allegation of patent
|
||||
infringement or for any other reason (not limited to patent issues),
|
||||
conditions are imposed on you (whether by court order, agreement or
|
||||
otherwise) that contradict the conditions of this License, they do not
|
||||
excuse you from the conditions of this License. If you cannot
|
||||
distribute so as to satisfy simultaneously your obligations under this
|
||||
License and any other pertinent obligations, then as a consequence you
|
||||
may not distribute the Library at all. For example, if a patent
|
||||
license would not permit royalty-free redistribution of the Library by
|
||||
all those who receive copies directly or indirectly through you, then
|
||||
the only way you could satisfy both it and this License would be to
|
||||
refrain entirely from distribution of the Library.
|
||||
|
||||
If any portion of this section is held invalid or unenforceable under any
|
||||
particular circumstance, the balance of the section is intended to apply,
|
||||
and the section as a whole is intended to apply in other circumstances.
|
||||
|
||||
It is not the purpose of this section to induce you to infringe any
|
||||
patents or other property right claims or to contest validity of any
|
||||
such claims; this section has the sole purpose of protecting the
|
||||
integrity of the free software distribution system which is
|
||||
implemented by public license practices. Many people have made
|
||||
generous contributions to the wide range of software distributed
|
||||
through that system in reliance on consistent application of that
|
||||
system; it is up to the author/donor to decide if he or she is willing
|
||||
to distribute software through any other system and a licensee cannot
|
||||
impose that choice.
|
||||
|
||||
This section is intended to make thoroughly clear what is believed to
|
||||
be a consequence of the rest of this License.
|
||||
|
||||
12. If the distribution and/or use of the Library is restricted in
|
||||
certain countries either by patents or by copyrighted interfaces, the
|
||||
original copyright holder who places the Library under this License may add
|
||||
an explicit geographical distribution limitation excluding those countries,
|
||||
so that distribution is permitted only in or among countries not thus
|
||||
excluded. In such case, this License incorporates the limitation as if
|
||||
written in the body of this License.
|
||||
|
||||
13. The Free Software Foundation may publish revised and/or new
|
||||
versions of the Library General Public License from time to time.
|
||||
Such new versions will be similar in spirit to the present version,
|
||||
but may differ in detail to address new problems or concerns.
|
||||
|
||||
Each version is given a distinguishing version number. If the Library
|
||||
specifies a version number of this License which applies to it and
|
||||
"any later version", you have the option of following the terms and
|
||||
conditions either of that version or of any later version published by
|
||||
the Free Software Foundation. If the Library does not specify a
|
||||
license version number, you may choose any version ever published by
|
||||
the Free Software Foundation.
|
||||
|
||||
14. If you wish to incorporate parts of the Library into other free
|
||||
programs whose distribution conditions are incompatible with these,
|
||||
write to the author to ask for permission. For software which is
|
||||
copyrighted by the Free Software Foundation, write to the Free
|
||||
Software Foundation; we sometimes make exceptions for this. Our
|
||||
decision will be guided by the two goals of preserving the free status
|
||||
of all derivatives of our free software and of promoting the sharing
|
||||
and reuse of software generally.
|
||||
|
||||
NO WARRANTY
|
||||
|
||||
15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
|
||||
WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
|
||||
EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
|
||||
OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
|
||||
KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
|
||||
LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
|
||||
THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||
|
||||
16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
|
||||
WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
|
||||
AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
|
||||
FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
|
||||
CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
|
||||
LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
|
||||
RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
|
||||
FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
|
||||
SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
|
||||
DAMAGES.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
How to Apply These Terms to Your New Libraries
|
||||
|
||||
If you develop a new library, and you want it to be of the greatest
|
||||
possible use to the public, we recommend making it free software that
|
||||
everyone can redistribute and change. You can do so by permitting
|
||||
redistribution under these terms (or, alternatively, under the terms of the
|
||||
ordinary General Public License).
|
||||
|
||||
To apply these terms, attach the following notices to the library. It is
|
||||
safest to attach them to the start of each source file to most effectively
|
||||
convey the exclusion of warranty; and each file should have at least the
|
||||
"copyright" line and a pointer to where the full notice is found.
|
||||
|
||||
<one line to give the library's name and a brief idea of what it does.>
|
||||
Copyright (C) <year> <name of author>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2 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
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library; if not, write to the Free
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
Also add information on how to contact you by electronic and paper mail.
|
||||
|
||||
You should also get your employer (if you work as a programmer) or your
|
||||
school, if any, to sign a "copyright disclaimer" for the library, if
|
||||
necessary. Here is a sample; alter the names:
|
||||
|
||||
Yoyodyne, Inc., hereby disclaims all copyright interest in the
|
||||
library `Frob' (a library for tweaking knobs) written by James Random Hacker.
|
||||
|
||||
<signature of Ty Coon>, 1 April 1990
|
||||
Ty Coon, President of Vice
|
||||
|
||||
That's all there is to it!
|
46
Makefile
Normal file
46
Makefile
Normal file
@ -0,0 +1,46 @@
|
||||
#
|
||||
# GNU Makefile
|
||||
#
|
||||
# Useful targets
|
||||
#
|
||||
# all : build all libraries and programs in the default configuration (currently 'release')
|
||||
# debug : build all libraries and programs in debug mode
|
||||
# release : build all libraries and programs in release mode
|
||||
# test : run the unit and stream tests
|
||||
# clean : remove all non-distro files
|
||||
#
|
||||
|
||||
all: libFLAC flac test_streams test_unit
|
||||
|
||||
DEFAULT_CONFIG = release
|
||||
|
||||
CONFIG = $(DEFAULT_CONFIG)
|
||||
|
||||
debug : CONFIG = debug
|
||||
release : CONFIG = release
|
||||
|
||||
debug : all
|
||||
release : all
|
||||
|
||||
libFLAC:
|
||||
(cd src/$@ ; make $(CONFIG))
|
||||
|
||||
flac: libFLAC
|
||||
(cd src/$@ ; make $(CONFIG))
|
||||
|
||||
test_streams: libFLAC
|
||||
(cd src/$@ ; make $(CONFIG))
|
||||
|
||||
test_unit: libFLAC
|
||||
(cd src/$@ ; make $(CONFIG))
|
||||
|
||||
test: debug
|
||||
(cd test ; make)
|
||||
|
||||
clean:
|
||||
-(cd src/libFLAC ; make clean)
|
||||
-(cd src/flac ; make clean)
|
||||
-(cd src/plugin_xmms ; make clean)
|
||||
-(cd src/test_streams ; make clean)
|
||||
-(cd src/test_unit ; make clean)
|
||||
-(cd test ; make clean)
|
44
README
Normal file
44
README
Normal file
@ -0,0 +1,44 @@
|
||||
==========
|
||||
FLAC - 0.2
|
||||
==========
|
||||
|
||||
This is the source release for the FLAC project. The
|
||||
reference encoder/decoder library 'libFLAC' is released
|
||||
under the LGPL (see COPYING.LGPL). This means the code
|
||||
in include/FLAC/ and src/libFLAC/. All other code is
|
||||
covered by the GPL (see COPYING.GPL). See
|
||||
|
||||
doc/index.html
|
||||
|
||||
for full documentation.
|
||||
|
||||
A brief description of the directory tree:
|
||||
|
||||
build/ makefile templates for building
|
||||
doc/ the HTML documentation
|
||||
include/ public include files for libFLAC
|
||||
obj/ the compiled libraries and executables will
|
||||
end up here
|
||||
src/ the source code and private headers
|
||||
test/ the test scripts
|
||||
|
||||
|
||||
=============================
|
||||
Building in a GNU environment
|
||||
=============================
|
||||
|
||||
All files called 'Makefile' are GNUmake files. To build all
|
||||
libraries and programs, just 'make all' from the top-level
|
||||
directory. To run the tests, just 'make test'.
|
||||
|
||||
Everything can be built in either debug or release mode.
|
||||
See the Makefiles for details.
|
||||
|
||||
|
||||
==================
|
||||
Building with MSVC
|
||||
==================
|
||||
|
||||
There is no overall make system for MSVC but the individual
|
||||
source directories with a 'Makefile.vc' file in them allow
|
||||
building with MSVC. Just 'nmake /f Makefile.vc'.
|
37
build/exe.mk
Normal file
37
build/exe.mk
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# GNU makefile fragment for building an executable
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
# LINKAGE can be forced to -static or -dynamic from invocation if desired, but it defaults to -static
|
||||
LINKAGE = -static
|
||||
LINK = gcc $(LINKAGE)
|
||||
BINPATH = ../../obj/bin
|
||||
LIBPATH = ../../obj/lib
|
||||
PROGRAM = $(BINPATH)/$(PROGRAM_NAME)
|
||||
|
||||
all : release
|
||||
|
||||
debug : CFLAGS = -g -O0 -DDEBUG $(DEBUG_CFLAGS) -Wall -W $(INCLUDES)
|
||||
release : CFLAGS = -O3 -DNDEBUG $(RELEASE_CFLAGS) -Wall -W $(INCLUDES)
|
||||
|
||||
LFLAGS = -L$(LIBPATH)
|
||||
|
||||
debug : $(PROGRAM)
|
||||
release : $(PROGRAM)
|
||||
|
||||
$(PROGRAM) : $(OBJS)
|
||||
$(LINK) -o $@ $(OBJS) $(LFLAGS) $(LIBS)
|
||||
|
||||
%.o : %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
%.i : %.c
|
||||
$(CC) $(CFLAGS) -E $< -o $@
|
||||
|
||||
.PHONY : clean
|
||||
clean :
|
||||
-rm -f $(OBJS) $(PROGRAM)
|
||||
|
||||
.PHONY : depend
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) $(INCLUDES) -- *.c
|
39
build/lib.mk
Normal file
39
build/lib.mk
Normal file
@ -0,0 +1,39 @@
|
||||
#
|
||||
# GNU makefile fragment for building a library
|
||||
#
|
||||
|
||||
CC = gcc
|
||||
LINK = ar cru
|
||||
LINKD = ld -G
|
||||
LIBPATH = ../../obj/lib
|
||||
STATIC_LIB = $(LIBPATH)/$(LIB_NAME).a
|
||||
DYNAMIC_LIB = $(LIBPATH)/$(LIB_NAME).so
|
||||
|
||||
all : release
|
||||
|
||||
debug : CFLAGS = -g -O0 -DDEBUG $(DEBUG_CFLAGS) -Wall -W $(INCLUDES)
|
||||
release : CFLAGS = -O3 -DNDEBUG $(RELEASE_CFLAGS) -Wall -W $(INCLUDES)
|
||||
|
||||
LFLAGS = -L$(LIBPATH)
|
||||
|
||||
debug : $(STATIC_LIB) $(DYNAMIC_LIB)
|
||||
release : $(STATIC_LIB) $(DYNAMIC_LIB)
|
||||
|
||||
$(STATIC_LIB) : $(OBJS)
|
||||
$(LINK) $@ $(OBJS)
|
||||
|
||||
$(DYNAMIC_LIB) : $(OBJS)
|
||||
$(LINKD) -o $@ $(OBJS) $(LFLAGS) $(LIBS)
|
||||
|
||||
%.o : %.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@
|
||||
%.i : %.c
|
||||
$(CC) $(CFLAGS) -E $< -o $@
|
||||
|
||||
.PHONY : clean
|
||||
clean :
|
||||
-rm -f $(OBJS) $(STATIC_LIB) $(DYNAMIC_LIB)
|
||||
|
||||
.PHONY : depend
|
||||
depend:
|
||||
makedepend -- $(CFLAGS) $(INCLUDES) -- *.c
|
654
doc/comparison.html
Normal file
654
doc/comparison.html
Normal file
@ -0,0 +1,654 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - comparison</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> comparison </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">comparison</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
The purpose of the comparison page is not only to show how compression ratios and encoding times using the flac reference encoder compare to other lossless encoders, but also to compare features (for example, some coders archive only and files must be uncompressed completely before playback can start). Keep a few things in mind:
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
As far as I know, only two of the lossless encoders out there (flac and Shorten) are truly free. Most others give out free binaries, but without access to the source, you are leaving your data to the whim of the maintainer for eternity; you have no way to port the program to another OS or fix it if it breaks. This can be a serious drawback unless the format has world-class clout (like MP3).
|
||||
</LI>
|
||||
<LI>
|
||||
The compression ratios and times are representative only of the reference encoder. They are not indicative of the limits of all FLAC encoders or the FLAC format itself since the format is open and extensible, and anyone is free to write a better FLAC encoder. And it is almost certain that the reference encoder itself will improve.
|
||||
</LI>
|
||||
<LI>
|
||||
Since FLAC supports streaming, it is at a slight disadvantage to the formats that don't because they don't have the extra overhead of all those frame headers.
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
I make an effort to keep this information as accurate as possible, but if any of the data is wrong, <A HREF="mailto:jcoalson@users.sourceforge.net">let me know</A> and I'll correct it.
|
||||
</P>
|
||||
<P>
|
||||
Reviewed encoders:
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
<A HREF="index.html">flac</A> of course.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://www-ft.ee.tu-berlin.de/~liebchen/lpac.html">LPAC</A> - A closed source codec. At least it's available for more than just Windows, but there's only a Winamp plugin.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://www.monkeysaudio.com/">Monkey's Audio</A> - A closed source, Windows-only codec, with a Winamp plugin.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://www.jpg.com/products/sound.html">Pegasus-SPS</A> - A closed source, Windows-only codec.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://rksoft.virtualave.net/">RKAU</A> - A closed source, Windows-only codec.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://www.softsound.com/Shorten.html">Shorten</A> - A.J. Robinson's well-known codec; source is available <A HREF="http://rpmfind.net/linux/rpm2html/search.php?query=shorten">here</A>.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://www.gadgetlabs.com/wavezip.htm">WaveZIP</A> - A closed source, Windows-only archiver. Uses the <A HREF="http://members.aol.com/_ht_a/sndspace/index.html">MUSICompress</A>[tm] engine which supposedly has a patent.
|
||||
</LI>
|
||||
<LI>
|
||||
<A HREF="http://www.wavpack.com/">WavPack</A> - A closed source, Windows-only archiver.
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
Encoders I couldn't get a copy of:
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
AudioPak
|
||||
</LI>
|
||||
<LI>
|
||||
WavARC
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
If you take maximum compression ratio and speed out of the picture (as you will see later, most coders exhibit similar performance), here is a subjective sort based on overall "usefulness". As far as features go, having source code gives you the most freedom since you can add anything you need that is missing; besides, open source projects tend to get better faster than closed source ones. A close second (depending on the user) would be OS support or plugin support.
|
||||
</P>
|
||||
<TABLE WIDTH="100%" BORDER="0" CELLSPACING="0" CELLPADDING="0" BGCOLOR="#EEEED4"><TR><TD>
|
||||
<TABLE WIDTH="100%" BORDER="1" BGCOLOR="#EEEED4">
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT">
|
||||
<FONT SIZE="+1"><B>Codec</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Source Available?</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Plugins Available?</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Streamable?</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Seekable?</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Cost</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>OS support</B></FONT>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
flac v0.2
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
YES (Winamp, XMMS)
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
FREE
|
||||
</TD>
|
||||
<TD>
|
||||
ANY (source)
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
Shorten v2.3a
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
YES (Winamp plugin somewhere)
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
FREE
|
||||
</TD>
|
||||
<TD>
|
||||
ANY (source)
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
LPAC v1.20 (codec 2.0)
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
YES (Winamp only)
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no?
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
FREE
|
||||
</TD>
|
||||
<TD>
|
||||
Windows/Linux/Solaris
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
Monkey's Audio v3.71
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
YES (Winamp only)
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
FREE
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
Windows only
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
RKAU v1.06
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
YES (Winamp only)
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
YES
|
||||
</TD>
|
||||
<TD>
|
||||
FREE
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
Windows only
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
WavPack v3.6
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
FREE
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
Windows only
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
WaveZIP v2
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD>
|
||||
FREE (24-bit costs $)
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
Windows only
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" BGCOLOR="#F4F4CC">
|
||||
Pegasus-SPS
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
no
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
$39 (free trial)
|
||||
</TD>
|
||||
<TD BGCOLOR="#D3D4C5">
|
||||
Windows only
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD></TR></TABLE>
|
||||
</P>
|
||||
<P>
|
||||
The machine I used for encoding the test files is a PII-333 with 256 megs of RAM, running Windows NT 4.0 SP5. Unfortunately, Windows is the lowest-common-denominator platform for all the encoders.
|
||||
</P>
|
||||
<P>
|
||||
The input corpus currently consists entirely of CD music tracks. In the future it may include more kinds of input (like speech, other sample rates, etc). There are ??? tracks whose genres range from death metal to pop to western classical to Indian classical.
|
||||
</P>
|
||||
<P>
|
||||
In all tables, the results are sorter by compression ratio, which is compressed size / uncompressed size. The first table is a summary of results on all input tracks. The remaining table shows the results of the encoders on each track.
|
||||
</P>
|
||||
<P>
|
||||
Some interesting things to note: LPAC quality settings are not too stable with -r (which allows seeking during playback) turned on. In most cases the 'normal' mode makes the smallest file, and much faster. RKAU also has a tendency to get bigger in the 'high' mode. Shorten's method for quantizing and transmitting the LPC coefficients is not very good which is the main reason why the fixed predictors runs are both smaller and faster.
|
||||
</P>
|
||||
<P>
|
||||
Another ironic fact is that the encoders that are patented or cost money turn out to be the worst by most measures. SPS is so archane and crippled that I gave up trying to put together results for it after one track.
|
||||
</P>
|
||||
<P>
|
||||
<TABLE WIDTH="100%" BORDER="0" CELLSPACING="0" CELLPADDING="0" BGCOLOR="#EEEED4"><TR><TD>
|
||||
<TABLE WIDTH="100%" BORDER="1" BGCOLOR="#EEEED4">
|
||||
<TR>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Encoder</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Encode time</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Compressed size</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Compression ratio</B></FONT>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR><TD>Monkey's Audio 3.80 (extra high)</TD><TD>20:24.18</TD><TD>381.85 MB</TD><TD>0.5073</TD></TR>
|
||||
<TR BGCOLOR="#D3D4C5"><TD>RKAU 1.06 (normal)</TD><TD>52:53.46</TD><TD>383.36 MB</TD><TD>0.5093</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (high)</TD><TD>133:25.36</TD><TD>383.75 MB</TD><TD>0.5098</TD></TR>
|
||||
<TR BGCOLOR="#D3D4C5"><TD>Monkey's Audio 3.80 (high)</TD><TD>7:45.75</TD><TD>387.97 MB</TD><TD>0.5154</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, normal)</TD><TD>20:49.34</TD><TD>393.16 MB</TD><TD>0.5223</TD></TR>
|
||||
<TR BGCOLOR="#D3D4C5"><TD>LPAC 1.20 (-r, high)</TD><TD>88:20.18</TD><TD>393.12 MB</TD><TD>0.5223</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, extra high)</TD><TD>109:27.86</TD><TD>393.93 MB</TD><TD>0.5234</TD></TR>
|
||||
<TR BGCOLOR="#D3D4C5"><TD>flac 0.2 (-6)</TD><TD>41:11.46</TD><TD>399.30 MB</TD><TD>0.5305</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>10:05.48</TD><TD>403.70 MB</TD><TD>0.5363</TD></TR>
|
||||
<TR BGCOLOR="#D3D4C5"><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>6:41.17</TD><TD>417.24 MB</TD><TD>0.5543</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>9:16.47</TD><TD>422.59 MB</TD><TD>0.5614</TD></TR>
|
||||
<TR BGCOLOR="#D3D4C5"><TD>WaveZip</TD><TD>8:24.17</TD><TD>435.06 MB</TD><TD>0.5780</TD></TR>
|
||||
</TABLE>
|
||||
</TD></TR></TABLE>
|
||||
</P>
|
||||
<P>
|
||||
Here are the results for each individual track.
|
||||
</P>
|
||||
<P>
|
||||
<TABLE WIDTH="100%" BORDER="0" CELLSPACING="0" CELLPADDING="0" BGCOLOR="#EEEED4"><TR><TD>
|
||||
<TABLE WIDTH="100%" BORDER="1" BGCOLOR="#EEEED4">
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT">
|
||||
<FONT SIZE="+1"><B>Track</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Encoder</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Encode time</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Compressed size</B></FONT>
|
||||
</TD>
|
||||
<TD BGCOLOR="#F4F4CC">
|
||||
<FONT SIZE="+1"><B>Compression ratio</B></FONT>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="14" BGCOLOR="#F4F4CC">
|
||||
Dream Theater<BR><I>6:00</I><BR>58.47 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>1:39.08</TD><TD>43.70 MB</TD><TD>0.7475</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:41.98</TD><TD>43.85 MB</TD><TD>0.7500</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>8:12.44</TD><TD>43.87 MB</TD><TD>0.7503</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>2:59.56</TD><TD>43.88 MB</TD><TD>0.7504</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>flac 0.2 (-6)</TD><TD>3:13.55</TD><TD>44.38 MB</TD><TD>0.7591</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>6:51.24</TD><TD>44.42 MB</TD><TD>0.7598</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>1:45.72</TD><TD>44.44 MB</TD><TD>0.7601</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, extra high)</TD><TD>7:50.80</TD><TD>44.44 MB</TD><TD>0.7601</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:47.79</TD><TD>44.74 MB</TD><TD>0.7653</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>0:49.21</TD><TD>45.37 MB</TD><TD>0.7760</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Pegasus-SPS</TD><TD>4:45.00</TD><TD>45.40 MB</TD><TD>0.7765</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:34.50</TD><TD>46.68 MB</TD><TD>0.7984</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WaveZip</TD><TD>0:38.99</TD><TD>47.22 MB</TD><TD>0.8077</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Tool<BR><I>Forty-six & 2</I><BR>64.25 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>1:48.94</TD><TD>39.30 MB</TD><TD>0.6116</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:33.43</TD><TD>39.51 MB</TD><TD>0.6149</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (normal)</TD><TD>3:34.75</TD><TD>39.93 MB</TD><TD>0.6214</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (high)</TD><TD>8:37.42</TD><TD>39.97 MB</TD><TD>0.6220</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>1:52.22</TD><TD>40.57 MB</TD><TD>0.6314</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>7:36.55</TD><TD>40.61 MB</TD><TD>0.6320</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>9:49.64</TD><TD>40.71 MB</TD><TD>0.6336</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>3:35.02</TD><TD>41.01 MB</TD><TD>0.6383</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>0:52.37</TD><TD>41.72 MB</TD><TD>0.6492</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:50.22</TD><TD>43.05 MB</TD><TD>0.6701</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:35.93</TD><TD>43.19 MB</TD><TD>0.6722</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:42.84</TD><TD>44.52 MB</TD><TD>0.6930</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Cannibal Corpse<BR><I>Mummified In Barbed Wire</I><BR>33.37 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>0:49.20</TD><TD>23.47 MB</TD><TD>0.7033</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:23.25</TD><TD>23.66 MB</TD><TD>0.7087</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>1:01.16</TD><TD>23.75 MB</TD><TD>0.7116</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>5:13.57</TD><TD>23.92 MB</TD><TD>0.7168</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>6:04.27</TD><TD>23.95 MB</TD><TD>0.7175</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>1:32.20</TD><TD>24.04 MB</TD><TD>0.7202</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>3:21.70</TD><TD>24.04 MB</TD><TD>0.7202</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>1:50.43</TD><TD>24.31 MB</TD><TD>0.7285</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:27.03</TD><TD>25.12 MB</TD><TD>0.7525</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>0:28.07</TD><TD>25.44 MB</TD><TD>0.7621</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:19.85</TD><TD>26.59 MB</TD><TD>0.7966</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:22.25</TD><TD>26.89 MB</TD><TD>0.8058</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Alanis Morisette<BR><I>Hand In My Pocket</I><BR>39.09 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>1:03.98</TD><TD>22.85 MB</TD><TD>0.5845</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:25.70</TD><TD>23.04 MB</TD><TD>0.5893</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>5:54.68</TD><TD>23.16 MB</TD><TD>0.5925</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>2:23.63</TD><TD>23.19 MB</TD><TD>0.5933</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>1:07.58</TD><TD>23.45 MB</TD><TD>0.6000</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>4:47.03</TD><TD>23.49 MB</TD><TD>0.6008</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>5:50.53</TD><TD>23.52 MB</TD><TD>0.6016</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>2:10.43</TD><TD>23.55 MB</TD><TD>0.6023</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>0:31.44</TD><TD>24.30 MB</TD><TD>0.6217</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:30.45</TD><TD>24.72 MB</TD><TD>0.6324</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:21.93</TD><TD>25.33 MB</TD><TD>0.6478</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:28.05</TD><TD>25.95 MB</TD><TD>0.6638</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Gloria Estefan<BR><I>Conga</I><BR>45.15 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>1:15.79</TD><TD>30.12 MB</TD><TD>0.6670</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:29.68</TD><TD>30.32 MB</TD><TD>0.6716</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>flac 0.2 (-6)</TD><TD>2:35.05</TD><TD>30.82 MB</TD><TD>0.6825</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (high)</TD><TD>6:52.69</TD><TD>30.83 MB</TD><TD>0.6828</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (normal)</TD><TD>2:41.42</TD><TD>30.87 MB</TD><TD>0.6837</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, normal)</TD><TD>1:20.29</TD><TD>31.03 MB</TD><TD>0.6871</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>0:37.15</TD><TD>31.04 MB</TD><TD>0.6875</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>5:33.21</TD><TD>31.06 MB</TD><TD>0.6879</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>6:39.28</TD><TD>31.11 MB</TD><TD>0.6889</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:35.51</TD><TD>31.76 MB</TD><TD>0.7033</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:24.65</TD><TD>32.62 MB</TD><TD>0.7223</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:29.42</TD><TD>33.02 MB</TD><TD>0.7313</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Cream<BR><I>White Room</I><BR>53.01 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>8:15.46</TD><TD>34.30 MB</TD><TD>0.6469</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>3:12.99</TD><TD>34.35 MB</TD><TD>0.6479</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>1:28.45</TD><TD>34.65 MB</TD><TD>0.6535</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:24.17</TD><TD>34.91 MB</TD><TD>0.6586</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>1:34.16</TD><TD>35.10 MB</TD><TD>0.6621</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>3:00.29</TD><TD>35.14 MB</TD><TD>0.6629</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, high)</TD><TD>6:39.29</TD><TD>35.17 MB</TD><TD>0.6633</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, extra high)</TD><TD>7:39.28</TD><TD>35.19 MB</TD><TD>0.6638</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:40.44</TD><TD>35.39 MB</TD><TD>0.6676</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>0:44.18</TD><TD>35.82 MB</TD><TD>0.6758</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:29.49</TD><TD>36.39 MB</TD><TD>0.6864</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:35.77</TD><TD>37.13 MB</TD><TD>0.7004</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Maurice Ravel<BR><I>Fanfare from "L'eventail de Jeanne"</I><BR>20.82 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (normal)</TD><TD>1:46.51</TD><TD>6.86 MB</TD><TD>0.3297</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (high)</TD><TD>3:53.54</TD><TD>6.90 MB</TD><TD>0.3316</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>0:30.30</TD><TD>7.09 MB</TD><TD>0.3407</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, normal)</TD><TD>0:30.93</TD><TD>7.47 MB</TD><TD>0.3586</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>3:06.27</TD><TD>7.48 MB</TD><TD>0.3591</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>2:21.16</TD><TD>7.48 MB</TD><TD>0.3593</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (high)</TD><TD>0:12.58</TD><TD>7.56 MB</TD><TD>0.3634</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>1:02.16</TD><TD>7.82 MB</TD><TD>0.3755</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>0:16.11</TD><TD>7.99 MB</TD><TD>0.3838</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:07.92</TD><TD>8.16 MB</TD><TD>0.3921</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:13.88</TD><TD>8.28 MB</TD><TD>0.3977</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:13.11</TD><TD>8.72 MB</TD><TD>0.4193</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Maurice Ravel<BR><I>String Quartet (4th movement)</I><BR>56.18 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>1:29.26</TD><TD>20.87 MB</TD><TD>0.3715</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>3:51.42</TD><TD>21.46 MB</TD><TD>0.3820</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (high)</TD><TD>0:34.29</TD><TD>21.55 MB</TD><TD>0.3836</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (high)</TD><TD>10:39.05</TD><TD>21.56 MB</TD><TD>0.3838</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, high)</TD><TD>6:28.14</TD><TD>22.30 MB</TD><TD>0.3969</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, normal)</TD><TD>1:28.02</TD><TD>22.32 MB</TD><TD>0.3972</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>8:13.86</TD><TD>22.38 MB</TD><TD>0.3983</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>0:43.84</TD><TD>22.53 MB</TD><TD>0.4010</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>flac 0.2 (-6)</TD><TD>3:00.34</TD><TD>22.85 MB</TD><TD>0.4067</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:29.33</TD><TD>23.63 MB</TD><TD>0.4205</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:38.05</TD><TD>25.58 MB</TD><TD>0.4552</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:36.60</TD><TD>25.84 MB</TD><TD>0.4600</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Sergei Prokofiev<BR><I>Piano Concerto No.3 (3rd movement)</I><BR>100.68 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>2:37.54</TD><TD>34.55 MB</TD><TD>0.3431</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>6:34.97</TD><TD>35.31 MB</TD><TD>0.3507</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (high)</TD><TD>1:00.47</TD><TD>35.46 MB</TD><TD>0.3521</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>10:12.47</TD><TD>35.74 MB</TD><TD>0.3549</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>18:34.20</TD><TD>35.80 MB</TD><TD>0.3555</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, extra high)</TD><TD>12:18.79</TD><TD>35.83 MB</TD><TD>0.3558</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>2:33.43</TD><TD>36.05 MB</TD><TD>0.3580</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>1:17.06</TD><TD>37.88 MB</TD><TD>0.3762</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>flac 0.2 (-6)</TD><TD>5:15.13</TD><TD>38.56 MB</TD><TD>0.3830</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:50.03</TD><TD>39.34 MB</TD><TD>0.3907</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WaveZip</TD><TD>1:05.60</TD><TD>43.67 MB</TD><TD>0.4337</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>1:09.86</TD><TD>45.36 MB</TD><TD>0.4505</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Frederic Chopin<BR><I>Prelude No.24 in d minor</I><BR>27.46 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>0:42.69</TD><TD>10.53 MB</TD><TD>0.3834</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:19.69</TD><TD>10.77 MB</TD><TD>0.3921</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, high)</TD><TD>3:21.61</TD><TD>10.91 MB</TD><TD>0.3973</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, normal)</TD><TD>0:41.79</TD><TD>10.92 MB</TD><TD>0.3976</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>3:56.36</TD><TD>10.93 MB</TD><TD>0.3979</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>1:58.42</TD><TD>10.97 MB</TD><TD>0.3994</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>5:20.71</TD><TD>11.21 MB</TD><TD>0.4083</TD></TR>
|
||||
<TR><TD>WavPack 3.6 (high)</TD><TD>0:22.32</TD><TD>11.52 MB</TD><TD>0.4193</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>flac 0.2 (-6)</TD><TD>1:26.66</TD><TD>11.77 MB</TD><TD>0.4285</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:13.56</TD><TD>12.01 MB</TD><TD>0.4374</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WaveZip</TD><TD>0:18.75</TD><TD>13.08 MB</TD><TD>0.4765</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:20.61</TD><TD>14.39 MB</TD><TD>0.5239</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
Domenico Scarlatti<BR><I>Sonata K.42 (arr.Yepes for guitar)</I><BR>16.39 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>0:25.79</TD><TD>6.96 MB</TD><TD>0.4245</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (high)</TD><TD>3:09.40</TD><TD>6.96 MB</TD><TD>0.4246</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (normal)</TD><TD>1:14.43</TD><TD>6.97 MB</TD><TD>0.4252</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:10.28</TD><TD>7.14 MB</TD><TD>0.4356</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>0:25.98</TD><TD>7.27 MB</TD><TD>0.4436</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>2:21.30</TD><TD>7.34 MB</TD><TD>0.4480</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>3:00.91</TD><TD>7.38 MB</TD><TD>0.4500</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>0:53.18</TD><TD>7.41 MB</TD><TD>0.4519</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>0:13.17</TD><TD>7.41 MB</TD><TD>0.4520</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:07.99</TD><TD>7.47 MB</TD><TD>0.4558</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WaveZip</TD><TD>0:10.56</TD><TD>7.83 MB</TD><TD>0.4781</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:10.91</TD><TD>8.20 MB</TD><TD>0.5001</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
The Benedictine Monks of<BR>Santo Domingo de Silos<BR><I>Laetatus sum</I><BR>24.26 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>3:15.29</TD><TD>12.21 MB</TD><TD>0.5031</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>1:25.48</TD><TD>12.21 MB</TD><TD>0.5034</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>0:41.19</TD><TD>12.47 MB</TD><TD>0.5138</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>0:15.69</TD><TD>12.68 MB</TD><TD>0.5228</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, normal)</TD><TD>0:41.22</TD><TD>12.75 MB</TD><TD>0.5253</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, high)</TD><TD>3:40.65</TD><TD>12.88 MB</TD><TD>0.5309</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>4:53.81</TD><TD>12.92 MB</TD><TD>0.5323</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>1:22.09</TD><TD>12.92 MB</TD><TD>0.5324</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>0:20.21</TD><TD>13.15 MB</TD><TD>0.5420</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>0:12.71</TD><TD>13.28 MB</TD><TD>0.5475</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>0:17.35</TD><TD>13.41 MB</TD><TD>0.5527</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>0:16.37</TD><TD>13.72 MB</TD><TD>0.5655</TD></TR>
|
||||
<TR>
|
||||
<TD ALIGN="RIGHT" ROWSPAN="13" BGCOLOR="#F4F4CC">
|
||||
L. Subramaniam<BR><I>Raga Sivapriya</I><BR>213.56 MB
|
||||
</TD>
|
||||
<TD> </TD><TD> </TD><TD> </TD><TD> </TD>
|
||||
</TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>RKAU 1.06 (high)</TD><TD>47:18.78</TD><TD>92.94 MB</TD><TD>0.4351</TD></TR>
|
||||
<TR><TD>RKAU 1.06 (normal)</TD><TD>19:37.68</TD><TD>93.31 MB</TD><TD>0.4369</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Monkey's Audio (extra high)</TD><TD>5:51.97</TD><TD>95.30 MB</TD><TD>0.4462</TD></TR>
|
||||
<TR><TD>Monkey's Audio (high)</TD><TD>2:14.54</TD><TD>97.52 MB</TD><TD>0.4566</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, high)</TD><TD>23:13.96</TD><TD>97.80 MB</TD><TD>0.4579</TD></TR>
|
||||
<TR><TD>LPAC 1.20 (-r, normal)</TD><TD>5:46.84</TD><TD>98.04 MB</TD><TD>0.4590</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>LPAC 1.20 (-r, extra high)</TD><TD>30:04.06</TD><TD>98.10 MB</TD><TD>0.4593</TD></TR>
|
||||
<TR><TD>flac 0.2 (-6)</TD><TD>11:47.13</TD><TD>98.76 MB</TD><TD>0.4624</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>WavPack 3.6 (high)</TD><TD>2:50.35</TD><TD>99.53 MB</TD><TD>0.4660</TD></TR>
|
||||
<TR><TD>Shorten 2.3a (-p0 -b1024)</TD><TD>1:53.28</TD><TD>102.54 MB</TD><TD>0.4801</TD></TR>
|
||||
<TR BGCOLOR="D3D4C5"><TD>Shorten 2.3a (-p8 -b2048)</TD><TD>2:34.37</TD><TD>102.59 MB</TD><TD>0.4803</TD></TR>
|
||||
<TR><TD>WaveZip</TD><TD>2:25.86</TD><TD>107.47 MB</TD><TD>0.5032</TD></TR>
|
||||
</TABLE>
|
||||
</TD></TR></TABLE>
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
130
doc/developers.html
Normal file
130
doc/developers.html
Normal file
@ -0,0 +1,130 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - developers</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> developers </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">developers</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
FLAC is an open source project and we are happy to enlist the help of anyone who wants to contribute. You can do this to a limited extent through the <A HREF="http://sourceforge.net/mail/?group_id=13478">mailing list</A> but if you have major changes to make to the code it's best to <A HREF="http://sourceforge.net/project/memberlist.php?group_id=13478">sign up as a developer</A>. In either case, make sure to check out the <A HREF="goals.html">FLAC goals</A> first; there are some thing the we <B>don't</B> want added to FLAC, like copy protection and lossy compression.
|
||||
</P>
|
||||
<P>
|
||||
There are several areas that are especially important:
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
Converging on the <A HREF="format.html">bitstream format</A>. This is probably the single most important issue.
|
||||
</LI>
|
||||
<LI>
|
||||
Testing. This is a close second, since if you are a lossless encoder you have to be absolutely lossless for all input. The test suite has patterns that are designed to strain the encoder to the limit but more test cases would definitely help.
|
||||
</LI>
|
||||
<LI>
|
||||
Makefile fixups and code changes to work on more platforms. Both libFLAC and flac are ANSI C and use only the standard C library and math library, meaning ports should not be that difficult. Currently there is a GNU make system and makefiles for MSVC.
|
||||
</LI>
|
||||
<LI>
|
||||
More input plugins. Currently there are plugins for XMMS and Winamp. More is better!
|
||||
</LI>
|
||||
<LI>
|
||||
Speeding up the encoding. Encoding speed at average compression is a little slower than I would like. Improvements to the reference encoder that don't drastically obfuscate the code would be welcome.
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
Some other "nice-to-haves":
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
Improving the compression methods. Some suggestions: on the entropy coding side, try context-modeling the Rice paramter, using general Golomb coding and Huffman coding. On the prediction side, try some other methods for determining the LP coefficients (covariance method, Marple, Burg), or explore other kinds of modeling.
|
||||
</LI>
|
||||
<LI>
|
||||
A faster seek algorithm in the file decoder.
|
||||
</LI>
|
||||
<LI>
|
||||
A stream analyser that gives useful statistics for tuning or testing new algorithms.
|
||||
</LI>
|
||||
<LI>
|
||||
Fix the MSVC makefiles to make libFLAC.dll (instead of just the .lib).
|
||||
</LI>
|
||||
<LI>
|
||||
Clean up the Winamp2 plugin and/or write a Winamp3 one.
|
||||
</LI>
|
||||
<LI>
|
||||
Configurable ID3V1 support and ID3V2 support in the plugins.
|
||||
</LI>
|
||||
<LI>
|
||||
Better encoding decoding statistics for flac.
|
||||
</LI>
|
||||
<LI>
|
||||
Support more input types than just WAVE and raw in flac.
|
||||
</LI>
|
||||
<LI>
|
||||
Expand the test suite.
|
||||
</LI>
|
||||
<LI>
|
||||
A better logo! Gimp jedi I'm not...
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
454
doc/documentation.html
Normal file
454
doc/documentation.html
Normal file
@ -0,0 +1,454 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - documentation</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> documentation </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">documentation</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
This page describes the user-level view of the FLAC format (for a more detailed explanation see the <A HREF="format.html">format page</A>). It also contains the user documentation for <B><TT>flac</TT></B>, which is the command-line file encoder/decoder, and the <A HREF="#plugins">input plugins</A>.
|
||||
</P>
|
||||
<P>
|
||||
Keep in mind that the online version of this document will always apply to the latest release. For older releases, check the documentation included with the release package.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">format</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
See the <A HREF="format.html#scope">Scope</A>, <A HREF="format.html#architecture">Architecture</A>, <A HREF="format.html#definitions">Definitions</A>, and <A HREF="format.html#overview">Overview</A> sections of the <A HREF="format.html">format page</A> for a good introduction. This section will be expanded in the future.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">flac</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
<B><TT>flac</TT></B> is the command-line file encoder/decoder. The input to the encoder and the output to the decoder must either be RIFF WAVE format, or raw interleaved sample data. <B><TT>flac</TT></B> only supports linear PCM samples (in other words, no A-LAW, uLAW, etc.). Another restriction (hopefully short-term) is that the input must be 8 or 16 bits per sample. This is not a limitation of the FLAC format, just the reference encoder.
|
||||
</P>
|
||||
<P>
|
||||
<B><TT>flac</TT></B> assumes that RIFF WAVE files will have the extension ".wav"; this may be overridden with a command-line option. Other than this, <B><TT>flac</TT></B> makes no assumptions about file extensions, though the convention is that FLAC files have the extension ".flac" (or ".fla" on ancient file systems like FAT-16).
|
||||
</P>
|
||||
<P>
|
||||
Before going into the full command-line description, two other things help to sort it out: 1) <B><TT>flac</TT></B> encodes by default, so you must use <B>-d</B> to decode; 2) the options <B><TT>-0</TT></B> .. <B><TT>-9</TT></B> that control the compression level actually are just synonyms for different groups of specific coding options (described later). You can get the same effect by using the same options.
|
||||
</P>
|
||||
<P>
|
||||
<B><TT>flac</TT></B> will be invoked one of two ways, depending on whether you are encoding or decoding:
|
||||
<UL>
|
||||
<LI>
|
||||
Encoding: flac [-v] [--skip #] [<format-options>] [<encoding options>] inputfile outputfile
|
||||
</LI>
|
||||
<LI>
|
||||
Decoding: flac -d [-v] [--skip #] [<format-options>] inputfile outputfile
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
In either case, inputfile may be "-" for stdin, and "-" for stdout. The encoding options affect the compression ratio and encoding speed. The format options are used to tell <B><TT>flac</TT></B> the arrangement of samples if the input file (or output file when decoding) is a raw file. If it is a RIFF WAVE file the format options are not needed since they are read from the WAVE header.
|
||||
</P>
|
||||
<P>
|
||||
<TABLE WIDTH="100%" BORDER="0" CELLSPACING="0" CELLPADDING="0" BGCOLOR="#EEEED4"><TR><TD>
|
||||
<TABLE WIDTH="100%" BORDER="1" BGCOLOR="#EEEED4">
|
||||
<TR>
|
||||
<TD COLSPAN="2" BGCOLOR="#D3D4C5">
|
||||
<FONT SIZE="+1"><B>General Options</B></FONT>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-d
|
||||
</TD>
|
||||
<TD>
|
||||
Decode (<B><TT>flac</TT></B> encodes by default).
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-s
|
||||
</TD>
|
||||
<TD>
|
||||
Silent: do not show encoding/decoding statistics.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
--skip #
|
||||
</TD>
|
||||
<TD>
|
||||
Skip over the first # of samples of the input. This works for both encoding and decoding.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD></TR></TABLE>
|
||||
</P>
|
||||
<P>
|
||||
<TABLE WIDTH="100%" BORDER="0" CELLSPACING="0" CELLPADDING="0" BGCOLOR="#EEEED4"><TR><TD>
|
||||
<TABLE WIDTH="100%" BORDER="1" BGCOLOR="#EEEED4">
|
||||
<TR>
|
||||
<TD COLSPAN="2" BGCOLOR="#D3D4C5">
|
||||
<FONT SIZE="+1"><B>Encoding Options</B></FONT>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
--lax
|
||||
</TD>
|
||||
<TD>
|
||||
Allow encoder to generate non-Subset files. The resulting FLAC file may not be streamable, so you should only use this option in combination with custom encoding options meant for archival. File decoders will still be able play (and seek in) such files.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-b #
|
||||
</TD>
|
||||
<TD>
|
||||
Set the blocksize. The default is 1152 for -l 0, otherwise 4608. Subset streams must use one of 192/576/1152/2304/4608. The current encoder uses the same blocksize for the entire stream.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-m
|
||||
</TD>
|
||||
<TD>
|
||||
Enable mid-side coding (only for stereo streams). Tends to increase compression by a few percent on average. For each block both the stereo pair and mid-side versions of the block will be encoded, and smallest resulting frame will be stored. Currently mid-side encoding is only available when bits-per-sample <= 16.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-0 .. -9
|
||||
</TD>
|
||||
<TD>
|
||||
Fastest compression .. highest compression. The default is <TT>-6</TT>.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-0
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 0
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-1
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 0 -m
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-2
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 0 -m -r # (where # is set based on the blocksize)
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-3
|
||||
</TD>
|
||||
<TD>
|
||||
Reserved
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-4
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 8
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-5
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 8 -m
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-6
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 8 -m -r # (where # is set based on the blocksize)
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-7
|
||||
</TD>
|
||||
<TD>
|
||||
Reserved
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-8
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 32 -m -r # (where # is set based on the blocksize)
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-9
|
||||
</TD>
|
||||
<TD>
|
||||
Synonymous with -l 32 -m -e -r 99 -p. This is painfully slow but gives you the maximum compression <B><TT>flac</TT></B> can do for a given blocksize.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-e
|
||||
</TD>
|
||||
<TD>
|
||||
Exhaustive model search (expensive!). Normally the encoder estimates the best model to use and encodes once based on the estimate. With an exhaustive model search, the encoder will generate subframes for every order and use the smallest. If the max LPC order is high this can significantly increase the encode time but can shave off another 0.5%.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-l #
|
||||
</TD>
|
||||
<TD>
|
||||
Specifies the maximum LPC order. This number must be <= 32. If 0, the encoder will not attempt generic linear prediction, and use only fixed predictors. Using fixed predictors is faster but usually results in files being 5-10% larger.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-q #
|
||||
</TD>
|
||||
<TD>
|
||||
Specifies the precision of the quantized LP coefficients, in bits. The default is <B><TT>-q 0</TT></B>, which means let the encoder decide based on the signal. Unless you really know your input file it's best to leave this up to the encoder.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-p
|
||||
</TD>
|
||||
<TD>
|
||||
Do exhaustive LP coefficient quantization optimization. This option overrides any <B><TT>-q</TT></B> option. It is expensive and typically will only improve the compression a tiny fraction of a percent.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-r #
|
||||
</TD>
|
||||
<TD>
|
||||
Do Rice parameter optimization. By default the encoder uses a single Rice parameter for the subframe's entire residual. With this option, the residual is partitioned into 2^n pieces, each with its own Rice parameter. Higher values of n yield diminishing returns. The most bang for the buck is usually with <B><TT>-r 2</TT></B> (more for higher blocksizes). This usually shaves off another 1.5%. The technique tends to peak out about when blocksize/(2^n)=128. Use <B><TT>-r 99</TT></B> to force the highest degree of optimization.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
</TD>
|
||||
<TD>
|
||||
-m-, -e-, -p-, --lax- can all be used to turn off a particular option.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD></TR></TABLE>
|
||||
</P>
|
||||
<P>
|
||||
<TABLE WIDTH="100%" BORDER="0" CELLSPACING="0" CELLPADDING="0" BGCOLOR="#EEEED4"><TR><TD>
|
||||
<TABLE WIDTH="100%" BORDER="1" BGCOLOR="#EEEED4">
|
||||
<TR>
|
||||
<TD COLSPAN="2" BGCOLOR="#D3D4C5">
|
||||
<FONT SIZE="+1"><B>Format Options</B></FONT>
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fb | -fl
|
||||
</TD>
|
||||
<TD>
|
||||
Specify big-endian | little-endian byte order in the raw file.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fc #
|
||||
</TD>
|
||||
<TD>
|
||||
Specify the number of channels in the raw file.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fp #
|
||||
</TD>
|
||||
<TD>
|
||||
Specify the number of bits per sample in the raw file.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fs #
|
||||
</TD>
|
||||
<TD>
|
||||
Specify the sample rate of the raw file.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fu
|
||||
</TD>
|
||||
<TD>
|
||||
Specify that the samples in the raw file are unsigned (the default is signed).
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fr
|
||||
</TD>
|
||||
<TD>
|
||||
Treat the input file (or output file if decoding) as a raw file, regardless of the extension.
|
||||
</TD>
|
||||
</TR>
|
||||
<TR>
|
||||
<TD NOWRAP ALIGN="RIGHT" VALIGN="TOP" BGCOLOR="#F4F4CC">
|
||||
-fw
|
||||
</TD>
|
||||
<TD>
|
||||
Treat the input file (or output file if decoding) as a RIFF WAVE file, regardless of the extension.
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD></TR></TABLE>
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<A NAME="plugins"><B><FONT SIZE="+2">xmms plugin</FONT></B></A>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
All that is necessary is to copy <B><TT>libxmms-flac.so</TT></B> to the directory where XMMS looks for input plugins (usually <B><TT>/usr/lib/xmms/Input</TT></B>). There is nothing else to configure. Make sure to restart XMMS before trying to play any .flac files.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">winamp plugin</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
All that is necessary is to copy <B><TT>in_flac.dll</TT></B> to the <B><TT>Plugins/</TT></B> directory of your Winamp installation. There is nothing else to configure. Make sure to restart Winamp before trying to play any .flac files.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
71
doc/download.html
Normal file
71
doc/download.html
Normal file
@ -0,0 +1,71 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - download</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> download </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">download</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
This page will be updated once the CVS repository is set up and the first release is made. Check back soon or <A HREF="http://sourceforge.net/mail/?group_id=13478">join the mailing list</A>.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
142
doc/features.html
Normal file
142
doc/features.html
Normal file
@ -0,0 +1,142 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - features</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> features </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">features</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
FLAC stands for Free Lossless Audio Coder. The FLAC project consists of:
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>the stream format</LI>
|
||||
<LI>libFLAC, which implements a reference encoder, stream decoder, and file decoder</LI>
|
||||
<LI>flac, which is a command-line wrapper around libFLAC to encode and decode .flac files</LI>
|
||||
<LI>input plugins for various music players (Winamp, XMMS, and more in the works)</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
"Free" means that the specification of the stream format is in the public domain (the FLAC project reserves the right to set the FLAC specification and certify compliance), and that neither the FLAC format nor any of the implemented encoding/decoding methods are covered by any patent. It also means that the source for libFLAC is available under the <A HREF="http://www.opensource.org/licenses/lgpl-license.html">LGPL</A> and the sources for flac and the plugins are available under the <A HREF="http://www.opensource.org/licenses/gpl-license.html">GPL</A>.
|
||||
</P>
|
||||
<P>
|
||||
What FLAC is:
|
||||
</P>
|
||||
<UL>
|
||||
<P><LI>
|
||||
FLAC is patent free. The FLAC format or encoding/decoding methods are not covered by any patents.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC is lossless. The encoding of PCM data incurs no loss of information, and the decoded audio is bit-for-bit identical to what went into the encoder.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC is designed to compress audio data. Technically, flac can "compress" other kinds of data losslessly (if you pass it in as a mono 8-bit raw file), but the output files tend to be bigger.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
The compression capabilities of FLAC are extendable, meaning that new methods can be added to future versions of the format without breaking older streams or decoders.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
The currently implemented compression methods in the reference encoder yield streams on par or smaller than shorten. The encoding time is variable, but is generally between that of <A HREF="http://www.softsound.com/Shorten.html">shorten</A>, and that of, say, <A HREF="http://www.mp3dev.org/mp3/">LAME</A>. The most aggressive compression however can be quite slow. For more info see the <A HREF="comparison.html">comparison page</A>.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC is asymmetric in favor of decode speed. Decoding requires only integer arithmetic, and is much less compute-intensive than for most perceptual codecs. Real-time decode performance is easily achievable on even modest hardare.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC is suitable for archiving, since there is no information loss. You are not locked into the format since there is no generation loss if you decide to convert your data to another format in the future.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC is suitable for streaming. Each FLAC frame contains enough data to decode that frame. FLAC does not even rely on previous or following frames. FLAC uses sync codes and CRCs (similar to MPEG and other formats), which, along with framing, allow decoders to pick up in the middle of a stream with a minimum of delay.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC supports fast sample-accurate seeking. Not only is this useful for playback, it makes FLAC files suitable for use in editing applications.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
FLAC has an extendable meta-data system. New meta-data blocks can be defined and implemented in future versions of FLAC without breaking older streams or decoders. ID3 and ID3V2 tags may be attached to .flac files without disrupting the decoder.
|
||||
</LI></P>
|
||||
</UL>
|
||||
<P>
|
||||
Some things that follow from the features:
|
||||
</P>
|
||||
<UL>
|
||||
<P><LI>
|
||||
FLAC streams can be played back consecutively with no audible gaps in between, unlike say, MP3s (this is one of the minor <A HREF="goals.html">goals</A>). For example, you can encode a live album as individual tracks and still play them back seamlessly.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
The sample-accurate seeking allows versatile playback: a sophisticated player could do index points, complex looping, or other structured playback. This could be useful in for say DJs, or practice sessions where you want to play along through specific passages.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
Basically, you get the versatility of a WAV file in a compressed streamable format.
|
||||
</LI></P>
|
||||
</UL>
|
||||
<P>
|
||||
What FLAC is <B>not</B>:
|
||||
</P>
|
||||
<UL>
|
||||
<P><LI>
|
||||
Lossy. FLAC is intended for lossless compression only, as there are many good lossy formats already, such as <A HREF="http://www.mp3-tech.org/">MP3</A> (see <A HREF="http://www.mp3dev.org/mp3/">LAME</A> for an excellent open-source implementation), and <A HREF="http://www.xiph.org/ogg/vorbis/index.html">Ogg Vorbis</A>.
|
||||
</LI></P>
|
||||
<P><LI>
|
||||
SDMI compliant, et cetera. There is no intention to support any methods of copy protection, which are, for all practical purposes, a complete waste of bits. (Another way to look at it is that since copy protection is futile, it really carries no information, so you might say FLAC already losslessly compresses all possible copy protection information down to zero bits!) Of course, we can't stop what some misguided person does with proprietary meta-data blocks, but then again, non-proprietary decoders will skip them anyway.
|
||||
</LI></P>
|
||||
</UL>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
1092
doc/format.html
Normal file
1092
doc/format.html
Normal file
File diff suppressed because it is too large
Load Diff
112
doc/goals.html
Normal file
112
doc/goals.html
Normal file
@ -0,0 +1,112 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - goals</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> goals </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">goals</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
Since FLAC is an open-source project, it's important to have a set of goals that everyone works to. They may change slightly from time to time but they're a good guideline. Changes should be in line with the goals and should not attempt to embrace any of the anti-goals!
|
||||
</P>
|
||||
<P>
|
||||
<B>Goals</B>
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
FLAC should be and stay an open format. The source code is all either LGPL'd or GPL'd.
|
||||
</LI>
|
||||
<LI>
|
||||
FLAC should be lossless. This seems obvious but lossy compression seems to creep into every audio coder. This goal also means that flac should stay archival quality and be truly lossless for all input. Testing of releases should be thorough.
|
||||
</LI>
|
||||
<LI>
|
||||
FLAC should yield respectable compression, on par or better than other lossless coders.
|
||||
</LI>
|
||||
<LI>
|
||||
FLAC should allow at least realtime decoding on even modest hardware.
|
||||
</LI>
|
||||
<LI>
|
||||
FLAC should support fast sample-accurate seeking.
|
||||
</LI>
|
||||
<LI>
|
||||
FLAC should allow gapless playback of consecutive streams. This follows from the lossless goal.
|
||||
</LI>
|
||||
<LI>
|
||||
The FLAC project owes a lot to the many people who have advanced the audio compression field so freely, and aims also to contribute through the open-source development of new ideas.
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
<B>Anti-goals</B>
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>
|
||||
Lossy compression. There are already many suitable lossy format (<A HREF="http://www.xiph.org/ogg/vorbis/index.html">Ogg Vorbis</A>, <A HREF="http://www.mp3-tech.org/">MP3</A>, etc.).
|
||||
</LI>
|
||||
<LI>
|
||||
Copy protection of any kind. Don't get me started, just see the <A HREF="features.html">features page</A> for the short answer.
|
||||
</LI>
|
||||
</UL>
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
BIN
doc/images/1x1.gif
Normal file
BIN
doc/images/1x1.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 61 B |
BIN
doc/images/logo.jpg
Normal file
BIN
doc/images/logo.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 3.0 KiB |
232
doc/index.html
Normal file
232
doc/index.html
Normal file
@ -0,0 +1,232 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - Free Lossless Audio Coder</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> home </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="news.html">news</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE cellspacing="0" cellpadding="3" border="0" width="100%" bgcolor="#99CC99">
|
||||
<TR>
|
||||
<TD align="center" valign="top">
|
||||
|
||||
<TABLE WIDTH="100%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">status</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>FLAC is currently in the alpha stage. The current version is 0.2. The format is well defined but may change enough before becoming beta to break older streams. It also has not gone through enough testing yet to be considered archival quality. You should keep those two things in mind when using any alpha or beta versions of FLAC.</P>
|
||||
<P>That said, we intend to settle on the format quickly, then start releasing beta versions. If you use FLAC and have suggestions or bugs, please <A HREF="http://sourceforge.net/mail/?group_id=13478">join the mailing list</A> or <A HREF="http://sourceforge.net/project/memberlist.php?group_id=13478">developers group</A> and help us move to an official 1.0 version.</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">what is FLAC?</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
FLAC stands for Free Lossless Audio Coder. The FLAC project consists of:
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI>the stream format</LI>
|
||||
<LI>libFLAC, which implements a reference encoder, stream decoder, and file decoder</LI>
|
||||
<LI>flac, which is a command-line wrapper around libFLAC to encode and decode .flac files</LI>
|
||||
<LI>input plugins for various music players (Winamp, XMMS, and more in the works)</LI>
|
||||
</UL>
|
||||
</P>
|
||||
<P>
|
||||
"Free" means that the specification of the stream format is in the public domain (the FLAC project reserves the right to set the FLAC specification and certify compliance), and that neither the FLAC format nor any of the implemented encoding/decoding methods are covered by any patent. It also means that the source for libFLAC is available under the <A HREF="http://www.opensource.org/licenses/lgpl-license.html">LGPL</A> and the sources for flac and the plugins are available under the <A HREF="http://www.opensource.org/licenses/gpl-license.html">GPL</A>.
|
||||
</P>
|
||||
<P>
|
||||
See the <A HREF="features.html">features page</A>, <A HREF="documentation.html">documentation page</A>, or <A HREF="format.html">FLAC format page</A> for more info, the <A HREF="comparison.html">comparison page</A> to see how the reference encoder measures up, or the <A HREF="goals.html">goals page</A> for what the FLAC project hopes to achieve.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
|
||||
<TABLE WIDTH="100%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">download</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
Visit the <A HREF="download.html">download page</A> for links to the source code or pre-built binaries, or go directly to the <A HREF="http://www.sourceforge.net/projects/flac/">source</A> on SourceForge.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
|
||||
<TABLE WIDTH="100%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">documentation</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
The documentation is available online as well as in the distributions. The general installation and usage documentation for flac and the plugins is <A HREF="documentation.html">here</A>. For a detailed description of the FLAC format and reference encoder see the <A HREF="format.html">FLAC format page</A>.
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
|
||||
<TABLE WIDTH="100%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">message from the maintainer</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
I came up with FLAC because no audio compression format I could find did everything I needed. Since I couldn't mash them all together (most are closed-source), I solidified all my requirements (now the FLAC <A HREF="goals.html">goals</A>) and wrote the first implementation. I intended to open-source it from the beginning for two reasons: 1) so that people who knew more about audio compression than me could help improve it; and 2) I wanted to give something back to the OS community, whose huge body of work I rely on so much.
|
||||
</P>
|
||||
<P>
|
||||
So I started the FLAC project on SourceForge as soon as I had a relatively complete first implementation. Now I'm the maintainer of the FLAC project. You can get in touch with me about it through the <A HREF="http://sourceforge.net/mail/?group_id=13478">mailing list</A> or <A HREF="mailto:jcoalson@users.sourceforge.net">directly</A>
|
||||
</P>
|
||||
<P>
|
||||
--Josh Coalson
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
|
||||
</TD>
|
||||
|
||||
|
||||
<TD width="26%" valign="top" align="center">
|
||||
|
||||
|
||||
<TABLE WIDTH="95%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B>news</B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD BGCOLOR="#EEEED4"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"><A HREF="news.html#20001101">10-Dec-2000</A> :<BR> FLAC <A HREF="http://www.sourceforge.net/projects/flac/">debuts</A> on SourceForge<BR></FONT></SMALL></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE><BR><P>
|
||||
|
||||
|
||||
<TABLE WIDTH="95%">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD ALIGN="center"><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B>links</B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD BGCOLOR="#EEEED4"><SMALL><FONT FACE="Lucida,Verdana,Helvetica,Arial"><A HREF="http://www.sourceforge.net/projects/flac/">SourceForge</A><BR></FONT></SMALL></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE><BR><P>
|
||||
|
||||
|
||||
<A href="http://sourceforge.net"><IMG src="http://sourceforge.net/sflogo.php?group_id=13478&type=1" width="88" height="31" border="0" alt="SourceForge Logo"></A><BR>
|
||||
|
||||
|
||||
<BR></FONT>
|
||||
</TD></TR></TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
76
doc/news.html
Normal file
76
doc/news.html
Normal file
@ -0,0 +1,76 @@
|
||||
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
|
||||
<HTML>
|
||||
<HEAD>
|
||||
<TITLE>FLAC - news</TITLE>
|
||||
</HEAD>
|
||||
|
||||
<BODY MARGINWIDTH="0" MARGINHEIGHT="0" LEFTMARGIN="0" RIGHTMARGIN="0" TOPMARGIN="0" BGCOLOR="#99CC99" TEXT="#000000" LINK="#336699" VLINK="#336699" ALINK="#336699">
|
||||
|
||||
<TABLE BORDER=0 WIDTH="100%" CELLPADDING=1 CELLSPACING=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#000000"><A HREF="http://flac.sourceforge.net/"><IMG SRC="images/logo.jpg" ALIGN=CENTER ALT="FLAC Logo" BORDER=0 HSPACE=0></a></TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="25" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD ALIGN="CENTER" BGCOLOR="#D3D4C5">
|
||||
<TABLE CELLPADDING=0 CELLSPACING=0 BORDER=0>
|
||||
<TR>
|
||||
<TD HEIGHT=22 BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="index.html">home</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> news </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="download.html">download</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="features.html">features</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="goals.html">goals</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="format.html">format</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="comparison.html">comparison</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="documentation.html">documentation</A> </TD><TD BGCOLOR="#D3D4C5" ALIGN=CENTER>|</TD>
|
||||
<TD BGCOLOR="#D3D4C5" ALIGN=CENTER NOWRAP> <A CLASS="topnav" HREF="developers.html">developers</A> </TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
</TD>
|
||||
</TR>
|
||||
</TABLE>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="2" ALT=""></TD></TR></TABLE>
|
||||
|
||||
<CENTER>
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#99CC99"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="15" ALT=""></TD></TR></TABLE>
|
||||
|
||||
|
||||
<TABLE WIDTH="100%" CELLPADDING="5" CELLSPACING="5" BORDER="0">
|
||||
<TR><TD>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#D3D4C5">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<B><FONT SIZE="+2">news</FONT></B>
|
||||
</FONT></TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
<TABLE CELLSPACING="0" CELLPADDING="3" WIDTH="100%" BORDER="0" BGCOLOR="#EEEED4">
|
||||
<TR><TD><FONT FACE="Lucida,Verdana,Helvetica,Arial">
|
||||
<P>
|
||||
<A NAME="20001101">10-Dec-2000:</A>
|
||||
</P>
|
||||
<P>
|
||||
<UL>
|
||||
<LI><B>FLAC debuts on SourceForge.</B> The FLAC project is now being hosted on SourceForge. Visit the <A HREF="http://www.sourceforge.net/projects/projects/flac/">FLAC project page</A> to join the mailing list or sign up as a developer.</LI>
|
||||
</UL>
|
||||
</P>
|
||||
</FONT>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
<TABLE WIDTH="100%" CELLPADDING="0" CELLSPACING="0" BORDER="0"><TR BGCOLOR="#000000"><TD><IMG SRC="images/1x1.gif" WIDTH="1" HEIGHT="1" ALT=""></TD></TR></TABLE>
|
||||
</TD></TR>
|
||||
</TABLE>
|
||||
|
||||
|
||||
</CENTER>
|
||||
|
||||
</BODY>
|
||||
</HTML>
|
28
include/FLAC/all.h
Normal file
28
include/FLAC/all.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ALL_H
|
||||
#define FLAC__ALL_H
|
||||
|
||||
#include "encoder.h"
|
||||
#include "file_decoder.h"
|
||||
#include "ordinals.h"
|
||||
#include "stream_decoder.h"
|
||||
|
||||
#endif
|
77
include/FLAC/encoder.h
Normal file
77
include/FLAC/encoder.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ENCODER_H
|
||||
#define FLAC__ENCODER_H
|
||||
|
||||
#include "format.h"
|
||||
|
||||
typedef enum {
|
||||
FLAC__ENCODER_WRITE_OK = 0,
|
||||
FLAC__ENCODER_WRITE_FATAL_ERROR = 1
|
||||
} FLAC__EncoderWriteStatus;
|
||||
|
||||
typedef enum {
|
||||
FLAC__ENCODER_OK,
|
||||
FLAC__ENCODER_UNINITIALIZED,
|
||||
FLAC__ENCODER_INVALID_NUMBER_OF_CHANNELS,
|
||||
FLAC__ENCODER_INVALID_BITS_PER_SAMPLE,
|
||||
FLAC__ENCODER_INVALID_SAMPLE_RATE,
|
||||
FLAC__ENCODER_INVALID_BLOCK_SIZE,
|
||||
FLAC__ENCODER_INVALID_QLP_COEFF_PRECISION,
|
||||
FLAC__ENCODER_MID_SIDE_CHANNELS_MISMATCH,
|
||||
FLAC__ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH,
|
||||
FLAC__ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER,
|
||||
FLAC__ENCODER_NOT_STREAMABLE,
|
||||
FLAC__ENCODER_FRAMING_ERROR,
|
||||
FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING,
|
||||
FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING, /* that is, the write_callback returned an error */
|
||||
FLAC__ENCODER_MEMORY_ALLOCATION_ERROR
|
||||
} FLAC__EncoderState;
|
||||
|
||||
struct FLAC__EncoderPrivate;
|
||||
typedef struct {
|
||||
/*
|
||||
* none of these fields may change once FLAC__encoder_init() is called
|
||||
*/
|
||||
struct FLAC__EncoderPrivate *guts; /* must be 0 when passed to FLAC__encoder_init() */
|
||||
FLAC__EncoderState state; /* must be FLAC__ENCODER_UNINITIALIZED when passed to FLAC__encoder_init() */
|
||||
bool streamable_subset;
|
||||
bool do_mid_side_stereo; /* 0 or 1; 1 only if channels==2 */
|
||||
unsigned channels; /* must be <= FLAC__MAX_CHANNELS */
|
||||
unsigned bits_per_sample; /* do not give the encoder wider data than what you specify here or bad things will happen! */
|
||||
unsigned sample_rate;
|
||||
unsigned blocksize;
|
||||
unsigned max_lpc_order; /* 0 => encoder will not try general LPC, only fixed predictors; must be <= FLAC__MAX_LPC_ORDER */
|
||||
unsigned qlp_coeff_precision; /* >= FLAC__MIN_QLP_COEFF_PRECISION, or 0 to let encoder select based on blocksize; */
|
||||
/* qlp_coeff_precision+bits_per_sample must be < 32 */
|
||||
bool do_qlp_coeff_prec_search; /* 0 => use qlp_coeff_precision, 1 => search around qlp_coeff_precision, take best */
|
||||
bool do_exhaustive_model_search; /* 0 => use estimated bits per residual for scoring, 1 => generate all, take shortest */
|
||||
unsigned rice_optimization_level; /* 0 => estimate Rice parameter based on residual variance, 1-8 => partition residual, use parameter for each */
|
||||
} FLAC__Encoder;
|
||||
|
||||
|
||||
FLAC__Encoder *FLAC__encoder_get_new_instance();
|
||||
void FLAC__encoder_free_instance(FLAC__Encoder *encoder);
|
||||
FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWriteStatus (*write_callback)(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data), void (*metadata_callback)(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data), void *client_data);
|
||||
void FLAC__encoder_finish(FLAC__Encoder *encoder);
|
||||
bool FLAC__encoder_process(FLAC__Encoder *encoder, const int32 *buf[], unsigned samples);
|
||||
bool FLAC__encoder_process_interleaved(FLAC__Encoder *encoder, const int32 buf[], unsigned samples);
|
||||
|
||||
#endif
|
59
include/FLAC/file_decoder.h
Normal file
59
include/FLAC/file_decoder.h
Normal file
@ -0,0 +1,59 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__FILE_DECODER_H
|
||||
#define FLAC__FILE_DECODER_H
|
||||
|
||||
#include "stream_decoder.h"
|
||||
|
||||
typedef enum {
|
||||
FLAC__FILE_DECODER_OK,
|
||||
FLAC__FILE_DECODER_SEEKING,
|
||||
FLAC__FILE_DECODER_END_OF_FILE,
|
||||
FLAC__FILE_DECODER_ERROR_OPENING_FILE,
|
||||
FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
FLAC__FILE_DECODER_SEEK_ERROR,
|
||||
FLAC__FILE_DECODER_STREAM_ERROR,
|
||||
FLAC__FILE_DECODER_UNINITIALIZED
|
||||
} FLAC__FileDecoderState;
|
||||
|
||||
struct FLAC__FileDecoderPrivate;
|
||||
typedef struct {
|
||||
FLAC__FileDecoderState state; /* must be FLAC__FILE_DECODER_UNINITIALIZED when passed to FLAC__file_decoder_init() */
|
||||
struct FLAC__FileDecoderPrivate *guts; /* must be 0 when passed to FLAC__file_decoder_init() */
|
||||
} FLAC__FileDecoder;
|
||||
|
||||
FLAC__FileDecoder *FLAC__file_decoder_get_new_instance();
|
||||
void FLAC__file_decoder_free_instance(FLAC__FileDecoder *decoder);
|
||||
FLAC__FileDecoderState FLAC__file_decoder_init(
|
||||
FLAC__FileDecoder *decoder,
|
||||
const char *filename,
|
||||
FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data),
|
||||
void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data),
|
||||
void (*error_callback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data),
|
||||
void *client_data
|
||||
);
|
||||
void FLAC__file_decoder_finish(FLAC__FileDecoder *decoder);
|
||||
bool FLAC__file_decoder_process_whole_file(FLAC__FileDecoder *decoder);
|
||||
bool FLAC__file_decoder_process_metadata(FLAC__FileDecoder *decoder);
|
||||
bool FLAC__file_decoder_process_one_frame(FLAC__FileDecoder *decoder);
|
||||
bool FLAC__file_decoder_process_remaining_frames(FLAC__FileDecoder *decoder);
|
||||
bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, uint64 sample);
|
||||
|
||||
#endif
|
315
include/FLAC/format.h
Normal file
315
include/FLAC/format.h
Normal file
@ -0,0 +1,315 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__FORMAT_H
|
||||
#define FLAC__FORMAT_H
|
||||
|
||||
#include "ordinals.h"
|
||||
|
||||
/* changing the following values to be higher will break the framing and hence the stream format, so DON'T! */
|
||||
#define FLAC__MIN_BLOCK_SIZE (16u)
|
||||
#define FLAC__MAX_BLOCK_SIZE (65535u)
|
||||
#define FLAC__MAX_CHANNELS (8u)
|
||||
/*NOTE: only up to 24 because of the current predictor coefficient quantization and the fact we use int32s for all work */
|
||||
#define FLAC__MAX_BITS_PER_SAMPLE (24u)
|
||||
/* the following is ((2 ** 20) - 1) div 10 */
|
||||
#define FLAC__MAX_SAMPLE_RATE (1048570u)
|
||||
#define FLAC__MAX_LPC_ORDER (32u)
|
||||
#define FLAC__MIN_QLP_COEFF_PRECISION (5u)
|
||||
/* changing this also means changing all of fixed.c and more, so DON'T! */
|
||||
#define FLAC__MAX_FIXED_ORDER (4u)
|
||||
#define FLAC__MAX_RICE_PARTITION_ORDER (15u)
|
||||
|
||||
#define FLAC__VERSION_STRING "0.2"
|
||||
extern const unsigned FLAC__MAJOR_VERSION;
|
||||
extern const unsigned FLAC__MINOR_VERSION;
|
||||
|
||||
extern const byte FLAC__STREAM_SYNC_STRING[4]; /* = "fLaC" */;
|
||||
extern const unsigned FLAC__STREAM_SYNC; /* = 0x664C6143 */;
|
||||
extern const unsigned FLAC__STREAM_SYNC_LEN; /* = 32 bits */;
|
||||
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* NOTE: Within the bitstream, all fixed-width numbers are big-endian coded.
|
||||
* All numbers are unsigned unless otherwise noted.
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
FLAC__METADATA_TYPE_ENCODING = 0
|
||||
} FLAC__MetaDataType;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 16: minimum blocksize (in samples) of all blocks in the stream
|
||||
* 16: maximum blocksize (in samples) of all blocks in the stream
|
||||
* 24: minimum framesize (in bytes) of all frames in the stream; 0 => unknown
|
||||
* 24: maximum framesize (in bytes) of all frames in the stream; 0 => unknown
|
||||
* 20: sample rate in Hz, 0 is invalid
|
||||
* 3: (number of channels)-1
|
||||
* 5: (bits per sample)-1
|
||||
* 36: total samples, 0 => unknown
|
||||
*---- -----------------
|
||||
* 18 bytes total
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned min_blocksize, max_blocksize;
|
||||
unsigned min_framesize, max_framesize;
|
||||
unsigned sample_rate;
|
||||
unsigned channels;
|
||||
unsigned bits_per_sample;
|
||||
uint64 total_samples;
|
||||
} FLAC__StreamMetaData_Encoding;
|
||||
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_MIN_BLOCK_SIZE_LEN; /* = 16 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_MAX_BLOCK_SIZE_LEN; /* = 16 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_MIN_FRAME_SIZE_LEN; /* = 24 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_MAX_FRAME_SIZE_LEN; /* = 24 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_SAMPLE_RATE_LEN; /* = 20 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_CHANNELS_LEN; /* = 3 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_BITS_PER_SAMPLE_LEN; /* = 5 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_TOTAL_SAMPLES_LEN; /* = 36 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_ENCODING_LENGTH; /* = 18 bytes */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 1: =1 if this is the last meta-data block, else =0
|
||||
* 7: meta-data type (c.f. FLAC__MetaDataType)
|
||||
* 24: length (in bytes) of the block-specific data to follow
|
||||
*---- -----------------
|
||||
* 4 bytes total
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__MetaDataType type;
|
||||
bool is_last;
|
||||
unsigned length; /* in bytes */
|
||||
union {
|
||||
FLAC__StreamMetaData_Encoding encoding;
|
||||
} data;
|
||||
} FLAC__StreamMetaData;
|
||||
|
||||
extern const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN; /* = 1 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_TYPE_LEN; /* = 7 bits */
|
||||
extern const unsigned FLAC__STREAM_METADATA_LENGTH_LEN; /* = 24 bits */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE = 0
|
||||
} FLAC__EntropyCodingMethodType;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 4: partition order => (2 ** order) subdivisions
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned order;
|
||||
unsigned parameters[1 << FLAC__MAX_RICE_PARTITION_ORDER];
|
||||
} FLAC__EntropyCodingMethod_PartitionedRice;
|
||||
|
||||
extern const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN; /* = 4 bits */
|
||||
extern const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN; /* = 4 bits */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 2: entropy coding method:
|
||||
* 00: partitioned rice coding
|
||||
* 01-11: reserved
|
||||
* ?: entropy coding method data
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__EntropyCodingMethodType type;
|
||||
union {
|
||||
FLAC__EntropyCodingMethod_PartitionedRice partitioned_rice;
|
||||
} data;
|
||||
} FLAC__EntropyCodingMethod;
|
||||
|
||||
extern const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN; /* = 2 bits */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT = 0,
|
||||
FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE = 1,
|
||||
FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE = 2,
|
||||
FLAC__CHANNEL_ASSIGNMENT_MID_SIDE = 3
|
||||
} FLAC__ChannelAssignment;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 9: sync code '111111110'
|
||||
* 3: blocksize in samples
|
||||
* 000: get from stream header => implies constant blocksize throughout stream
|
||||
* 001: 192 samples (AES/EBU) => implies constant blocksize throughout stream
|
||||
* 010-101: 576 * (2^(2-n)) samples, i.e. 576/1152/2304/4608 => implies constant blocksize throughout stream
|
||||
* 110: get 8 bit (blocksize-1) from end of header => variable blocksize throughout stream unless it's the last frame
|
||||
* 111: get 16 bit (blocksize-1) from end of header => variable blocksize throughout stream unless it's the last frame
|
||||
* 4: sample rate:
|
||||
* 0000: get from stream header
|
||||
* 0001-0011: reserved
|
||||
* 0100: 8kHz
|
||||
* 0101: 16kHz
|
||||
* 0110: 22.05kHz
|
||||
* 0111: 24kHz
|
||||
* 1000: 32kHz
|
||||
* 1001: 44.1kHz
|
||||
* 1010: 48kHz
|
||||
* 1011: 96kHz
|
||||
* 1100: get 8 bit sample rate (in kHz) from end of header
|
||||
* 1101: get 16 bit sample rate (in Hz) from end of header
|
||||
* 1110: get 16 bit sample rate (in tens of Hz) from end of header
|
||||
* 1111: invalid, to prevent sync-fooling string of 1s (use to check for erroneous sync)
|
||||
* 4: channel assignment
|
||||
* 0000-0111: (number of independent channels)-1. when == 0001, channel 0 is the left channel and channel 1 is the right
|
||||
* 1000: left/side stereo : channel 0 is the left channel, channel 1 is the side(difference) channel
|
||||
* 1001: right/side stereo: channel 0 is the side(difference) channel, channel 1 is the right channel
|
||||
* 1010: mid/side stereo : channel 0 is the mid(average) channel, channel 1 is the side(difference) channel
|
||||
* 1011-1111: reserved
|
||||
* 3: sample size in bits
|
||||
* 000: get from stream header
|
||||
* 001: 8 bits per sample
|
||||
* 010: 12 bits per sample
|
||||
* 011: reserved
|
||||
* 100: 16 bits per sample
|
||||
* 101: 20 bits per sample
|
||||
* 110: 24 bits per sample
|
||||
* 111: reserved
|
||||
* 1: zero pad, to prevent sync-fooling string of 1s (use to check for erroneous sync)
|
||||
* ?: if(variable blocksize)
|
||||
* 8-56: 'UTF-8' coded sample number (decoded number is 0-36 bits) (use to check for erroneous sync)
|
||||
* else
|
||||
* 8-48: 'UTF-8' coded frame number (decoded number is 0-31 bits) (use to check for erroneous sync)
|
||||
* ?: if(blocksize bits == 11x)
|
||||
* 8/16 bit (blocksize-1)
|
||||
* ?: if(sample rate bits == 11xx)
|
||||
* 8/16 bit sample rate
|
||||
* 8: CRC-8 (polynomial = x^8 + x^2 + x + 1) of everything before the crc, including the sync code
|
||||
*/
|
||||
typedef struct {
|
||||
unsigned blocksize; /* in samples */
|
||||
unsigned sample_rate; /* in Hz */
|
||||
unsigned channels;
|
||||
FLAC__ChannelAssignment channel_assignment;
|
||||
unsigned bits_per_sample;
|
||||
union {
|
||||
uint32 frame_number;
|
||||
uint64 sample_number;
|
||||
} number;
|
||||
} FLAC__FrameHeader;
|
||||
|
||||
extern const unsigned FLAC__FRAME_HEADER_SYNC; /* = 0x1fe */
|
||||
extern const unsigned FLAC__FRAME_HEADER_SYNC_LEN; /* = 9 bits */
|
||||
extern const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN; /* = 3 bits */
|
||||
extern const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN; /* = 4 bits */
|
||||
extern const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN; /* = 4 bits */
|
||||
extern const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN; /* = 3 bits */
|
||||
extern const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN; /* = 1 bit */
|
||||
extern const unsigned FLAC__FRAME_HEADER_CRC8_LEN; /* = 8 bits */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
typedef enum {
|
||||
FLAC__SUBFRAME_TYPE_CONSTANT = 0,
|
||||
FLAC__SUBFRAME_TYPE_VERBATIM = 1,
|
||||
FLAC__SUBFRAME_TYPE_FIXED = 2,
|
||||
FLAC__SUBFRAME_TYPE_LPC = 3
|
||||
} FLAC__SubframeType;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* n: constant value for signal; n = frame's bits-per-sample
|
||||
*/
|
||||
typedef struct {
|
||||
int32 value;
|
||||
} FLAC__SubframeHeader_Constant;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* n*i: unencoded signal; n = frame's bits-per-sample, i = frame's blocksize
|
||||
*/
|
||||
/* There is no (trivial) for structure FLAC__SubframeHeader_Verbatim */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* n: unencoded warm-up samples (n = fixed-predictor order * bits per sample)
|
||||
* ?: entropy coding method info
|
||||
* ?: encoded residual ((blocksize minus fixed-predictor order) samples)
|
||||
* The order is stored in the main subframe header
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__EntropyCodingMethod entropy_coding_method;
|
||||
unsigned order;
|
||||
int32 warmup[FLAC__MAX_FIXED_ORDER];
|
||||
} FLAC__SubframeHeader_Fixed;
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* n: unencoded warm-up samples (n = lpc order * bits per sample)
|
||||
* 4: (qlp coeff precision in bits)-1 (1111 = invalid, use to check for erroneous sync)
|
||||
* 5: qlp shift needed in bits (signed)
|
||||
* n: unencoded predictor coefficients (n = lpc order * qlp coeff precision)
|
||||
* ?: entropy coding method info
|
||||
* ?: encoded residual ((blocksize minus lpc order) samples)
|
||||
* The order is stored in the main subframe header
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__EntropyCodingMethod entropy_coding_method;
|
||||
unsigned order;
|
||||
unsigned qlp_coeff_precision;
|
||||
int quantization_level;
|
||||
int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
|
||||
int32 warmup[FLAC__MAX_LPC_ORDER];
|
||||
} FLAC__SubframeHeader_LPC;
|
||||
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_LPC_QLP_COEFF_PRECISION_LEN; /* = 4 bits */
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_LPC_QLP_SHIFT_LEN; /* = 5 bits */
|
||||
|
||||
/*****************************************************************************
|
||||
*
|
||||
* 8: subframe type
|
||||
* xxxxxxx1: invalid, to prevent sync-fooling string of 1s (use to check for erroneous sync)
|
||||
* 00000000: constant value
|
||||
* 00000010: verbatim
|
||||
* 000001x0: reserved
|
||||
* 00001xx0: reserved
|
||||
* 0001xxx0: fixed predictor, xxx=order <= 4, else reserved
|
||||
* 001xxxx0: reserved
|
||||
* 01xxxxx0: lpc, xxxxx=order-1
|
||||
* 1xxxxxxx: invalid, to prevent sync-fooling string of 1s (use to check for erroneous sync)
|
||||
* ?: subframe-specific header (c.f. FLAC__SubframeHeader_*)
|
||||
*/
|
||||
typedef struct {
|
||||
FLAC__SubframeType type;
|
||||
union {
|
||||
FLAC__SubframeHeader_Constant constant;
|
||||
FLAC__SubframeHeader_Fixed fixed;
|
||||
FLAC__SubframeHeader_LPC lpc;
|
||||
} data; /* data will be undefined for FLAC__SUBFRAME_TYPE_VERBATIM */
|
||||
} FLAC__SubframeHeader;
|
||||
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_TYPE_CONSTANT; /* = 0x00 */
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_TYPE_VERBATIM; /* = 0x02 */
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_TYPE_FIXED; /* = 0x10 */
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_TYPE_LPC; /* = 0x40 */
|
||||
extern const unsigned FLAC__SUBFRAME_HEADER_TYPE_LEN; /* = 8 bits */
|
||||
|
||||
/*****************************************************************************/
|
||||
|
||||
#endif
|
75
include/FLAC/ordinals.h
Normal file
75
include/FLAC/ordinals.h
Normal file
@ -0,0 +1,75 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__ORDINALS_H
|
||||
#define FLAC__ORDINALS_H
|
||||
|
||||
#ifdef bool
|
||||
#undef bool
|
||||
#endif
|
||||
#ifdef true
|
||||
#undef true
|
||||
#endif
|
||||
#ifdef false
|
||||
#undef false
|
||||
#endif
|
||||
#ifdef byte
|
||||
#undef byte
|
||||
#endif
|
||||
#ifdef int16
|
||||
#undef int16
|
||||
#endif
|
||||
#ifdef uint16
|
||||
#undef uint16
|
||||
#endif
|
||||
#ifdef int32
|
||||
#undef int32
|
||||
#endif
|
||||
#ifdef uint32
|
||||
#undef uint32
|
||||
#endif
|
||||
#ifdef int64
|
||||
#undef int64
|
||||
#endif
|
||||
#ifdef uint64
|
||||
#undef uint64
|
||||
#endif
|
||||
#ifdef real
|
||||
#undef real
|
||||
#endif
|
||||
|
||||
#define true 1
|
||||
#define false 0
|
||||
|
||||
typedef int bool;
|
||||
typedef unsigned char byte;
|
||||
typedef short int16;
|
||||
typedef unsigned short uint16;
|
||||
typedef int int32;
|
||||
typedef unsigned int uint32;
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
typedef __int64 int64;
|
||||
typedef unsigned __int64 uint64;
|
||||
#else
|
||||
typedef long long int int64;
|
||||
typedef unsigned long long uint64;
|
||||
#endif
|
||||
typedef double real;
|
||||
|
||||
#endif
|
83
include/FLAC/stream_decoder.h
Normal file
83
include/FLAC/stream_decoder.h
Normal file
@ -0,0 +1,83 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__STREAM_DECODER_H
|
||||
#define FLAC__STREAM_DECODER_H
|
||||
|
||||
#include "format.h"
|
||||
|
||||
typedef enum {
|
||||
FLAC__STREAM_DECODER_SEARCH_FOR_METADATA,
|
||||
FLAC__STREAM_DECODER_READ_METADATA,
|
||||
FLAC__STREAM_DECODER_SEARCH_FOR_FRAME_SYNC,
|
||||
FLAC__STREAM_DECODER_READ_FRAME,
|
||||
FLAC__STREAM_DECODER_RESYNC_IN_HEADER,
|
||||
FLAC__STREAM_DECODER_END_OF_STREAM,
|
||||
FLAC__STREAM_DECODER_ABORTED,
|
||||
FLAC__STREAM_DECODER_UNPARSEABLE_STREAM,
|
||||
FLAC__STREAM_DECODER_MEMORY_ALLOCATION_ERROR,
|
||||
FLAC__STREAM_DECODER_UNINITIALIZED
|
||||
} FLAC__StreamDecoderState;
|
||||
|
||||
typedef enum {
|
||||
FLAC__STREAM_DECODER_READ_CONTINUE,
|
||||
FLAC__STREAM_DECODER_READ_END_OF_STREAM,
|
||||
FLAC__STREAM_DECODER_READ_ABORT
|
||||
} FLAC__StreamDecoderReadStatus;
|
||||
|
||||
typedef enum {
|
||||
FLAC__STREAM_DECODER_WRITE_CONTINUE,
|
||||
FLAC__STREAM_DECODER_WRITE_ABORT
|
||||
} FLAC__StreamDecoderWriteStatus;
|
||||
|
||||
typedef enum {
|
||||
FLAC__STREAM_DECODER_ERROR_LOST_SYNC
|
||||
} FLAC__StreamDecoderErrorStatus;
|
||||
|
||||
struct FLAC__StreamDecoderPrivate;
|
||||
typedef struct {
|
||||
/* these fields are read-only and valid as of the last write_callback() */
|
||||
unsigned channels;
|
||||
FLAC__ChannelAssignment channel_assignment;
|
||||
unsigned bits_per_sample;
|
||||
unsigned sample_rate; /* in Hz */
|
||||
unsigned blocksize; /* in samples (per channel) */
|
||||
FLAC__StreamDecoderState state; /* must be FLAC__STREAM_DECODER_UNINITIALIZED when passed to FLAC__stream_decoder_init() */
|
||||
struct FLAC__StreamDecoderPrivate *guts; /* must be 0 when passed to FLAC__stream_decoder_init() */
|
||||
} FLAC__StreamDecoder;
|
||||
|
||||
FLAC__StreamDecoder *FLAC__stream_decoder_get_new_instance();
|
||||
void FLAC__stream_decoder_free_instance(FLAC__StreamDecoder *decoder);
|
||||
FLAC__StreamDecoderState FLAC__stream_decoder_init(
|
||||
FLAC__StreamDecoder *decoder,
|
||||
FLAC__StreamDecoderReadStatus (*read_callback)(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data),
|
||||
FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__StreamDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data),
|
||||
void (*metadata_callback)(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data),
|
||||
void (*error_callback)(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data),
|
||||
void *client_data
|
||||
);
|
||||
void FLAC__stream_decoder_finish(FLAC__StreamDecoder *decoder);
|
||||
bool FLAC__stream_decoder_flush(FLAC__StreamDecoder *decoder);
|
||||
bool FLAC__stream_decoder_reset(FLAC__StreamDecoder *decoder);
|
||||
bool FLAC__stream_decoder_process_whole_stream(FLAC__StreamDecoder *decoder);
|
||||
bool FLAC__stream_decoder_process_metadata(FLAC__StreamDecoder *decoder);
|
||||
bool FLAC__stream_decoder_process_one_frame(FLAC__StreamDecoder *decoder);
|
||||
bool FLAC__stream_decoder_process_remaining_frames(FLAC__StreamDecoder *decoder);
|
||||
|
||||
#endif
|
16
src/flac/Makefile
Normal file
16
src/flac/Makefile
Normal file
@ -0,0 +1,16 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
PROGRAM_NAME = flac
|
||||
INCLUDES = -I./include -I../../include
|
||||
LIBS = -lFLAC -lm
|
||||
|
||||
OBJS = \
|
||||
decode.o \
|
||||
encode.o \
|
||||
main.o
|
||||
|
||||
include ../../build/exe.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
25
src/flac/Makefile.vc
Normal file
25
src/flac/Makefile.vc
Normal file
@ -0,0 +1,25 @@
|
||||
!include <win32.mak>
|
||||
|
||||
!IFDEF DEBUG
|
||||
.c.obj:
|
||||
$(cc) $(cdebug) $(cflags) /I "..\..\include" /I ".\include" -DSTRICT -YX /Od /D "_DEBUG" $<
|
||||
!else
|
||||
.c.obj:
|
||||
$(cc) $(cdebug) $(cflags) /I "..\..\include" /I ".\include" -DSTRICT -YX /O2 -DNODEBUG $<
|
||||
!endif
|
||||
|
||||
C_FILES= \
|
||||
decode.c \
|
||||
encode.c \
|
||||
main.c
|
||||
|
||||
OBJS= $(C_FILES:.c=.obj)
|
||||
|
||||
all: flac.exe
|
||||
|
||||
flac.exe: $(OBJS)
|
||||
link.exe /libpath:"..\..\obj\lib" -out:../../obj/bin/$*.exe $(OBJS) libFLAC.lib
|
||||
|
||||
clean:
|
||||
-del *.obj *.pch
|
||||
-del ..\..\obj\bin\flac.exe
|
377
src/flac/decode.c
Normal file
377
src/flac/decode.c
Normal file
@ -0,0 +1,377 @@
|
||||
/* flac - Command-line FLAC encoder/decoder
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
/* where MSVC puts unlink() */
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include <string.h> /* for strcmp() */
|
||||
#include "FLAC/all.h"
|
||||
#include "decode.h"
|
||||
|
||||
typedef struct {
|
||||
FILE *fout;
|
||||
bool abort_flag;
|
||||
bool is_wave_out;
|
||||
bool is_big_endian;
|
||||
bool is_unsigned_samples;
|
||||
uint64 total_samples;
|
||||
unsigned bps;
|
||||
unsigned channels;
|
||||
unsigned sample_rate;
|
||||
bool verbose;
|
||||
uint64 skip;
|
||||
uint64 samples_processed;
|
||||
unsigned frame_counter;
|
||||
} stream_info_struct;
|
||||
|
||||
static FLAC__FileDecoder *decoder;
|
||||
static bool is_big_endian_host;
|
||||
|
||||
/* local routines */
|
||||
static bool init(const char *infile, stream_info_struct *stream_info);
|
||||
static bool write_little_endian_uint16(FILE *f, uint16 val);
|
||||
static bool write_little_endian_uint32(FILE *f, uint32 val);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
|
||||
static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
static void print_stats(const stream_info_struct *stream_info);
|
||||
|
||||
int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip)
|
||||
{
|
||||
stream_info_struct stream_info;
|
||||
|
||||
decoder = 0;
|
||||
stream_info.abort_flag = false;
|
||||
stream_info.is_wave_out = true;
|
||||
stream_info.verbose = verbose;
|
||||
stream_info.skip = skip;
|
||||
stream_info.samples_processed = 0;
|
||||
stream_info.frame_counter = 0;
|
||||
|
||||
if(0 == strcmp(outfile, "-")) {
|
||||
stream_info.fout = stdout;
|
||||
}
|
||||
else {
|
||||
if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
|
||||
fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!init(infile, &stream_info))
|
||||
goto wav_abort_;
|
||||
|
||||
if(skip > 0) {
|
||||
if(!FLAC__file_decoder_process_metadata(decoder)) {
|
||||
fprintf(stderr, "ERROR during decoding\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
|
||||
fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
|
||||
goto wav_abort_;
|
||||
}
|
||||
if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
|
||||
fprintf(stderr, "ERROR during decodingg\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
|
||||
fprintf(stderr, "ERROR during decodinggg\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!FLAC__file_decoder_process_whole_file(decoder)) {
|
||||
fprintf(stderr, "ERROR during decoding\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
|
||||
fprintf(stderr, "ERROR during decodingg, state=%u\n", decoder->state);
|
||||
goto wav_abort_;
|
||||
}
|
||||
}
|
||||
|
||||
if(decoder) {
|
||||
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder);
|
||||
print_stats(&stream_info);
|
||||
FLAC__file_decoder_free_instance(decoder);
|
||||
}
|
||||
fclose(stream_info.fout);
|
||||
if(verbose)
|
||||
printf("\n");
|
||||
return 0;
|
||||
wav_abort_:
|
||||
if(decoder) {
|
||||
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder);
|
||||
FLAC__file_decoder_free_instance(decoder);
|
||||
}
|
||||
fclose(stream_info.fout);
|
||||
unlink(outfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples)
|
||||
{
|
||||
stream_info_struct stream_info;
|
||||
|
||||
decoder = 0;
|
||||
stream_info.abort_flag = false;
|
||||
stream_info.is_wave_out = false;
|
||||
stream_info.is_big_endian = is_big_endian;
|
||||
stream_info.is_unsigned_samples = is_unsigned_samples;
|
||||
stream_info.verbose = verbose;
|
||||
stream_info.skip = skip;
|
||||
stream_info.samples_processed = 0;
|
||||
stream_info.frame_counter = 0;
|
||||
|
||||
if(0 == strcmp(outfile, "-")) {
|
||||
stream_info.fout = stdout;
|
||||
}
|
||||
else {
|
||||
if(0 == (stream_info.fout = fopen(outfile, "wb"))) {
|
||||
fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!init(infile, &stream_info))
|
||||
goto raw_abort_;
|
||||
|
||||
if(skip > 0) {
|
||||
if(!FLAC__file_decoder_process_metadata(decoder)) {
|
||||
fprintf(stderr, "ERROR during decoding\n");
|
||||
goto raw_abort_;
|
||||
}
|
||||
if(!FLAC__file_decoder_seek_absolute(decoder, skip)) {
|
||||
fprintf(stderr, "ERROR seeking while skipping bytes in input file %s\n", infile);
|
||||
goto raw_abort_;
|
||||
}
|
||||
if(!FLAC__file_decoder_process_remaining_frames(decoder)) {
|
||||
fprintf(stderr, "ERROR during decodingg\n");
|
||||
goto raw_abort_;
|
||||
}
|
||||
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
|
||||
fprintf(stderr, "ERROR during decodinggg\n");
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(!FLAC__file_decoder_process_whole_file(decoder)) {
|
||||
fprintf(stderr, "ERROR during decoding\n");
|
||||
goto raw_abort_;
|
||||
}
|
||||
if(decoder->state != FLAC__FILE_DECODER_OK && decoder->state != FLAC__FILE_DECODER_END_OF_FILE) {
|
||||
fprintf(stderr, "ERROR during decodingg\n");
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
|
||||
if(decoder) {
|
||||
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder);
|
||||
print_stats(&stream_info);
|
||||
FLAC__file_decoder_free_instance(decoder);
|
||||
}
|
||||
fclose(stream_info.fout);
|
||||
if(verbose)
|
||||
printf("\n");
|
||||
return 0;
|
||||
raw_abort_:
|
||||
if(decoder) {
|
||||
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder);
|
||||
FLAC__file_decoder_free_instance(decoder);
|
||||
}
|
||||
fclose(stream_info.fout);
|
||||
unlink(outfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool init(const char *infile, stream_info_struct *stream_info)
|
||||
{
|
||||
uint32 test = 1;
|
||||
|
||||
is_big_endian_host = (*((byte*)(&test)))? false : true;
|
||||
|
||||
decoder = FLAC__file_decoder_get_new_instance();
|
||||
if(0 == decoder) {
|
||||
fprintf(stderr, "ERROR creating the decoder instance\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, stream_info) != FLAC__FILE_DECODER_OK) {
|
||||
fprintf(stderr, "ERROR initializing decoder, state = %d\n", decoder->state);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool write_little_endian_uint16(FILE *f, uint16 val)
|
||||
{
|
||||
byte *b = (byte*)(&val);
|
||||
if(is_big_endian_host) {
|
||||
byte tmp;
|
||||
tmp = b[1]; b[1] = b[0]; b[0] = tmp;
|
||||
}
|
||||
return fwrite(b, 1, 2, f) == 2;
|
||||
}
|
||||
|
||||
bool write_little_endian_uint32(FILE *f, uint32 val)
|
||||
{
|
||||
byte *b = (byte*)(&val);
|
||||
if(is_big_endian_host) {
|
||||
byte tmp;
|
||||
tmp = b[3]; b[3] = b[0]; b[0] = tmp;
|
||||
tmp = b[2]; b[2] = b[1]; b[1] = tmp;
|
||||
}
|
||||
return fwrite(b, 1, 4, f) == 4;
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
|
||||
{
|
||||
stream_info_struct *stream_info = (stream_info_struct *)client_data;
|
||||
FILE *fout = stream_info->fout;
|
||||
unsigned bps = stream_info->bps, channels = stream_info->channels;
|
||||
bool is_big_endian = (stream_info->is_wave_out? false : stream_info->is_big_endian);
|
||||
bool is_unsigned_samples = (stream_info->is_wave_out? bps==8 : stream_info->is_unsigned_samples);
|
||||
unsigned wide_samples = header->blocksize, wide_sample, sample, channel, byte;
|
||||
static signed char scbuffer[FLAC__MAX_BLOCK_SIZE * FLAC__MAX_CHANNELS * ((FLAC__MAX_BITS_PER_SAMPLE+7)>>3)]; /* WATCHOUT: can be up to 2 megs */
|
||||
unsigned char *ucbuffer = (unsigned char *)scbuffer;
|
||||
signed short *ssbuffer = (signed short *)scbuffer;
|
||||
unsigned short *usbuffer = (unsigned short *)scbuffer;
|
||||
|
||||
(void)decoder;
|
||||
|
||||
if(stream_info->abort_flag)
|
||||
return FLAC__STREAM_DECODER_WRITE_ABORT;
|
||||
|
||||
stream_info->samples_processed += wide_samples;
|
||||
stream_info->frame_counter++;
|
||||
|
||||
if(stream_info->verbose && !(stream_info->frame_counter & 0x1f))
|
||||
print_stats(stream_info);
|
||||
|
||||
if(bps == 8) {
|
||||
if(is_unsigned_samples) {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
ucbuffer[sample] = buffer[channel][wide_sample] + 128;
|
||||
}
|
||||
else {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
scbuffer[sample] = buffer[channel][wide_sample];
|
||||
}
|
||||
if(fwrite(ucbuffer, 1, sample, fout) != sample)
|
||||
return FLAC__STREAM_DECODER_WRITE_ABORT;
|
||||
}
|
||||
else { /* bps == 16 */
|
||||
if(is_unsigned_samples) {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
usbuffer[sample] = buffer[channel][wide_sample] + 32768;
|
||||
}
|
||||
else {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
ssbuffer[sample] = buffer[channel][wide_sample];
|
||||
}
|
||||
if(is_big_endian != is_big_endian_host) {
|
||||
unsigned char tmp;
|
||||
for(byte = 0; byte < sample<<1; byte += 2) {
|
||||
tmp = ucbuffer[byte];
|
||||
ucbuffer[byte] = ucbuffer[byte+1];
|
||||
ucbuffer[byte+1] = tmp;
|
||||
}
|
||||
}
|
||||
if(fwrite(usbuffer, 2, sample, fout) != sample)
|
||||
return FLAC__STREAM_DECODER_WRITE_ABORT;
|
||||
}
|
||||
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
|
||||
}
|
||||
|
||||
void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
|
||||
{
|
||||
stream_info_struct *stream_info = (stream_info_struct *)client_data;
|
||||
(void)decoder;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_ENCODING) {
|
||||
stream_info->total_samples = metadata->data.encoding.total_samples - stream_info->skip;
|
||||
stream_info->bps = metadata->data.encoding.bits_per_sample;
|
||||
stream_info->channels = metadata->data.encoding.channels;
|
||||
stream_info->sample_rate = metadata->data.encoding.sample_rate;
|
||||
|
||||
if(stream_info->bps != 8 && stream_info->bps != 16) {
|
||||
fprintf(stderr, "ERROR: bits per sample is not 8 or 16\n");
|
||||
stream_info->abort_flag = true;
|
||||
return;
|
||||
}
|
||||
|
||||
/* write the WAVE headers if necessary */
|
||||
if(stream_info->is_wave_out) {
|
||||
uint64 data_size = stream_info->total_samples * stream_info->channels * ((stream_info->bps+7)/8);
|
||||
if(data_size >= 0xFFFFFFDC) {
|
||||
fprintf(stderr, "ERROR: stream is too big for a wave file\n");
|
||||
stream_info->abort_flag = true;
|
||||
return;
|
||||
}
|
||||
if(fwrite("RIFF", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
|
||||
if(!write_little_endian_uint32(stream_info->fout, (uint32)(data_size+36))) stream_info->abort_flag = true; /* filesize-8 */
|
||||
if(fwrite("WAVEfmt ", 1, 8, stream_info->fout) != 8) stream_info->abort_flag = true;
|
||||
if(fwrite("\020\000\000\000", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true; /* chunk size = 16 */
|
||||
if(fwrite("\001\000", 1, 2, stream_info->fout) != 2) stream_info->abort_flag = true; /* compression code == 1 */
|
||||
if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels))) stream_info->abort_flag = true;
|
||||
if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate)) stream_info->abort_flag = true;
|
||||
if(!write_little_endian_uint32(stream_info->fout, stream_info->sample_rate * stream_info->channels * ((stream_info->bps+7) / 8))) stream_info->abort_flag = true; /* @@@ or is it (sample_rate*channels*bps) / 8 ??? */
|
||||
if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->channels * ((stream_info->bps+7) / 8)))) stream_info->abort_flag = true; /* block align */
|
||||
if(!write_little_endian_uint16(stream_info->fout, (uint16)(stream_info->bps))) stream_info->abort_flag = true; /* bits per sample */
|
||||
if(fwrite("data", 1, 4, stream_info->fout) != 4) stream_info->abort_flag = true;
|
||||
if(!write_little_endian_uint32(stream_info->fout, (uint32)data_size)) stream_info->abort_flag = true; /* data size */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
stream_info_struct *stream_info = (stream_info_struct *)client_data;
|
||||
(void)decoder;
|
||||
fprintf(stderr, "*** Got error code %d\n", status);
|
||||
stream_info->abort_flag = true;
|
||||
}
|
||||
|
||||
void print_stats(const stream_info_struct *stream_info)
|
||||
{
|
||||
if(stream_info->verbose) {
|
||||
printf("\rwrote %u of %u samples, %6.2f%% complete",
|
||||
(unsigned)stream_info->samples_processed,
|
||||
(unsigned)stream_info->total_samples,
|
||||
#ifdef _MSC_VER
|
||||
/* with VC++ you have to spoon feed it the casting */
|
||||
(double)(int64)stream_info->samples_processed / (double)(int64)stream_info->total_samples * 100.0
|
||||
#else
|
||||
(double)stream_info->samples_processed / (double)stream_info->total_samples * 100.0
|
||||
#endif
|
||||
);
|
||||
fflush(stdout);
|
||||
}
|
||||
}
|
25
src/flac/decode.h
Normal file
25
src/flac/decode.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* flac - Command-line FLAC encoder/decoder
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef flac__decode_h
|
||||
#define flac__decode_h
|
||||
|
||||
int decode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip);
|
||||
int decode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool is_big_endian, bool is_unsigned_samples);
|
||||
|
||||
#endif
|
587
src/flac/encode.c
Normal file
587
src/flac/encode.c
Normal file
@ -0,0 +1,587 @@
|
||||
/* flac - Command-line FLAC encoder/decoder
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#if defined _WIN32 && !defined __CYGWIN__
|
||||
/* where MSVC puts unlink() */
|
||||
# include <io.h>
|
||||
#else
|
||||
# include <unistd.h>
|
||||
#endif
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include <string.h> /* for strcmp() */
|
||||
#include "FLAC/all.h"
|
||||
#include "encode.h"
|
||||
|
||||
#define CHUNK_OF_SAMPLES 2048
|
||||
|
||||
typedef struct {
|
||||
FILE *fout;
|
||||
const char *outfile;
|
||||
FLAC__Encoder *encoder;
|
||||
bool verbose;
|
||||
uint64 unencoded_size;
|
||||
uint64 total_samples_to_encode;
|
||||
uint64 bytes_written;
|
||||
uint64 samples_written;
|
||||
unsigned current_frame;
|
||||
} encoder_wrapper_struct;
|
||||
|
||||
static bool is_big_endian_host;
|
||||
|
||||
static unsigned char ucbuffer[CHUNK_OF_SAMPLES*FLAC__MAX_CHANNELS*(FLAC__MAX_BITS_PER_SAMPLE>>3)];
|
||||
static signed char *scbuffer = (signed char *)ucbuffer;
|
||||
static uint16 *usbuffer = (uint16 *)ucbuffer;
|
||||
static int16 *ssbuffer = (int16 *)ucbuffer;
|
||||
|
||||
static int32 in[FLAC__MAX_CHANNELS][CHUNK_OF_SAMPLES];
|
||||
static int32 *input[FLAC__MAX_CHANNELS];
|
||||
|
||||
/* local routines */
|
||||
static bool init(encoder_wrapper_struct *encoder_wrapper);
|
||||
static bool init_encoder(bool lax, bool do_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper);
|
||||
static void format_input(unsigned wide_samples, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps);
|
||||
static FLAC__EncoderWriteStatus write_callback(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
static void metadata_callback(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
static void print_stats(const encoder_wrapper_struct *encoder_wrapper);
|
||||
static bool read_little_endian_uint16(FILE *f, uint16 *val, bool eof_ok);
|
||||
static bool read_little_endian_uint32(FILE *f, uint32 *val, bool eof_ok);
|
||||
|
||||
int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip, bool lax, bool do_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision)
|
||||
{
|
||||
encoder_wrapper_struct encoder_wrapper;
|
||||
FILE *fin;
|
||||
bool is_unsigned_samples;
|
||||
unsigned channels, bps, sample_rate, data_bytes;
|
||||
size_t bytes_per_wide_sample, bytes_read;
|
||||
uint16 x;
|
||||
uint32 xx;
|
||||
|
||||
encoder_wrapper.encoder = 0;
|
||||
encoder_wrapper.verbose = verbose;
|
||||
encoder_wrapper.bytes_written = 0;
|
||||
encoder_wrapper.samples_written = 0;
|
||||
encoder_wrapper.outfile = outfile;
|
||||
|
||||
if(0 == strcmp(infile, "-")) {
|
||||
fin = stdin;
|
||||
}
|
||||
else {
|
||||
if(0 == (fin = fopen(infile, "rb"))) {
|
||||
fprintf(stderr, "ERROR: can't open input file %s\n", infile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(0 == strcmp(outfile, "-")) {
|
||||
encoder_wrapper.fout = stdout;
|
||||
}
|
||||
else {
|
||||
if(0 == (encoder_wrapper.fout = fopen(outfile, "wb"))) {
|
||||
fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
|
||||
fclose(fin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!init(&encoder_wrapper))
|
||||
goto wav_abort_;
|
||||
|
||||
/*
|
||||
* check the RIFF chunk
|
||||
*/
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
if(xx != 0x46464952) { /* "RIFF" */
|
||||
fprintf(stderr, "ERROR: no RIFF header\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
|
||||
/*
|
||||
* now process the WAVE chunk
|
||||
*/
|
||||
if(!read_little_endian_uint32(fin, &xx, true))
|
||||
goto wav_end_;
|
||||
if(xx != 0x45564157) { /* "WAVE" */
|
||||
fprintf(stderr, "ERROR: no WAVE header\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
|
||||
/* do the format sub-chunk */
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
if(xx != 0x20746d66) { /* "fmt " */
|
||||
fprintf(stderr, "ERROR: no format sub-chunk\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
/* fmt chunk size */
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
if(xx != 16) {
|
||||
fprintf(stderr, "ERROR: unsupported chunk\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
/* compression code */
|
||||
if(!read_little_endian_uint16(fin, &x, false))
|
||||
goto wav_abort_;
|
||||
if(x != 1) {
|
||||
fprintf(stderr, "ERROR: unsupported compression type %u\n", (unsigned)x);
|
||||
goto wav_abort_;
|
||||
}
|
||||
/* number of channels */
|
||||
if(!read_little_endian_uint16(fin, &x, false))
|
||||
goto wav_abort_;
|
||||
if(x == 0 || x > FLAC__MAX_CHANNELS) {
|
||||
fprintf(stderr, "ERROR: unsupported number channels %u\n", (unsigned)x);
|
||||
goto wav_abort_;
|
||||
}
|
||||
channels = x;
|
||||
/* sample rate */
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
if(xx == 0 || xx > FLAC__MAX_SAMPLE_RATE) {
|
||||
fprintf(stderr, "ERROR: unsupported sample rate %u\n", (unsigned)xx);
|
||||
goto wav_abort_;
|
||||
}
|
||||
sample_rate = xx;
|
||||
/* avg bytes per second (ignored) */
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
/* block align (ignored) */
|
||||
if(!read_little_endian_uint16(fin, &x, false))
|
||||
goto wav_abort_;
|
||||
/* bits per sample */
|
||||
if(!read_little_endian_uint16(fin, &x, false))
|
||||
goto wav_abort_;
|
||||
if(x != 8 && x != 16) {
|
||||
fprintf(stderr, "ERROR: unsupported bits per sample %u\n", (unsigned)x);
|
||||
goto wav_abort_;
|
||||
}
|
||||
bps = x;
|
||||
is_unsigned_samples = (x == 8);
|
||||
|
||||
/* do the data sub-chunk */
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
if(xx != 0x61746164) { /* "data" */
|
||||
fprintf(stderr, "ERROR: no data sub-chunk\n");
|
||||
goto wav_abort_;
|
||||
}
|
||||
/* data size */
|
||||
if(!read_little_endian_uint32(fin, &xx, false))
|
||||
goto wav_abort_;
|
||||
data_bytes = xx;
|
||||
|
||||
if(!init_encoder(lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, &encoder_wrapper))
|
||||
goto wav_abort_;
|
||||
|
||||
bytes_per_wide_sample = channels * (bps >> 3);
|
||||
|
||||
if(-1 == fseek(fin, bytes_per_wide_sample * (unsigned)skip, SEEK_CUR)) {
|
||||
fprintf(stderr, "ERROR seeking while skipping samples in input file %s\n", infile);
|
||||
goto wav_abort_;
|
||||
}
|
||||
|
||||
encoder_wrapper.total_samples_to_encode = data_bytes / bytes_per_wide_sample - skip;
|
||||
encoder_wrapper.unencoded_size = encoder_wrapper.total_samples_to_encode * bytes_per_wide_sample + 44; /* 44 for the size of the WAV headers */
|
||||
|
||||
while(data_bytes > 0) {
|
||||
bytes_read = fread(ucbuffer, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, fin);
|
||||
if(bytes_read == 0) {
|
||||
if(ferror(fin)) {
|
||||
fprintf(stderr, "ERROR reading from %s\n", infile);
|
||||
goto wav_abort_;
|
||||
}
|
||||
else if(feof(fin))
|
||||
break;
|
||||
}
|
||||
else if(bytes_read % bytes_per_wide_sample != 0) {
|
||||
fprintf(stderr, "ERROR, got partial sample from input file %s\n", infile);
|
||||
goto wav_abort_;
|
||||
}
|
||||
else {
|
||||
unsigned wide_samples = bytes_read / bytes_per_wide_sample;
|
||||
format_input(wide_samples, false, is_unsigned_samples, channels, bps);
|
||||
if(!FLAC__encoder_process(encoder_wrapper.encoder, input, wide_samples)) {
|
||||
fprintf(stderr, "ERROR during encoding, state = %d\n", encoder_wrapper.encoder->state);
|
||||
goto wav_abort_;
|
||||
}
|
||||
data_bytes -= bytes_read;
|
||||
}
|
||||
}
|
||||
|
||||
wav_end_:
|
||||
if(encoder_wrapper.encoder) {
|
||||
if(encoder_wrapper.encoder->state != FLAC__ENCODER_UNINITIALIZED)
|
||||
FLAC__encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__encoder_free_instance(encoder_wrapper.encoder);
|
||||
}
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
|
||||
print_stats(&encoder_wrapper);
|
||||
printf("\n");
|
||||
}
|
||||
fclose(fin);
|
||||
return 0;
|
||||
wav_abort_:
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0)
|
||||
printf("\n");
|
||||
if(encoder_wrapper.encoder) {
|
||||
if(encoder_wrapper.encoder->state != FLAC__ENCODER_UNINITIALIZED)
|
||||
FLAC__encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__encoder_free_instance(encoder_wrapper.encoder);
|
||||
}
|
||||
fclose(fin);
|
||||
unlink(outfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool lax, bool do_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate)
|
||||
{
|
||||
encoder_wrapper_struct encoder_wrapper;
|
||||
FILE *fin;
|
||||
size_t bytes_read;
|
||||
const size_t bytes_per_wide_sample = channels * (bps >> 3);
|
||||
|
||||
encoder_wrapper.encoder = 0;
|
||||
encoder_wrapper.verbose = verbose;
|
||||
encoder_wrapper.bytes_written = 0;
|
||||
encoder_wrapper.samples_written = 0;
|
||||
encoder_wrapper.outfile = outfile;
|
||||
|
||||
if(0 == strcmp(infile, "-")) {
|
||||
fin = stdin;
|
||||
}
|
||||
else {
|
||||
if(0 == (fin = fopen(infile, "rb"))) {
|
||||
fprintf(stderr, "ERROR: can't open input file %s\n", infile);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(0 == strcmp(outfile, "-")) {
|
||||
encoder_wrapper.fout = stdout;
|
||||
}
|
||||
else {
|
||||
if(0 == (encoder_wrapper.fout = fopen(outfile, "wb"))) {
|
||||
fprintf(stderr, "ERROR: can't open output file %s\n", outfile);
|
||||
fclose(fin);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if(!init(&encoder_wrapper))
|
||||
goto raw_abort_;
|
||||
|
||||
if(!init_encoder(lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, blocksize, qlp_coeff_precision, channels, bps, sample_rate, &encoder_wrapper))
|
||||
goto raw_abort_;
|
||||
|
||||
/* get the file length */
|
||||
if(0 != fseek(fin, 0, SEEK_END)) {
|
||||
encoder_wrapper.total_samples_to_encode = encoder_wrapper.unencoded_size = 0;
|
||||
}
|
||||
else {
|
||||
long filesize;
|
||||
fflush(fin);
|
||||
if(-1 == (filesize = ftell(fin))) {
|
||||
encoder_wrapper.total_samples_to_encode = encoder_wrapper.unencoded_size = 0;
|
||||
}
|
||||
else {
|
||||
encoder_wrapper.unencoded_size = filesize - skip * bytes_per_wide_sample;
|
||||
encoder_wrapper.total_samples_to_encode = filesize / bytes_per_wide_sample - skip;
|
||||
}
|
||||
}
|
||||
|
||||
if(-1 == fseek(fin, bytes_per_wide_sample * (unsigned)skip, SEEK_SET)) {
|
||||
fprintf(stderr, "ERROR seeking while skipping samples in input file %s\n", infile);
|
||||
goto raw_abort_;
|
||||
}
|
||||
|
||||
while(!feof(fin)) {
|
||||
bytes_read = fread(ucbuffer, sizeof(unsigned char), CHUNK_OF_SAMPLES * bytes_per_wide_sample, fin);
|
||||
if(bytes_read == 0) {
|
||||
if(ferror(fin)) {
|
||||
fprintf(stderr, "ERROR reading from %s\n", infile);
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
else if(bytes_read % bytes_per_wide_sample != 0) {
|
||||
fprintf(stderr, "ERROR, got partial sample from input file %s\n", infile);
|
||||
goto raw_abort_;
|
||||
}
|
||||
else {
|
||||
unsigned wide_samples = bytes_read / bytes_per_wide_sample;
|
||||
format_input(wide_samples, is_big_endian, is_unsigned_samples, channels, bps);
|
||||
if(!FLAC__encoder_process(encoder_wrapper.encoder, input, wide_samples)) {
|
||||
fprintf(stderr, "ERROR during encoding, state = %d\n", encoder_wrapper.encoder->state);
|
||||
goto raw_abort_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(encoder_wrapper.encoder) {
|
||||
if(encoder_wrapper.encoder->state != FLAC__ENCODER_UNINITIALIZED)
|
||||
FLAC__encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__encoder_free_instance(encoder_wrapper.encoder);
|
||||
}
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0) {
|
||||
print_stats(&encoder_wrapper);
|
||||
printf("\n");
|
||||
}
|
||||
fclose(fin);
|
||||
return 0;
|
||||
raw_abort_:
|
||||
if(encoder_wrapper.verbose && encoder_wrapper.total_samples_to_encode > 0)
|
||||
printf("\n");
|
||||
if(encoder_wrapper.encoder) {
|
||||
if(encoder_wrapper.encoder->state != FLAC__ENCODER_UNINITIALIZED)
|
||||
FLAC__encoder_finish(encoder_wrapper.encoder);
|
||||
FLAC__encoder_free_instance(encoder_wrapper.encoder);
|
||||
}
|
||||
fclose(fin);
|
||||
unlink(outfile);
|
||||
return 1;
|
||||
}
|
||||
|
||||
bool init(encoder_wrapper_struct *encoder_wrapper)
|
||||
{
|
||||
unsigned i;
|
||||
uint32 test = 1;
|
||||
|
||||
is_big_endian_host = (*((byte*)(&test)))? false : true;
|
||||
|
||||
for(i = 0; i < FLAC__MAX_CHANNELS; i++)
|
||||
input[i] = &(in[i][0]);
|
||||
|
||||
encoder_wrapper->encoder = FLAC__encoder_get_new_instance();
|
||||
if(0 == encoder_wrapper->encoder) {
|
||||
fprintf(stderr, "ERROR creating the encoder instance\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool init_encoder(bool lax, bool do_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, unsigned channels, unsigned bps, unsigned sample_rate, encoder_wrapper_struct *encoder_wrapper)
|
||||
{
|
||||
if(channels != 2 || bps > 16)
|
||||
do_mid_side = false;
|
||||
|
||||
encoder_wrapper->encoder->streamable_subset = !lax;
|
||||
encoder_wrapper->encoder->channels = channels;
|
||||
encoder_wrapper->encoder->bits_per_sample = bps;
|
||||
encoder_wrapper->encoder->sample_rate = sample_rate;
|
||||
encoder_wrapper->encoder->blocksize = blocksize;
|
||||
encoder_wrapper->encoder->qlp_coeff_precision = qlp_coeff_precision;
|
||||
encoder_wrapper->encoder->max_lpc_order = max_lpc_order;
|
||||
encoder_wrapper->encoder->do_mid_side_stereo = do_mid_side;
|
||||
encoder_wrapper->encoder->do_exhaustive_model_search = do_exhaustive_model_search;
|
||||
encoder_wrapper->encoder->do_qlp_coeff_prec_search = do_qlp_coeff_prec_search;
|
||||
encoder_wrapper->encoder->rice_optimization_level = rice_optimization_level;
|
||||
|
||||
if(FLAC__encoder_init(encoder_wrapper->encoder, write_callback, metadata_callback, encoder_wrapper) != FLAC__ENCODER_OK) {
|
||||
fprintf(stderr, "ERROR initializing encoder, state = %d\n", encoder_wrapper->encoder->state);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void format_input(unsigned wide_samples, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps)
|
||||
{
|
||||
unsigned wide_sample, sample, channel, byte;
|
||||
|
||||
if(bps == 8) {
|
||||
if(is_unsigned_samples) {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
input[channel][wide_sample] = (int32)ucbuffer[sample] - 128;
|
||||
}
|
||||
else {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
input[channel][wide_sample] = (int32)scbuffer[sample];
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(is_big_endian != is_big_endian_host) {
|
||||
unsigned char tmp;
|
||||
const unsigned bytes = wide_samples * channels * (bps >> 3);
|
||||
for(byte = 0; byte < bytes; byte += 2) {
|
||||
tmp = ucbuffer[byte];
|
||||
ucbuffer[byte] = ucbuffer[byte+1];
|
||||
ucbuffer[byte+1] = tmp;
|
||||
}
|
||||
}
|
||||
if(is_unsigned_samples) {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
input[channel][wide_sample] = (int32)usbuffer[sample] - 32768;
|
||||
}
|
||||
else {
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
input[channel][wide_sample] = (int32)ssbuffer[sample];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__EncoderWriteStatus write_callback(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data)
|
||||
{
|
||||
encoder_wrapper_struct *encoder_wrapper = (encoder_wrapper_struct *)client_data;
|
||||
unsigned mask = (encoder->do_exhaustive_model_search || encoder->do_qlp_coeff_prec_search)? 0x07 : 0x1f;
|
||||
|
||||
encoder_wrapper->bytes_written += bytes;
|
||||
encoder_wrapper->samples_written += samples;
|
||||
encoder_wrapper->current_frame = current_frame;
|
||||
|
||||
if(samples && encoder_wrapper->verbose && encoder_wrapper->total_samples_to_encode > 0 && !(current_frame & mask))
|
||||
print_stats(encoder_wrapper);
|
||||
|
||||
if(fwrite(buffer, sizeof(byte), bytes, encoder_wrapper->fout) == bytes)
|
||||
return FLAC__ENCODER_WRITE_OK;
|
||||
else
|
||||
return FLAC__ENCODER_WRITE_FATAL_ERROR;
|
||||
}
|
||||
|
||||
void metadata_callback(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data)
|
||||
{
|
||||
encoder_wrapper_struct *encoder_wrapper = (encoder_wrapper_struct *)client_data;
|
||||
byte b;
|
||||
FILE *f;
|
||||
const uint64 samples = metadata->data.encoding.total_samples;
|
||||
const unsigned min_framesize = metadata->data.encoding.min_framesize;
|
||||
const unsigned max_framesize = metadata->data.encoding.max_framesize;
|
||||
|
||||
(void)encoder; /* silence compiler warning about unused parameter */
|
||||
|
||||
if(encoder_wrapper->fout == stdout)
|
||||
return;
|
||||
|
||||
fclose(encoder_wrapper->fout);
|
||||
if(0 == (f = fopen(encoder_wrapper->outfile, "r+b")))
|
||||
return;
|
||||
|
||||
/* all this is based on intimate knowledge of the stream header
|
||||
* layout, but a change to the header format that would break this
|
||||
* would also break all streams encoded in the previous format.
|
||||
*/
|
||||
|
||||
if(-1 == fseek(f, 21, SEEK_SET)) goto framesize_;
|
||||
if(fread(&b, 1, 1, f) != 1) goto framesize_;
|
||||
if(-1 == fseek(f, 21, SEEK_SET)) goto framesize_;
|
||||
b = (b & 0xf0) | (byte)((samples >> 32) & 0x0F);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
|
||||
b = (byte)((samples >> 24) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
|
||||
b = (byte)((samples >> 16) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
|
||||
b = (byte)((samples >> 8) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
|
||||
b = (byte)(samples & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto framesize_;
|
||||
|
||||
framesize_:
|
||||
if(-1 == fseek(f, 12, SEEK_SET)) goto end_;
|
||||
b = (byte)((min_framesize >> 16) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto end_;
|
||||
b = (byte)((min_framesize >> 8) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto end_;
|
||||
b = (byte)(min_framesize & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto end_;
|
||||
b = (byte)((max_framesize >> 16) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto end_;
|
||||
b = (byte)((max_framesize >> 8) & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto end_;
|
||||
b = (byte)(max_framesize & 0xFF);
|
||||
if(fwrite(&b, 1, 1, f) != 1) goto end_;
|
||||
end_:
|
||||
fclose(encoder_wrapper->fout);
|
||||
return;
|
||||
}
|
||||
|
||||
void print_stats(const encoder_wrapper_struct *encoder_wrapper)
|
||||
{
|
||||
#ifdef _MSC_VER
|
||||
/* with VC++ you have to spoon feed it the casting */
|
||||
double progress = (double)(int64)encoder_wrapper->samples_written / (double)(int64)encoder_wrapper->total_samples_to_encode;
|
||||
#else
|
||||
double progress = (double)encoder_wrapper->samples_written / (double)encoder_wrapper->total_samples_to_encode;
|
||||
#endif
|
||||
printf("\r%0.2f%% complete: frame %u, wrote %u bytes, %u of %u samples, ratio = %5.3f",
|
||||
progress * 100.0, encoder_wrapper->current_frame,
|
||||
(unsigned)encoder_wrapper->bytes_written, (unsigned)encoder_wrapper->samples_written, (unsigned)encoder_wrapper->total_samples_to_encode,
|
||||
#ifdef _MSC_VER
|
||||
/* with VC++ you have to spoon feed it the casting */
|
||||
(double)(int64)encoder_wrapper->bytes_written / ((double)(int64)encoder_wrapper->unencoded_size * progress)
|
||||
#else
|
||||
(double)encoder_wrapper->bytes_written / ((double)encoder_wrapper->unencoded_size * progress)
|
||||
#endif
|
||||
);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
bool read_little_endian_uint16(FILE *f, uint16 *val, bool eof_ok)
|
||||
{
|
||||
size_t bytes_read = fread(val, 1, 2, f);
|
||||
|
||||
if(bytes_read == 0) {
|
||||
if(!eof_ok) {
|
||||
fprintf(stderr, "ERROR: unexpected EOF\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if(bytes_read < 2) {
|
||||
fprintf(stderr, "ERROR: unexpected EOF\n");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(is_big_endian_host) {
|
||||
byte tmp, *b = (byte*)val;
|
||||
tmp = b[1]; b[1] = b[0]; b[0] = tmp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool read_little_endian_uint32(FILE *f, uint32 *val, bool eof_ok)
|
||||
{
|
||||
size_t bytes_read = fread(val, 1, 4, f);
|
||||
|
||||
if(bytes_read == 0) {
|
||||
if(!eof_ok) {
|
||||
fprintf(stderr, "ERROR: unexpected EOF\n");
|
||||
return false;
|
||||
}
|
||||
else
|
||||
return true;
|
||||
}
|
||||
else if(bytes_read < 4) {
|
||||
fprintf(stderr, "ERROR: unexpected EOF\n");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if(is_big_endian_host) {
|
||||
byte tmp, *b = (byte*)val;
|
||||
tmp = b[3]; b[3] = b[0]; b[0] = tmp;
|
||||
tmp = b[2]; b[2] = b[1]; b[1] = tmp;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
27
src/flac/encode.h
Normal file
27
src/flac/encode.h
Normal file
@ -0,0 +1,27 @@
|
||||
/* flac - Command-line FLAC encoder/decoder
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef flac__encode_h
|
||||
#define flac__encode_h
|
||||
|
||||
#include "FLAC/ordinals.h"
|
||||
|
||||
int encode_wav(const char *infile, const char *outfile, bool verbose, uint64 skip, bool lax, bool do_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision);
|
||||
int encode_raw(const char *infile, const char *outfile, bool verbose, uint64 skip, bool lax, bool do_mid_side, bool do_exhaustive_model_search, bool do_qlp_coeff_prec_search, unsigned rice_optimization_level, unsigned max_lpc_order, unsigned blocksize, unsigned qlp_coeff_precision, bool is_big_endian, bool is_unsigned_samples, unsigned channels, unsigned bps, unsigned sample_rate);
|
||||
|
||||
#endif
|
338
src/flac/main.c
Normal file
338
src/flac/main.c
Normal file
@ -0,0 +1,338 @@
|
||||
/* flac - Command-line FLAC encoder/decoder
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "FLAC/all.h"
|
||||
#include "decode.h"
|
||||
#include "encode.h"
|
||||
|
||||
static int usage(const char *message, ...);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int i;
|
||||
bool verbose = true, lax = false, mode_decode = false, do_mid_side = true, do_exhaustive_model_search = false, do_qlp_coeff_prec_search = false;
|
||||
unsigned max_lpc_order = 8;
|
||||
unsigned qlp_coeff_precision = 0;
|
||||
uint64 skip = 0;
|
||||
int format_is_wave = -1, format_is_big_endian = -1, format_is_unsigned_samples = false;
|
||||
int format_channels = -1, format_bps = -1, format_sample_rate = -1;
|
||||
int blocksize = -1, rice_optimization_level = -1;
|
||||
|
||||
if(argc <= 1)
|
||||
return usage(0);
|
||||
|
||||
/* get the options */
|
||||
for(i = 1; i < argc; i++) {
|
||||
if(argv[i][0] != '-' || argv[i][1] == 0)
|
||||
break;
|
||||
if(0 == strcmp(argv[i], "-d"))
|
||||
mode_decode = true;
|
||||
else if(0 == strcmp(argv[i], "-s"))
|
||||
verbose = false;
|
||||
else if(0 == strcmp(argv[i], "-s-"))
|
||||
verbose = true;
|
||||
else if(0 == strcmp(argv[i], "--skip"))
|
||||
skip = (uint64)atoi(argv[++i]); /* takes a pretty damn big file to overflow atoi() here, but it could happen */
|
||||
else if(0 == strcmp(argv[i], "--lax"))
|
||||
lax = true;
|
||||
else if(0 == strcmp(argv[i], "--lax-"))
|
||||
lax = false;
|
||||
else if(0 == strcmp(argv[i], "-b"))
|
||||
blocksize = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-e"))
|
||||
do_exhaustive_model_search = true;
|
||||
else if(0 == strcmp(argv[i], "-e-"))
|
||||
do_exhaustive_model_search = false;
|
||||
else if(0 == strcmp(argv[i], "-l"))
|
||||
max_lpc_order = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-m"))
|
||||
do_mid_side = true;
|
||||
else if(0 == strcmp(argv[i], "-m-"))
|
||||
do_mid_side = false;
|
||||
else if(0 == strcmp(argv[i], "-p"))
|
||||
do_qlp_coeff_prec_search = true;
|
||||
else if(0 == strcmp(argv[i], "-p-"))
|
||||
do_qlp_coeff_prec_search = false;
|
||||
else if(0 == strcmp(argv[i], "-q"))
|
||||
qlp_coeff_precision = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-r"))
|
||||
rice_optimization_level = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-fb"))
|
||||
format_is_big_endian = true;
|
||||
else if(0 == strcmp(argv[i], "-fl"))
|
||||
format_is_big_endian = false;
|
||||
else if(0 == strcmp(argv[i], "-fc"))
|
||||
format_channels = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-fp"))
|
||||
format_bps = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-fs"))
|
||||
format_sample_rate = atoi(argv[++i]);
|
||||
else if(0 == strcmp(argv[i], "-fu"))
|
||||
format_is_unsigned_samples = true;
|
||||
else if(0 == strcmp(argv[i], "-fr"))
|
||||
format_is_wave = false;
|
||||
else if(0 == strcmp(argv[i], "-fw"))
|
||||
format_is_wave = true;
|
||||
else if(0 == strcmp(argv[i], "-0")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = false;
|
||||
qlp_coeff_precision = 0;
|
||||
rice_optimization_level = 0;
|
||||
max_lpc_order = 0;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-1")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = true;
|
||||
qlp_coeff_precision = 0;
|
||||
rice_optimization_level = 0;
|
||||
max_lpc_order = 0;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-2")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = true;
|
||||
qlp_coeff_precision = 0;
|
||||
max_lpc_order = 0;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-4")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = false;
|
||||
qlp_coeff_precision = 0;
|
||||
rice_optimization_level = 0;
|
||||
max_lpc_order = 8;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-5")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = true;
|
||||
qlp_coeff_precision = 0;
|
||||
rice_optimization_level = 0;
|
||||
max_lpc_order = 8;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-6")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = true;
|
||||
qlp_coeff_precision = 0;
|
||||
max_lpc_order = 8;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-8")) {
|
||||
do_exhaustive_model_search = false;
|
||||
do_mid_side = true;
|
||||
qlp_coeff_precision = 0;
|
||||
max_lpc_order = 32;
|
||||
}
|
||||
else if(0 == strcmp(argv[i], "-9")) {
|
||||
do_exhaustive_model_search = true;
|
||||
do_mid_side = true;
|
||||
do_qlp_coeff_prec_search = true;
|
||||
rice_optimization_level = 99;
|
||||
max_lpc_order = 32;
|
||||
}
|
||||
else if(isdigit((int)(argv[i][1]))) {
|
||||
return usage("ERROR: compression level '%s' is still reserved\n", argv[i]);
|
||||
}
|
||||
else {
|
||||
return usage("ERROR: invalid option '%s'\n", argv[i]);
|
||||
}
|
||||
}
|
||||
if(i + 2 != argc)
|
||||
return usage("ERROR: invalid arguments (more/less than 2 filenames?)\n");
|
||||
|
||||
/* tweak options based on the filenames; validate the values */
|
||||
if(!mode_decode) {
|
||||
if(format_is_wave < 0) {
|
||||
if(strstr(argv[i], ".wav") == argv[i] + (strlen(argv[i]) - strlen(".wav")))
|
||||
format_is_wave = true;
|
||||
else
|
||||
format_is_wave = false;
|
||||
}
|
||||
if(!format_is_wave) {
|
||||
if(format_is_big_endian < 0 || format_channels < 0 || format_bps < 0 || format_sample_rate < 0)
|
||||
return usage("ERROR: for encoding a raw file you must specify { -fb or -fl }, -fc, -fp, and -fs\n");
|
||||
}
|
||||
if(blocksize < 0) {
|
||||
if(max_lpc_order == 0)
|
||||
blocksize = 1152;
|
||||
else
|
||||
blocksize = 4608;
|
||||
}
|
||||
if(rice_optimization_level < 0) {
|
||||
if(blocksize <= 1152)
|
||||
rice_optimization_level = 4;
|
||||
else if(blocksize <= 2304)
|
||||
rice_optimization_level = 4;
|
||||
else if(blocksize <= 4608)
|
||||
rice_optimization_level = 4;
|
||||
else
|
||||
rice_optimization_level = 5;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if(format_is_wave < 0) {
|
||||
if(strstr(argv[i+1], ".wav") == argv[i+1] + (strlen(argv[i+1]) - strlen(".wav")))
|
||||
format_is_wave = true;
|
||||
else
|
||||
format_is_wave = false;
|
||||
}
|
||||
if(!format_is_wave) {
|
||||
if(format_is_big_endian < 0)
|
||||
return usage("ERROR: for decoding to a raw file you must specify -fb or -fl\n");
|
||||
}
|
||||
}
|
||||
|
||||
assert(blocksize >= 0 || mode_decode);
|
||||
|
||||
if(format_channels >= 0) {
|
||||
if(format_channels == 0 || (unsigned)format_channels > FLAC__MAX_CHANNELS)
|
||||
return usage("ERROR: invalid number of channels '%u', must be > 0 and <= %u\n", format_channels, FLAC__MAX_CHANNELS);
|
||||
}
|
||||
if(format_bps >= 0) {
|
||||
if(format_bps != 8 && format_bps != 16)
|
||||
return usage("ERROR: invalid bits per sample '%u' (must be 8 or 16)\n", format_bps);
|
||||
}
|
||||
if(format_sample_rate >= 0) {
|
||||
if(format_sample_rate == 0 || (unsigned)format_sample_rate > FLAC__MAX_SAMPLE_RATE)
|
||||
return usage("ERROR: invalid sample rate '%u', must be > 0 and <= %u\n", format_sample_rate, FLAC__MAX_SAMPLE_RATE);
|
||||
}
|
||||
if(!mode_decode && ((unsigned)blocksize < FLAC__MIN_BLOCK_SIZE || (unsigned)blocksize > FLAC__MAX_BLOCK_SIZE)) {
|
||||
return usage("ERROR: invalid blocksize '%u', must be >= %u and <= %u\n", (unsigned)blocksize, FLAC__MIN_BLOCK_SIZE, FLAC__MAX_BLOCK_SIZE);
|
||||
}
|
||||
if(qlp_coeff_precision > 0 && qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION) {
|
||||
return usage("ERROR: invalid value for -q '%u', must be 0 or >= %u\n", qlp_coeff_precision, FLAC__MIN_QLP_COEFF_PRECISION);
|
||||
}
|
||||
|
||||
/* turn off verbosity if the output stream is going to stdout */
|
||||
if(0 == strcmp(argv[i+1], "-"))
|
||||
verbose = false;
|
||||
|
||||
if(verbose) {
|
||||
printf("\n");
|
||||
printf("flac v%u.%u, Copyright (C) 2000 Josh Coalson\n", FLAC__MAJOR_VERSION, FLAC__MINOR_VERSION);
|
||||
printf("flac comes with ABSOLUTELY NO WARRANTY. This is free software, and you are\n");
|
||||
printf("welcome to redistribute it under certain conditions. Type `flac' for details.\n\n");
|
||||
|
||||
if(!mode_decode) {
|
||||
printf("options:%s -b %u%s -l %u%s%s -q %u -r %u\n",
|
||||
lax?" --lax":"", (unsigned)blocksize, do_mid_side?" -m":"", max_lpc_order,
|
||||
do_exhaustive_model_search?" -e":"", do_qlp_coeff_prec_search?" -p":"",
|
||||
qlp_coeff_precision, (unsigned)rice_optimization_level
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if(mode_decode)
|
||||
if(format_is_wave)
|
||||
return decode_wav(argv[i], argv[i+1], verbose, skip);
|
||||
else
|
||||
return decode_raw(argv[i], argv[i+1], verbose, skip, format_is_big_endian, format_is_unsigned_samples);
|
||||
else
|
||||
if(format_is_wave)
|
||||
return encode_wav(argv[i], argv[i+1], verbose, skip, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision);
|
||||
else
|
||||
return encode_raw(argv[i], argv[i+1], verbose, skip, lax, do_mid_side, do_exhaustive_model_search, do_qlp_coeff_prec_search, rice_optimization_level, max_lpc_order, (unsigned)blocksize, qlp_coeff_precision, format_is_big_endian, format_is_unsigned_samples, format_channels, format_bps, format_sample_rate);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int usage(const char *message, ...)
|
||||
{
|
||||
va_list args;
|
||||
|
||||
if(message) {
|
||||
fprintf(stderr, message);
|
||||
fprintf(stderr, "\n");
|
||||
va_start(args, message);
|
||||
|
||||
(void) vfprintf(stderr, message, args);
|
||||
|
||||
va_end(args);
|
||||
|
||||
}
|
||||
printf("==============================================================================\n");
|
||||
printf("flac - Command-line FLAC encoder/decoder version %u.%u\n", FLAC__MAJOR_VERSION, FLAC__MINOR_VERSION);
|
||||
printf("Copyright (C) 2000 Josh Coalson\n");
|
||||
printf("\n");
|
||||
printf("This program is free software; you can redistribute it and/or\n");
|
||||
printf("modify it under the terms of the GNU General Public License\n");
|
||||
printf("as published by the Free Software Foundation; either version 2\n");
|
||||
printf("of the License, or (at your option) any later version.\n");
|
||||
printf("\n");
|
||||
printf("This program is distributed in the hope that it will be useful,\n");
|
||||
printf("but WITHOUT ANY WARRANTY; without even the implied warranty of\n");
|
||||
printf("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n");
|
||||
printf("GNU General Public License for more details.\n");
|
||||
printf("\n");
|
||||
printf("You should have received a copy of the GNU General Public License\n");
|
||||
printf("along with this program; if not, write to the Free Software\n");
|
||||
printf("Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\n");
|
||||
printf("==============================================================================\n");
|
||||
printf("Usage:\n");
|
||||
printf(" flac [options] infile outfile\n");
|
||||
printf("\n");
|
||||
printf("For encoding:\n");
|
||||
printf(" infile may be a PCM RIFF WAVE file or raw samples\n");
|
||||
printf(" outfile will be in FLAC format\n");
|
||||
printf("For decoding, the reverse will be true\n");
|
||||
printf("\n");
|
||||
printf("infile may be - for stdin, outfile may be - for stdout\n");
|
||||
printf("\n");
|
||||
printf("If the unencoded filename ends with '.wav' or -fw is used, it's assumed to be\n");
|
||||
printf("RIFF WAVE. Otherwise, it's assumed to be raw samples and you have to specify\n");
|
||||
printf("all the format options. You can force a .wav file to be treated as a raw file\n");
|
||||
printf("using -fr.\n");
|
||||
printf("\n");
|
||||
printf("generic options:\n");
|
||||
printf(" -d : decode (default behavior is encode)\n");
|
||||
printf(" -s : silent (do not write runtime encode/decode statistics to stdout)\n");
|
||||
printf(" --skip samples : can be used both for encoding and decoding\n");
|
||||
printf("encoding options:\n");
|
||||
printf(" --lax : allow encoder to generate non-Subset files\n");
|
||||
printf(" -b blocksize : default is 1152 for -l 0, else 4608; should be 192/576/1152/2304/4608 (unless --lax is used)\n");
|
||||
printf(" -m : try mid-side coding for each frame (stereo input only)\n");
|
||||
printf(" -0 .. -9 : fastest compression .. highest compression, default is -6\n");
|
||||
printf(" these are synonyms for other options:\n");
|
||||
printf(" -0 : synonymous with -l 0\n");
|
||||
printf(" -1 : synonymous with -l 0 -m\n");
|
||||
printf(" -2 : synonymous with -l 0 -m -r # (# is automatically determined by the block size)\n");
|
||||
printf(" -3 : reserved\n");
|
||||
printf(" -4 : synonymous with -l 8\n");
|
||||
printf(" -5 : synonymous with -l 8 -m\n");
|
||||
printf(" -6 : synonymous with -l 8 -m -r # (# is automatically determined by the block size)\n");
|
||||
printf(" -7 : reserved\n");
|
||||
printf(" -8 : synonymous with -l 32 -m -r # (# is automatically determined by the block size)\n");
|
||||
printf(" -9 : synonymous with -l 32 -m -e -r 99 -p (very slow!)\n");
|
||||
printf(" -e : do exhaustive model search (expensive!)\n");
|
||||
printf(" -l max_lpc_order : 0 => use only fixed predictors\n");
|
||||
printf(" -p : do exhaustive search of LP coefficient quantization (expensive!); overrides -q\n");
|
||||
printf(" -q bits : precision of the quantized linear-predictor coefficients, 0 => let encoder decide (min is %u, default is -q 0)\n", FLAC__MIN_QLP_COEFF_PRECISION);
|
||||
printf(" -r level : rice parameter optimization level (level is 0..99, 0 => none, default is -r 0, above 4 doesn't usually help much)\n");
|
||||
printf(" -m-, -e-, -p-, --lax- can all be used to turn off a particular option\n");
|
||||
printf("format options:\n");
|
||||
printf(" -fb | -fl : big-endian | little-endian byte order\n");
|
||||
printf(" -fc channels\n");
|
||||
printf(" -fp bits_per_sample\n");
|
||||
printf(" -fs sample_rate : in Hz\n");
|
||||
printf(" -fu : unsigned samples (default is signed)\n");
|
||||
printf(" -fr : force to raw format (even if filename ends in .wav)\n");
|
||||
printf(" -fw : force to RIFF WAVE\n");
|
||||
return 1;
|
||||
}
|
22
src/libFLAC/Makefile
Normal file
22
src/libFLAC/Makefile
Normal file
@ -0,0 +1,22 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
LIB_NAME = libFLAC
|
||||
INCLUDES = -I./include -I../../include
|
||||
DEBUG_CFLAGS = -DFLAC_OVERFLOW_DETECT
|
||||
|
||||
OBJS = \
|
||||
bitbuffer.o \
|
||||
crc.o \
|
||||
encoder.o \
|
||||
encoder_framing.o \
|
||||
file_decoder.o \
|
||||
fixed.o \
|
||||
format.o \
|
||||
lpc.o \
|
||||
stream_decoder.o
|
||||
|
||||
include ../../build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
31
src/libFLAC/Makefile.vc
Normal file
31
src/libFLAC/Makefile.vc
Normal file
@ -0,0 +1,31 @@
|
||||
!include <win32.mak>
|
||||
|
||||
!IFDEF DEBUG
|
||||
.c.obj:
|
||||
$(cc) /D FLAC_OVERFLOW_DETECT /GX $(cdebug) $(cflags) /I "..\..\include" /I ".\include" -DSTRICT -YX /Od /D "_DEBUG" $<
|
||||
!else
|
||||
.c.obj:
|
||||
$(cc) $(cdebug) $(cflags) /O2 /I "..\..\include" /I ".\include" -DSTRICT -YX -DNODEBUG $<
|
||||
!endif
|
||||
|
||||
C_FILES= \
|
||||
bitbuffer.c \
|
||||
crc.c \
|
||||
encoder.c \
|
||||
encoder_framing.c \
|
||||
file_decoder.c \
|
||||
fixed.c \
|
||||
format.c \
|
||||
lpc.c \
|
||||
stream_decoder.c
|
||||
|
||||
OBJS= $(C_FILES:.c=.obj)
|
||||
|
||||
all: libFLAC.lib
|
||||
|
||||
libFLAC.lib: $(OBJS)
|
||||
link.exe -lib -out:../../obj/lib/$*.lib $(OBJS)
|
||||
|
||||
clean:
|
||||
-del *.obj *.pch
|
||||
-del ..\..\obj\lib\libFLAC.lib ..\..\obj\lib\libFLAC.pdb
|
962
src/libFLAC/bitbuffer.c
Normal file
962
src/libFLAC/bitbuffer.c
Normal file
@ -0,0 +1,962 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcpy(), memset() */
|
||||
#include "private/bitbuffer.h"
|
||||
|
||||
static const unsigned FLAC__BITBUFFER_DEFAULT_CAPACITY = 65536; /* bytes */
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x,y) ((x)<(y)?(x):(y))
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
static bool bitbuffer_resize_(FLAC__BitBuffer *bb, unsigned new_capacity)
|
||||
{
|
||||
byte *new_buffer;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
if(bb->capacity == new_capacity)
|
||||
return true;
|
||||
|
||||
new_buffer = (byte*)malloc(sizeof(byte) * new_capacity);
|
||||
if(new_buffer == 0)
|
||||
return false;
|
||||
memset(new_buffer, 0, new_capacity);
|
||||
memcpy(new_buffer, bb->buffer, sizeof(byte)*min(bb->bytes+(bb->bits?1:0), new_capacity));
|
||||
if(new_capacity < bb->bytes+(bb->bits?1:0)) {
|
||||
bb->bytes = new_capacity;
|
||||
bb->bits = 0;
|
||||
bb->total_bits = (new_capacity<<3);
|
||||
}
|
||||
if(new_capacity < bb->consumed_bytes+(bb->consumed_bits?1:0)) {
|
||||
bb->consumed_bytes = new_capacity;
|
||||
bb->consumed_bits = 0;
|
||||
bb->total_consumed_bits = (new_capacity<<3);
|
||||
}
|
||||
bb->buffer = new_buffer;
|
||||
bb->capacity = new_capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bitbuffer_grow_(FLAC__BitBuffer *bb, unsigned min_bytes_to_add)
|
||||
{
|
||||
unsigned new_capacity;
|
||||
|
||||
assert(min_bytes_to_add > 0);
|
||||
|
||||
new_capacity = max(bb->capacity * 4, bb->capacity + min_bytes_to_add);
|
||||
return bitbuffer_resize_(bb, new_capacity);
|
||||
}
|
||||
|
||||
static bool bitbuffer_ensure_size_(FLAC__BitBuffer *bb, unsigned bits_to_add)
|
||||
{
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
if((bb->capacity<<3) < bb->total_bits + bits_to_add)
|
||||
return bitbuffer_grow_(bb, (bits_to_add>>3)+2);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool bitbuffer_read_from_client_(FLAC__BitBuffer *bb, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
unsigned bytes;
|
||||
|
||||
/* first shift the unconsumed buffer data toward the front as much as possible */
|
||||
if(bb->total_consumed_bits >= 8) {
|
||||
unsigned l = 0, r = bb->consumed_bytes, r_end = bb->bytes;
|
||||
for( ; r < r_end; l++, r++)
|
||||
bb->buffer[l] = bb->buffer[r];
|
||||
for( ; l < r_end; l++)
|
||||
bb->buffer[l] = 0;
|
||||
bb->bytes -= bb->consumed_bytes;
|
||||
bb->total_bits -= (bb->consumed_bytes<<3);
|
||||
bb->consumed_bytes = 0;
|
||||
bb->total_consumed_bits = bb->consumed_bits;
|
||||
}
|
||||
/* grow if we need to */
|
||||
if(bb->capacity <= 1) {
|
||||
if(!bitbuffer_resize_(bb, 16))
|
||||
return false;
|
||||
}
|
||||
/* finally, read in some data; if OK, go back to read_bit_, else fail */
|
||||
bytes = bb->capacity - bb->bytes;
|
||||
if(!read_callback(bb->buffer+bb->bytes, &bytes, client_data))
|
||||
return false;
|
||||
bb->bytes += bytes;
|
||||
bb->total_bits += (bytes<<3);
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitbuffer_init(FLAC__BitBuffer *bb)
|
||||
{
|
||||
assert(bb != 0);
|
||||
bb->buffer = 0;
|
||||
bb->capacity = 0;
|
||||
bb->bytes = bb->bits = bb->total_bits = 0;
|
||||
bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const byte buffer[], unsigned bytes)
|
||||
{
|
||||
assert(bb != 0);
|
||||
FLAC__bitbuffer_init(bb);
|
||||
if(bytes == 0)
|
||||
return true;
|
||||
else {
|
||||
assert(buffer != 0);
|
||||
bb->buffer = (byte*)malloc(sizeof(byte)*bytes);
|
||||
if(bb->buffer == 0)
|
||||
return false;
|
||||
memcpy(bb->buffer, buffer, sizeof(byte)*bytes);
|
||||
bb->capacity = bb->bytes = bytes;
|
||||
bb->bits = 0;
|
||||
bb->total_bits = (bytes<<3);
|
||||
bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src)
|
||||
{
|
||||
static byte mask_[9] = { 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff };
|
||||
unsigned bits_to_add = src->total_bits - src->total_consumed_bits;
|
||||
assert(dest != 0);
|
||||
assert(src != 0);
|
||||
|
||||
if(bits_to_add == 0)
|
||||
return true;
|
||||
if(dest->bits != src->consumed_bits)
|
||||
return false;
|
||||
if(!bitbuffer_ensure_size_(dest, bits_to_add))
|
||||
return false;
|
||||
if(dest->bits == 0) {
|
||||
memcpy(dest->buffer+dest->bytes, src->buffer+src->consumed_bytes, src->bytes-src->consumed_bytes + ((src->bits)? 1:0));
|
||||
}
|
||||
else if(dest->bits + bits_to_add > 8) {
|
||||
dest->buffer[dest->bytes] <<= (8 - dest->bits);
|
||||
dest->buffer[dest->bytes] |= (src->buffer[src->consumed_bytes] & mask_[8-dest->bits]);
|
||||
memcpy(dest->buffer+dest->bytes+1, src->buffer+src->consumed_bytes+1, src->bytes-src->consumed_bytes-1 + ((src->bits)? 1:0));
|
||||
}
|
||||
else {
|
||||
dest->buffer[dest->bytes] <<= bits_to_add;
|
||||
dest->buffer[dest->bytes] |= (src->buffer[src->consumed_bytes] & mask_[bits_to_add]);
|
||||
}
|
||||
dest->bits = src->bits;
|
||||
dest->total_bits += bits_to_add;
|
||||
dest->bytes = dest->total_bits / 8;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitbuffer_free(FLAC__BitBuffer *bb)
|
||||
{
|
||||
assert(bb != 0);
|
||||
if(bb->buffer != 0)
|
||||
free(bb->buffer);
|
||||
bb->buffer = 0;
|
||||
bb->capacity = 0;
|
||||
bb->bytes = bb->bits = bb->total_bits = 0;
|
||||
bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb)
|
||||
{
|
||||
if(bb->buffer == 0) {
|
||||
bb->capacity = FLAC__BITBUFFER_DEFAULT_CAPACITY;
|
||||
bb->buffer = (byte*)malloc(sizeof(byte) * bb->capacity);
|
||||
if(bb->buffer == 0)
|
||||
return false;
|
||||
memset(bb->buffer, 0, bb->capacity);
|
||||
}
|
||||
else {
|
||||
memset(bb->buffer, 0, bb->bytes + (bb->bits?1:0));
|
||||
}
|
||||
bb->bytes = bb->bits = bb->total_bits = 0;
|
||||
bb->consumed_bytes = bb->consumed_bits = bb->total_consumed_bits = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src)
|
||||
{
|
||||
if(dest->capacity < src->capacity)
|
||||
if(!bitbuffer_resize_(dest, src->capacity))
|
||||
return false;
|
||||
memcpy(dest->buffer, src->buffer, sizeof(byte)*min(src->capacity, src->bytes+1));
|
||||
dest->bytes = src->bytes;
|
||||
dest->bits = src->bits;
|
||||
dest->total_bits = src->total_bits;
|
||||
dest->consumed_bytes = src->consumed_bytes;
|
||||
dest->consumed_bits = src->consumed_bits;
|
||||
dest->total_consumed_bits = src->total_consumed_bits;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits)
|
||||
{
|
||||
unsigned n, k;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
if(bits == 0)
|
||||
return true;
|
||||
if(!bitbuffer_ensure_size_(bb, bits))
|
||||
return false;
|
||||
bb->total_bits += bits;
|
||||
while(bits > 0) {
|
||||
n = min(8 - bb->bits, bits);
|
||||
k = bits - n;
|
||||
bb->buffer[bb->bytes] <<= n;
|
||||
bits -= n;
|
||||
bb->bits += n;
|
||||
if(bb->bits == 8) {
|
||||
bb->bytes++;
|
||||
bb->bits = 0;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, uint32 val, unsigned bits)
|
||||
{
|
||||
static uint32 mask[] = {
|
||||
0,
|
||||
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
|
||||
};
|
||||
unsigned n, k;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(bits <= 32);
|
||||
if(bits == 0)
|
||||
return true;
|
||||
if(!bitbuffer_ensure_size_(bb, bits))
|
||||
return false;
|
||||
val &= mask[bits];
|
||||
bb->total_bits += bits;
|
||||
while(bits > 0) {
|
||||
n = 8 - bb->bits;
|
||||
if(n == 8) { /* i.e. bb->bits == 0 */
|
||||
if(bits < 8) {
|
||||
bb->buffer[bb->bytes] = val;
|
||||
bb->bits = bits;
|
||||
break;
|
||||
}
|
||||
else if(bits == 8) {
|
||||
bb->buffer[bb->bytes++] = val;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
k = bits - 8;
|
||||
bb->buffer[bb->bytes++] = val >> k;
|
||||
val &= (~(0xffffffff << k));
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
else if(bits <= n) {
|
||||
bb->buffer[bb->bytes] <<= bits;
|
||||
bb->buffer[bb->bytes] |= val;
|
||||
if(bits == n) {
|
||||
bb->bytes++;
|
||||
bb->bits = 0;
|
||||
}
|
||||
else
|
||||
bb->bits += bits;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
k = bits - n;
|
||||
bb->buffer[bb->bytes] <<= n;
|
||||
bb->buffer[bb->bytes] |= (val>>k);
|
||||
val &= (~(0xffffffff << k));
|
||||
bits -= n;
|
||||
bb->bytes++;
|
||||
bb->bits = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, int32 val, unsigned bits)
|
||||
{
|
||||
return FLAC__bitbuffer_write_raw_uint32(bb, (uint32)val, bits);
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, uint64 val, unsigned bits)
|
||||
{
|
||||
static uint64 mask[] = {
|
||||
0,
|
||||
0x0000000000000001, 0x0000000000000003, 0x0000000000000007, 0x000000000000000F,
|
||||
0x000000000000001F, 0x000000000000003F, 0x000000000000007F, 0x00000000000000FF,
|
||||
0x00000000000001FF, 0x00000000000003FF, 0x00000000000007FF, 0x0000000000000FFF,
|
||||
0x0000000000001FFF, 0x0000000000003FFF, 0x0000000000007FFF, 0x000000000000FFFF,
|
||||
0x000000000001FFFF, 0x000000000003FFFF, 0x000000000007FFFF, 0x00000000000FFFFF,
|
||||
0x00000000001FFFFF, 0x00000000003FFFFF, 0x00000000007FFFFF, 0x0000000000FFFFFF,
|
||||
0x0000000001FFFFFF, 0x0000000003FFFFFF, 0x0000000007FFFFFF, 0x000000000FFFFFFF,
|
||||
0x000000001FFFFFFF, 0x000000003FFFFFFF, 0x000000007FFFFFFF, 0x00000000FFFFFFFF,
|
||||
0x00000001FFFFFFFF, 0x00000003FFFFFFFF, 0x00000007FFFFFFFF, 0x0000000FFFFFFFFF,
|
||||
0x0000001FFFFFFFFF, 0x0000003FFFFFFFFF, 0x0000007FFFFFFFFF, 0x000000FFFFFFFFFF,
|
||||
0x000001FFFFFFFFFF, 0x000003FFFFFFFFFF, 0x000007FFFFFFFFFF, 0x00000FFFFFFFFFFF,
|
||||
0x00001FFFFFFFFFFF, 0x00003FFFFFFFFFFF, 0x00007FFFFFFFFFFF, 0x0000FFFFFFFFFFFF,
|
||||
0x0001FFFFFFFFFFFF, 0x0003FFFFFFFFFFFF, 0x0007FFFFFFFFFFFF, 0x000FFFFFFFFFFFFF,
|
||||
0x001FFFFFFFFFFFFF, 0x003FFFFFFFFFFFFF, 0x007FFFFFFFFFFFFF, 0x00FFFFFFFFFFFFFF,
|
||||
0x01FFFFFFFFFFFFFF, 0x03FFFFFFFFFFFFFF, 0x07FFFFFFFFFFFFFF, 0x0FFFFFFFFFFFFFFF,
|
||||
0x1FFFFFFFFFFFFFFF, 0x3FFFFFFFFFFFFFFF, 0x7FFFFFFFFFFFFFFF, 0xFFFFFFFFFFFFFFFF
|
||||
};
|
||||
unsigned n, k;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(bits <= 64);
|
||||
if(bits == 0)
|
||||
return true;
|
||||
if(!bitbuffer_ensure_size_(bb, bits))
|
||||
return false;
|
||||
val &= mask[bits];
|
||||
bb->total_bits += bits;
|
||||
while(bits > 0) {
|
||||
if(bb->bits == 0) {
|
||||
if(bits < 8) {
|
||||
bb->buffer[bb->bytes] = val;
|
||||
bb->bits = bits;
|
||||
break;
|
||||
}
|
||||
else if(bits == 8) {
|
||||
bb->buffer[bb->bytes++] = val;
|
||||
break;
|
||||
}
|
||||
else {
|
||||
k = bits - 8;
|
||||
bb->buffer[bb->bytes++] = val >> k;
|
||||
val &= (~(0xffffffffffffffff << k));
|
||||
bits -= 8;
|
||||
}
|
||||
}
|
||||
else {
|
||||
n = min(8 - bb->bits, bits);
|
||||
k = bits - n;
|
||||
bb->buffer[bb->bytes] <<= n;
|
||||
bb->buffer[bb->bytes] |= (val>>k);
|
||||
val &= (~(0xffffffffffffffff << k));
|
||||
bits -= n;
|
||||
bb->bits += n;
|
||||
if(bb->bits == 8) {
|
||||
bb->bytes++;
|
||||
bb->bits = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, int64 val, unsigned bits)
|
||||
{
|
||||
return FLAC__bitbuffer_write_raw_uint64(bb, (uint64)val, bits);
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter)
|
||||
{
|
||||
unsigned bits, msbs;
|
||||
uint32 pattern;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
/* init pattern with sign bit */
|
||||
if(val < 0) {
|
||||
pattern = 1;
|
||||
val = -val;
|
||||
}
|
||||
else
|
||||
pattern = 0;
|
||||
|
||||
msbs = val >> parameter;
|
||||
bits = 2 + parameter + msbs;
|
||||
|
||||
if(bits <= 32) {
|
||||
pattern = (pattern << parameter) | (val & ((1<<parameter)-1));
|
||||
pattern = (pattern << (msbs+1)) | 1;
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, bits))
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
/* write the sign bit */
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, 1))
|
||||
return false;
|
||||
/* write the binary LSBs */
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, val & ((1<<parameter)-1), parameter))
|
||||
return false;
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitbuffer_write_zeroes(bb, msbs))
|
||||
return false;
|
||||
/* write the end bit */
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, 1, 1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, bool *overflow)
|
||||
{
|
||||
unsigned bits, msbs;
|
||||
uint32 pattern;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
*overflow = false;
|
||||
|
||||
/* init pattern with sign bit */
|
||||
if(val < 0) {
|
||||
pattern = 1;
|
||||
val = -val;
|
||||
}
|
||||
else
|
||||
pattern = 0;
|
||||
|
||||
msbs = val >> parameter;
|
||||
bits = 2 + parameter + msbs;
|
||||
|
||||
if(bits <= 32) {
|
||||
pattern = (pattern << parameter) | (val & ((1<<parameter)-1));
|
||||
pattern = (pattern << (msbs+1)) | 1;
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, bits))
|
||||
return false;
|
||||
}
|
||||
else if(bits > max_bits) {
|
||||
*overflow = true;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
/* write the sign bit */
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, pattern, 1))
|
||||
return false;
|
||||
/* write the binary LSBs */
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, val & ((1<<parameter)-1), parameter))
|
||||
return false;
|
||||
/* write the unary MSBs */
|
||||
if(!FLAC__bitbuffer_write_zeroes(bb, msbs))
|
||||
return false;
|
||||
/* write the end bit */
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, 1, 1))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, uint32 val)
|
||||
{
|
||||
bool ok = 1;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(!(val & 0x80000000)); /* this version only handles 31 bits */
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitbuffer_write_raw_uint32(bb, val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (val>>6), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (val>>12), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (val>>18), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (val>>24), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (val>>30), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | ((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (val&0x3F), 8);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, uint64 val)
|
||||
{
|
||||
bool ok = 1;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(!(val & 0xFFFFFFF000000000)); /* this version only handles 36 bits */
|
||||
|
||||
if(val < 0x80) {
|
||||
return FLAC__bitbuffer_write_raw_uint32(bb, (uint32)val, 8);
|
||||
}
|
||||
else if(val < 0x800) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xC0 | (uint32)(val>>6), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x10000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xE0 | (uint32)(val>>12), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x200000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF0 | (uint32)(val>>18), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x4000000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xF8 | (uint32)(val>>24), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)(val&0x3F), 8);
|
||||
}
|
||||
else if(val < 0x80000000) {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFC | (uint32)(val>>30), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)(val&0x3F), 8);
|
||||
}
|
||||
else {
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0xFE, 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>30)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>24)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>18)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>12)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)((val>>6)&0x3F), 8);
|
||||
ok &= FLAC__bitbuffer_write_raw_uint32(bb, 0x80 | (uint32)(val&0x3F), 8);
|
||||
}
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb)
|
||||
{
|
||||
/* 0-pad to byte boundary */
|
||||
if(bb->bits != 0)
|
||||
return FLAC__bitbuffer_write_zeroes(bb, 8 - bb->bits);
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
static byte mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||
|
||||
/* to avoid a drastic speed penalty we don't:
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
assert(bb->bits == 0);
|
||||
*/
|
||||
|
||||
read_bit_:
|
||||
if(bb->total_consumed_bits < bb->total_bits) {
|
||||
*val = (bb->buffer[bb->consumed_bytes] & mask[bb->consumed_bits])? 1 : 0;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
|
||||
return false;
|
||||
goto read_bit_;
|
||||
}
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
static byte mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||
|
||||
/* to avoid a drastic speed penalty we don't:
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
assert(bb->bits == 0);
|
||||
*/
|
||||
|
||||
read_bit_:
|
||||
if(bb->total_consumed_bits < bb->total_bits) {
|
||||
*val = (bb->buffer[bb->consumed_bytes] & mask[bb->consumed_bits])? 1 : 0;
|
||||
bb->consumed_bits++;
|
||||
if(bb->consumed_bits == 8) {
|
||||
bb->consumed_bytes++;
|
||||
bb->consumed_bits = 0;
|
||||
}
|
||||
bb->total_consumed_bits++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
|
||||
return false;
|
||||
goto read_bit_;
|
||||
}
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, uint32 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
static byte mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||
|
||||
/* to avoid a drastic speed penalty we don't:
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
assert(bb->bits == 0);
|
||||
*/
|
||||
|
||||
read_bit_:
|
||||
if(bb->total_consumed_bits < bb->total_bits) {
|
||||
*val <<= 1;
|
||||
*val |= (bb->buffer[bb->consumed_bytes] & mask[bb->consumed_bits])? 1 : 0;
|
||||
bb->consumed_bits++;
|
||||
if(bb->consumed_bits == 8) {
|
||||
bb->consumed_bytes++;
|
||||
bb->consumed_bits = 0;
|
||||
}
|
||||
bb->total_consumed_bits++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
|
||||
return false;
|
||||
goto read_bit_;
|
||||
}
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, uint64 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
static byte mask[] = { 128, 64, 32, 16, 8, 4, 2, 1 };
|
||||
|
||||
/* to avoid a drastic speed penalty we don't:
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
assert(bb->bits == 0);
|
||||
*/
|
||||
|
||||
read_bit_:
|
||||
if(bb->total_consumed_bits < bb->total_bits) {
|
||||
*val <<= 1;
|
||||
*val |= (bb->buffer[bb->consumed_bytes] & mask[bb->consumed_bits])? 1 : 0;
|
||||
bb->consumed_bits++;
|
||||
if(bb->consumed_bits == 8) {
|
||||
bb->consumed_bytes++;
|
||||
bb->consumed_bits = 0;
|
||||
}
|
||||
bb->total_consumed_bits++;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if(!bitbuffer_read_from_client_(bb, read_callback, client_data))
|
||||
return false;
|
||||
goto read_bit_;
|
||||
}
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, uint32 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(bits <= 32);
|
||||
|
||||
*val = 0;
|
||||
for(i = 0; i < bits; i++) {
|
||||
if(!FLAC__bitbuffer_read_bit_to_uint32(bb, val, read_callback, client_data))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, int32 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
unsigned i;
|
||||
uint32 x;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(bits <= 32);
|
||||
|
||||
x = 0;
|
||||
for(i = 0; i < bits; i++) {
|
||||
if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &x, read_callback, client_data))
|
||||
return false;
|
||||
}
|
||||
/* fix the sign */
|
||||
i = 32 - bits;
|
||||
if(i) {
|
||||
x <<= i;
|
||||
*val = (int32)x;
|
||||
*val >>= i;
|
||||
}
|
||||
else
|
||||
*val = (int32)x;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, uint64 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(bits <= 64);
|
||||
|
||||
*val = 0;
|
||||
for(i = 0; i < bits; i++) {
|
||||
if(!FLAC__bitbuffer_read_bit_to_uint64(bb, val, read_callback, client_data))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, int64 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
unsigned i;
|
||||
uint64 x;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
assert(bits <= 64);
|
||||
|
||||
x = 0;
|
||||
for(i = 0; i < bits; i++) {
|
||||
if(!FLAC__bitbuffer_read_bit_to_uint64(bb, &x, read_callback, client_data))
|
||||
return false;
|
||||
}
|
||||
/* fix the sign */
|
||||
i = 64 - bits;
|
||||
if(i) {
|
||||
x <<= i;
|
||||
*val = (int64)x;
|
||||
*val >>= i;
|
||||
}
|
||||
else
|
||||
*val = (int64)x;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data)
|
||||
{
|
||||
uint32 sign = 0, lsbs, msbs = 0;
|
||||
unsigned bit;
|
||||
|
||||
assert(bb != 0);
|
||||
assert(bb->buffer != 0);
|
||||
|
||||
/* read the sign bit */
|
||||
if(!FLAC__bitbuffer_read_bit_to_uint32(bb, &sign, read_callback, client_data))
|
||||
return false;
|
||||
/* read the binary LSBs */
|
||||
if(!FLAC__bitbuffer_read_raw_uint32(bb, &lsbs, parameter, read_callback, client_data))
|
||||
return false;
|
||||
/* read the unary MSBs and end bit */
|
||||
while(1) {
|
||||
if(!FLAC__bitbuffer_read_bit(bb, &bit, read_callback, client_data))
|
||||
return false;
|
||||
if(bit)
|
||||
break;
|
||||
else
|
||||
msbs++;
|
||||
}
|
||||
/* compose the value */
|
||||
*val = (msbs << parameter) | lsbs;
|
||||
if(sign)
|
||||
*val = -(*val);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* on return, if *val == 0xffffffff then the utf-8 sequence was invalid, but the return value will be true */
|
||||
bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, uint32 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data, byte *raw, unsigned *rawlen)
|
||||
{
|
||||
uint32 v = 0;
|
||||
uint32 x;
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data))
|
||||
return false;
|
||||
if(raw)
|
||||
raw[(*rawlen)++] = (byte)x;
|
||||
if(!(x & 0x80)) { /* 0xxxxxxx */
|
||||
v = x;
|
||||
i = 0;
|
||||
}
|
||||
else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */
|
||||
v = x & 0x1F;
|
||||
i = 1;
|
||||
}
|
||||
else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */
|
||||
v = x & 0x0F;
|
||||
i = 2;
|
||||
}
|
||||
else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */
|
||||
v = x & 0x07;
|
||||
i = 3;
|
||||
}
|
||||
else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */
|
||||
v = x & 0x03;
|
||||
i = 4;
|
||||
}
|
||||
else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */
|
||||
v = x & 0x01;
|
||||
i = 5;
|
||||
}
|
||||
else
|
||||
goto invalid_;
|
||||
for( ; i; i--) {
|
||||
if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data))
|
||||
return false;
|
||||
if(raw)
|
||||
raw[(*rawlen)++] = (byte)x;
|
||||
if(!(x & 0x80) || (x & 0x40)) /* 10xxxxxx */
|
||||
goto invalid_;
|
||||
v <<= 6;
|
||||
v |= (x & 0x3F);
|
||||
}
|
||||
*val = v;
|
||||
return true;
|
||||
invalid_:
|
||||
*val = 0xffffffff;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* on return, if *val == 0xffffffffffffffff then the utf-8 sequence was invalid, but the return value will be true */
|
||||
bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, uint64 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data, byte *raw, unsigned *rawlen)
|
||||
{
|
||||
uint64 v = 0;
|
||||
uint32 x;
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data))
|
||||
return false;
|
||||
if(raw)
|
||||
raw[(*rawlen)++] = (byte)x;
|
||||
if(!(x & 0x80)) { /* 0xxxxxxx */
|
||||
v = x;
|
||||
i = 0;
|
||||
}
|
||||
else if(x & 0xC0 && !(x & 0x20)) { /* 110xxxxx */
|
||||
v = x & 0x1F;
|
||||
i = 1;
|
||||
}
|
||||
else if(x & 0xE0 && !(x & 0x10)) { /* 1110xxxx */
|
||||
v = x & 0x0F;
|
||||
i = 2;
|
||||
}
|
||||
else if(x & 0xF0 && !(x & 0x08)) { /* 11110xxx */
|
||||
v = x & 0x07;
|
||||
i = 3;
|
||||
}
|
||||
else if(x & 0xF8 && !(x & 0x04)) { /* 111110xx */
|
||||
v = x & 0x03;
|
||||
i = 4;
|
||||
}
|
||||
else if(x & 0xFC && !(x & 0x02)) { /* 1111110x */
|
||||
v = x & 0x01;
|
||||
i = 5;
|
||||
}
|
||||
else if(x & 0xFE && !(x & 0x01)) { /* 11111110 */
|
||||
v = 0;
|
||||
i = 6;
|
||||
}
|
||||
else
|
||||
goto invalid_;
|
||||
for( ; i; i--) {
|
||||
if(!FLAC__bitbuffer_read_raw_uint32(bb, &x, 8, read_callback, client_data))
|
||||
return false;
|
||||
if(raw)
|
||||
raw[(*rawlen)++] = (byte)x;
|
||||
if(!(x & 0x80) || (x & 0x40)) /* 10xxxxxx */
|
||||
goto invalid_;
|
||||
v <<= 6;
|
||||
v |= (x & 0x3F);
|
||||
}
|
||||
*val = v;
|
||||
return true;
|
||||
invalid_:
|
||||
*val = 0xffffffff;
|
||||
return true;
|
||||
}
|
||||
|
||||
void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out)
|
||||
{
|
||||
unsigned i, j;
|
||||
if(bb == 0) {
|
||||
fprintf(out, "bitbuffer is NULL\n");
|
||||
}
|
||||
else {
|
||||
fprintf(out, "bitbuffer: capacity=%u bytes=%u bits=%u total_bits=%u consumed: bytes=%u, bits=%u, total_bits=%u\n", bb->capacity, bb->bytes, bb->bits, bb->total_bits, bb->consumed_bytes, bb->consumed_bits, bb->total_consumed_bits);
|
||||
for(i = 0; i < bb->bytes; i++) {
|
||||
fprintf(out, "%08X: ", i);
|
||||
for(j = 0; j < 8; j++)
|
||||
if(i*8+j < bb->total_consumed_bits)
|
||||
fprintf(out, ".");
|
||||
else
|
||||
fprintf(out, "%01u", bb->buffer[i] & (1 << (8-j-1)) ? 1:0);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
if(bb->bits > 0) {
|
||||
fprintf(out, "%08X: ", i);
|
||||
for(j = 0; j < bb->bits; j++)
|
||||
if(i*8+j < bb->total_consumed_bits)
|
||||
fprintf(out, ".");
|
||||
else
|
||||
fprintf(out, "%01u", bb->buffer[i] & (1 << (bb->bits-j-1)) ? 1:0);
|
||||
fprintf(out, "\n");
|
||||
}
|
||||
}
|
||||
}
|
65
src/libFLAC/crc.c
Normal file
65
src/libFLAC/crc.c
Normal file
@ -0,0 +1,65 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "private/crc.h"
|
||||
|
||||
byte FLAC__crc8(const byte *data, const unsigned len)
|
||||
{
|
||||
static byte const 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
|
||||
};
|
||||
unsigned i;
|
||||
byte crc = 0;
|
||||
|
||||
for(i = 0; i < len; i++)
|
||||
crc = crc8_table_[crc ^ *data++];
|
||||
|
||||
return crc;
|
||||
}
|
900
src/libFLAC/encoder.c
Normal file
900
src/libFLAC/encoder.c
Normal file
@ -0,0 +1,900 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for memcpy() */
|
||||
#include "FLAC/encoder.h"
|
||||
#include "private/bitbuffer.h"
|
||||
#include "private/encoder_framing.h"
|
||||
#include "private/fixed.h"
|
||||
#include "private/lpc.h"
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#define min(x,y) ((x)<(y)?(x):(y))
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
#ifdef RICE_BITS
|
||||
#undef RICE_BITS
|
||||
#endif
|
||||
#define RICE_BITS(value, parameter) (2 + (parameter) + (((unsigned)((value) < 0? -(value) : (value))) >> (parameter)))
|
||||
|
||||
typedef struct FLAC__EncoderPrivate {
|
||||
unsigned input_capacity; /* current size (in samples) of the signal and residual buffers */
|
||||
int32 *integer_signal[FLAC__MAX_CHANNELS]; /* the integer version of the input signal */
|
||||
int32 *integer_signal_mid_side[2]; /* the integer version of the mid-side input signal (stereo only) */
|
||||
real *real_signal[FLAC__MAX_CHANNELS]; /* the floating-point version of the input signal */
|
||||
real *real_signal_mid_side[2]; /* the floating-point version of the mid-side input signal (stereo only) */
|
||||
int32 *residual[2]; /* where the candidate and best subframe residual signals will be stored */
|
||||
unsigned best_residual; /* index into the above */
|
||||
FLAC__BitBuffer frame; /* the current frame being worked on */
|
||||
FLAC__BitBuffer frame_mid_side; /* special parallel workspace for the mid-side coded version of the current frame */
|
||||
FLAC__BitBuffer frame_left_side; /* special parallel workspace for the left-side coded version of the current frame */
|
||||
FLAC__BitBuffer frame_right_side; /* special parallel workspace for the right-side coded version of the current frame */
|
||||
FLAC__SubframeHeader best_subframe, candidate_subframe;
|
||||
bool current_frame_can_do_mid_side; /* encoder sets this false when any given sample of a frame's side channel exceeds 16 bits */
|
||||
FLAC__StreamMetaData metadata;
|
||||
unsigned current_sample_number;
|
||||
unsigned current_frame_number;
|
||||
FLAC__EncoderWriteStatus (*write_callback)(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data);
|
||||
void (*metadata_callback)(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
void *client_data;
|
||||
} FLAC__EncoderPrivate;
|
||||
|
||||
static bool encoder_resize_buffers_(FLAC__Encoder *encoder, unsigned new_size);
|
||||
static bool encoder_process_frame_(FLAC__Encoder *encoder, bool is_last_frame);
|
||||
static bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame, const FLAC__FrameHeader *frame_header, unsigned channels, const int32 *integer_signal[], const real *real_signal[], FLAC__BitBuffer *bitbuffer);
|
||||
static unsigned encoder_evaluate_constant_subframe_(const int32 signal, unsigned bits_per_sample, FLAC__SubframeHeader *subframe);
|
||||
static unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], unsigned blocksize, unsigned bits_per_sample, unsigned order, unsigned rice_parameter, unsigned max_partition_order, FLAC__SubframeHeader *subframe);
|
||||
static unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[], const real lp_coeff[], unsigned blocksize, unsigned bits_per_sample, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned max_partition_order, FLAC__SubframeHeader *subframe);
|
||||
static unsigned encoder_evaluate_verbatim_subframe_(unsigned blocksize, unsigned bits_per_sample, FLAC__SubframeHeader *subframe);
|
||||
static unsigned encoder_find_best_partition_order_(int32 residual[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned max_partition_order, unsigned *best_partition_order, unsigned best_parameters[]);
|
||||
static bool encoder_generate_constant_subframe_(const FLAC__SubframeHeader *header, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer);
|
||||
static bool encoder_generate_fixed_subframe_(const FLAC__SubframeHeader *header, int32 residual[], unsigned blocksize, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer);
|
||||
static bool encoder_generate_lpc_subframe_(const FLAC__SubframeHeader *header, int32 residual[], unsigned blocksize, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer);
|
||||
static bool encoder_generate_verbatim_subframe_(const FLAC__SubframeHeader *header, const int32 signal[], unsigned blocksize, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer);
|
||||
static void encoder_promote_candidate_subframe_(FLAC__Encoder *encoder);
|
||||
static bool encoder_set_partitioned_rice_(const int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameter, const unsigned partition_order, unsigned parameters[], unsigned *bits);
|
||||
|
||||
|
||||
bool encoder_resize_buffers_(FLAC__Encoder *encoder, unsigned new_size)
|
||||
{
|
||||
bool ok;
|
||||
unsigned i;
|
||||
int32 *previous_is, *current_is;
|
||||
real *previous_rs, *current_rs;
|
||||
int32 *residual;
|
||||
|
||||
assert(new_size > 0);
|
||||
assert(encoder->state == FLAC__ENCODER_OK);
|
||||
assert(encoder->guts->current_sample_number == 0);
|
||||
|
||||
/* To avoid excessive malloc'ing, we only grow the buffer; no shrinking. */
|
||||
if(new_size <= encoder->guts->input_capacity)
|
||||
return true;
|
||||
|
||||
ok = 1;
|
||||
if(ok) {
|
||||
for(i = 0; ok && i < encoder->channels; i++) {
|
||||
/* integer version of the signal */
|
||||
previous_is = encoder->guts->integer_signal[i];
|
||||
current_is = (int32*)malloc(sizeof(int32) * new_size);
|
||||
if(0 == current_is) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
ok = 0;
|
||||
}
|
||||
else {
|
||||
encoder->guts->integer_signal[i] = current_is;
|
||||
if(previous_is != 0)
|
||||
free(previous_is);
|
||||
}
|
||||
/* real version of the signal */
|
||||
previous_rs = encoder->guts->real_signal[i];
|
||||
current_rs = (real*)malloc(sizeof(real) * new_size);
|
||||
if(0 == current_rs) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
ok = 0;
|
||||
}
|
||||
else {
|
||||
encoder->guts->real_signal[i] = current_rs;
|
||||
if(previous_rs != 0)
|
||||
free(previous_rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ok) {
|
||||
for(i = 0; ok && i < 2; i++) {
|
||||
/* integer version of the signal */
|
||||
previous_is = encoder->guts->integer_signal_mid_side[i];
|
||||
current_is = (int32*)malloc(sizeof(int32) * new_size);
|
||||
if(0 == current_is) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
ok = 0;
|
||||
}
|
||||
else {
|
||||
encoder->guts->integer_signal_mid_side[i] = current_is;
|
||||
if(previous_is != 0)
|
||||
free(previous_is);
|
||||
}
|
||||
/* real version of the signal */
|
||||
previous_rs = encoder->guts->real_signal_mid_side[i];
|
||||
current_rs = (real*)malloc(sizeof(real) * new_size);
|
||||
if(0 == current_rs) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
ok = 0;
|
||||
}
|
||||
else {
|
||||
encoder->guts->real_signal_mid_side[i] = current_rs;
|
||||
if(previous_rs != 0)
|
||||
free(previous_rs);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ok) {
|
||||
for(i = 0; i < 2; i++) {
|
||||
residual = (int32*)malloc(sizeof(int32) * new_size);
|
||||
if(0 == residual) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
ok = 0;
|
||||
}
|
||||
else {
|
||||
if(encoder->guts->residual[i] != 0)
|
||||
free(encoder->guts->residual[i]);
|
||||
encoder->guts->residual[i] = residual;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(ok)
|
||||
encoder->guts->input_capacity = new_size;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
FLAC__Encoder *FLAC__encoder_get_new_instance()
|
||||
{
|
||||
FLAC__Encoder *encoder = (FLAC__Encoder*)malloc(sizeof(FLAC__Encoder));
|
||||
if(encoder != 0) {
|
||||
encoder->state = FLAC__ENCODER_UNINITIALIZED;
|
||||
encoder->guts = 0;
|
||||
}
|
||||
return encoder;
|
||||
}
|
||||
|
||||
void FLAC__encoder_free_instance(FLAC__Encoder *encoder)
|
||||
{
|
||||
assert(encoder != 0);
|
||||
free(encoder);
|
||||
}
|
||||
|
||||
FLAC__EncoderState FLAC__encoder_init(FLAC__Encoder *encoder, FLAC__EncoderWriteStatus (*write_callback)(const FLAC__Encoder *encoder, const byte buffer[], unsigned bytes, unsigned samples, unsigned current_frame, void *client_data), void (*metadata_callback)(const FLAC__Encoder *encoder, const FLAC__StreamMetaData *metadata, void *client_data), void *client_data)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
assert(sizeof(int) >= 4); /* we want to die right away if this is not true */
|
||||
assert(encoder != 0);
|
||||
assert(write_callback != 0);
|
||||
assert(metadata_callback != 0);
|
||||
assert(encoder->state == FLAC__ENCODER_UNINITIALIZED);
|
||||
assert(encoder->guts == 0);
|
||||
|
||||
encoder->state = FLAC__ENCODER_OK;
|
||||
|
||||
if(encoder->channels == 0 || encoder->channels > FLAC__MAX_CHANNELS)
|
||||
return encoder->state = FLAC__ENCODER_INVALID_NUMBER_OF_CHANNELS;
|
||||
|
||||
if(encoder->do_mid_side_stereo && encoder->channels != 2)
|
||||
return encoder->state = FLAC__ENCODER_MID_SIDE_CHANNELS_MISMATCH;
|
||||
|
||||
if(encoder->do_mid_side_stereo && encoder->bits_per_sample > 16)
|
||||
return encoder->state = FLAC__ENCODER_MID_SIDE_SAMPLE_SIZE_MISMATCH;
|
||||
|
||||
if(encoder->bits_per_sample == 0 || encoder->bits_per_sample > FLAC__MAX_BITS_PER_SAMPLE)
|
||||
return encoder->state = FLAC__ENCODER_INVALID_BITS_PER_SAMPLE;
|
||||
|
||||
if(encoder->sample_rate == 0 || encoder->sample_rate > FLAC__MAX_SAMPLE_RATE)
|
||||
return encoder->state = FLAC__ENCODER_INVALID_SAMPLE_RATE;
|
||||
|
||||
if(encoder->blocksize < FLAC__MIN_BLOCK_SIZE || encoder->blocksize > FLAC__MAX_BLOCK_SIZE)
|
||||
return encoder->state = FLAC__ENCODER_INVALID_BLOCK_SIZE;
|
||||
|
||||
if(encoder->blocksize < encoder->max_lpc_order)
|
||||
return encoder->state = FLAC__ENCODER_BLOCK_SIZE_TOO_SMALL_FOR_LPC_ORDER;
|
||||
|
||||
if(encoder->qlp_coeff_precision == 0) {
|
||||
if(encoder->bits_per_sample < 16) {
|
||||
/* @@@ need some data about how to set this here w.r.t. blocksize and sample rate */
|
||||
/* @@@ until then we'll make a guess */
|
||||
encoder->qlp_coeff_precision = max(5, 2 + encoder->bits_per_sample / 2);
|
||||
}
|
||||
else if(encoder->bits_per_sample == 16) {
|
||||
if(encoder->blocksize <= 192)
|
||||
encoder->qlp_coeff_precision = 7;
|
||||
else if(encoder->blocksize <= 384)
|
||||
encoder->qlp_coeff_precision = 8;
|
||||
else if(encoder->blocksize <= 576)
|
||||
encoder->qlp_coeff_precision = 9;
|
||||
else if(encoder->blocksize <= 1152)
|
||||
encoder->qlp_coeff_precision = 10;
|
||||
else if(encoder->blocksize <= 2304)
|
||||
encoder->qlp_coeff_precision = 11;
|
||||
else if(encoder->blocksize <= 4608)
|
||||
encoder->qlp_coeff_precision = 12;
|
||||
else
|
||||
encoder->qlp_coeff_precision = 13;
|
||||
}
|
||||
else {
|
||||
encoder->qlp_coeff_precision = min(13, 8*sizeof(int32) - encoder->bits_per_sample - 1);
|
||||
}
|
||||
}
|
||||
else if(encoder->qlp_coeff_precision < FLAC__MIN_QLP_COEFF_PRECISION || encoder->qlp_coeff_precision + encoder->bits_per_sample >= 8*sizeof(uint32))
|
||||
return encoder->state = FLAC__ENCODER_INVALID_QLP_COEFF_PRECISION;
|
||||
|
||||
if(encoder->streamable_subset) {
|
||||
if(encoder->bits_per_sample != 8 && encoder->bits_per_sample != 12 && encoder->bits_per_sample != 16 && encoder->bits_per_sample != 20 && encoder->bits_per_sample != 24)
|
||||
return encoder->state = FLAC__ENCODER_NOT_STREAMABLE;
|
||||
if(encoder->sample_rate > 655350)
|
||||
return encoder->state = FLAC__ENCODER_NOT_STREAMABLE;
|
||||
}
|
||||
|
||||
if(encoder->rice_optimization_level >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
|
||||
encoder->rice_optimization_level = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN) - 1;
|
||||
|
||||
encoder->guts = (FLAC__EncoderPrivate*)malloc(sizeof(FLAC__EncoderPrivate));
|
||||
if(encoder->guts == 0)
|
||||
return encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
|
||||
encoder->guts->input_capacity = 0;
|
||||
for(i = 0; i < encoder->channels; i++) {
|
||||
encoder->guts->integer_signal[i] = 0;
|
||||
encoder->guts->real_signal[i] = 0;
|
||||
}
|
||||
for(i = 0; i < 2; i++) {
|
||||
encoder->guts->integer_signal_mid_side[i] = 0;
|
||||
encoder->guts->real_signal_mid_side[i] = 0;
|
||||
}
|
||||
encoder->guts->residual[0] = 0;
|
||||
encoder->guts->residual[1] = 0;
|
||||
encoder->guts->best_residual = 0;
|
||||
encoder->guts->current_frame_can_do_mid_side = true;
|
||||
encoder->guts->current_sample_number = 0;
|
||||
encoder->guts->current_frame_number = 0;
|
||||
|
||||
if(!encoder_resize_buffers_(encoder, encoder->blocksize)) {
|
||||
/* the above function sets the state for us in case of an error */
|
||||
return encoder->state;
|
||||
}
|
||||
FLAC__bitbuffer_init(&encoder->guts->frame);
|
||||
encoder->guts->write_callback = write_callback;
|
||||
encoder->guts->metadata_callback = metadata_callback;
|
||||
encoder->guts->client_data = client_data;
|
||||
|
||||
/*
|
||||
* write the stream header
|
||||
*/
|
||||
if(!FLAC__bitbuffer_clear(&encoder->guts->frame))
|
||||
return encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(&encoder->guts->frame, FLAC__STREAM_SYNC, FLAC__STREAM_SYNC_LEN))
|
||||
return encoder->state = FLAC__ENCODER_FRAMING_ERROR;
|
||||
|
||||
encoder->guts->metadata.type = FLAC__METADATA_TYPE_ENCODING;
|
||||
encoder->guts->metadata.is_last = true;
|
||||
encoder->guts->metadata.length = FLAC__STREAM_METADATA_ENCODING_LENGTH;
|
||||
encoder->guts->metadata.data.encoding.min_blocksize = encoder->blocksize; /* this encoder uses the same blocksize for the whole stream */
|
||||
encoder->guts->metadata.data.encoding.max_blocksize = encoder->blocksize;
|
||||
encoder->guts->metadata.data.encoding.min_framesize = 0; /* we don't know this yet; have to fill it in later */
|
||||
encoder->guts->metadata.data.encoding.max_framesize = 0; /* we don't know this yet; have to fill it in later */
|
||||
encoder->guts->metadata.data.encoding.sample_rate = encoder->sample_rate;
|
||||
encoder->guts->metadata.data.encoding.channels = encoder->channels;
|
||||
encoder->guts->metadata.data.encoding.bits_per_sample = encoder->bits_per_sample;
|
||||
encoder->guts->metadata.data.encoding.total_samples = 0; /* we don't know this yet; have to fill it in later */
|
||||
if(!FLAC__add_metadata_block(&encoder->guts->metadata, &encoder->guts->frame))
|
||||
return encoder->state = FLAC__ENCODER_FRAMING_ERROR;
|
||||
|
||||
assert(encoder->guts->frame.bits == 0); /* assert that we're byte-aligned before writing */
|
||||
assert(encoder->guts->frame.total_consumed_bits == 0); /* assert that no reading of the buffer was done */
|
||||
if(encoder->guts->write_callback(encoder, encoder->guts->frame.buffer, encoder->guts->frame.bytes, 0, encoder->guts->current_frame_number, encoder->guts->client_data) != FLAC__ENCODER_WRITE_OK)
|
||||
return encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING;
|
||||
|
||||
/* now that the metadata block is written, we can init this to an absurdly-high value */
|
||||
encoder->guts->metadata.data.encoding.min_framesize = (1u << FLAC__STREAM_METADATA_ENCODING_MIN_FRAME_SIZE_LEN) - 1;
|
||||
|
||||
return encoder->state;
|
||||
}
|
||||
|
||||
void FLAC__encoder_finish(FLAC__Encoder *encoder)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
assert(encoder != 0);
|
||||
if(encoder->state == FLAC__ENCODER_UNINITIALIZED)
|
||||
return;
|
||||
if(encoder->guts->current_sample_number != 0) {
|
||||
encoder->blocksize = encoder->guts->current_sample_number;
|
||||
encoder_process_frame_(encoder, true); /* true => is last frame */
|
||||
}
|
||||
encoder->guts->metadata_callback(encoder, &encoder->guts->metadata, encoder->guts->client_data);
|
||||
if(encoder->guts != 0) {
|
||||
for(i = 0; i < encoder->channels; i++) {
|
||||
if(encoder->guts->integer_signal[i] != 0) {
|
||||
free(encoder->guts->integer_signal[i]);
|
||||
encoder->guts->integer_signal[i] = 0;
|
||||
}
|
||||
if(encoder->guts->real_signal[i] != 0) {
|
||||
free(encoder->guts->real_signal[i]);
|
||||
encoder->guts->real_signal[i] = 0;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 2; i++) {
|
||||
if(encoder->guts->integer_signal_mid_side[i] != 0) {
|
||||
free(encoder->guts->integer_signal_mid_side[i]);
|
||||
encoder->guts->integer_signal_mid_side[i] = 0;
|
||||
}
|
||||
if(encoder->guts->real_signal_mid_side[i] != 0) {
|
||||
free(encoder->guts->real_signal_mid_side[i]);
|
||||
encoder->guts->real_signal_mid_side[i] = 0;
|
||||
}
|
||||
}
|
||||
for(i = 0; i < 2; i++) {
|
||||
if(encoder->guts->residual[i] != 0) {
|
||||
free(encoder->guts->residual[i]);
|
||||
encoder->guts->residual[i] = 0;
|
||||
}
|
||||
}
|
||||
FLAC__bitbuffer_free(&encoder->guts->frame);
|
||||
free(encoder->guts);
|
||||
encoder->guts = 0;
|
||||
}
|
||||
encoder->state = FLAC__ENCODER_UNINITIALIZED;
|
||||
}
|
||||
|
||||
bool FLAC__encoder_process(FLAC__Encoder *encoder, const int32 *buf[], unsigned samples)
|
||||
{
|
||||
unsigned i, j, channel;
|
||||
int32 x, mid, side;
|
||||
const bool ms = encoder->do_mid_side_stereo && encoder->channels == 2;
|
||||
const int32 min_side = -((int64)1 << (encoder->bits_per_sample-1));
|
||||
const int32 max_side = ((int64)1 << (encoder->bits_per_sample-1)) - 1;
|
||||
|
||||
assert(encoder != 0);
|
||||
assert(encoder->state == FLAC__ENCODER_OK);
|
||||
|
||||
j = 0;
|
||||
do {
|
||||
for(i = encoder->guts->current_sample_number; i < encoder->blocksize && j < samples; i++, j++) {
|
||||
for(channel = 0; channel < encoder->channels; channel++) {
|
||||
x = buf[channel][j];
|
||||
encoder->guts->integer_signal[channel][i] = x;
|
||||
encoder->guts->real_signal[channel][i] = (real)x;
|
||||
}
|
||||
if(ms && encoder->guts->current_frame_can_do_mid_side) {
|
||||
side = buf[0][j] - buf[1][j];
|
||||
if(side < min_side || side > max_side) {
|
||||
encoder->guts->current_frame_can_do_mid_side = false;
|
||||
}
|
||||
else {
|
||||
mid = (buf[0][j] + buf[1][j]) >> 1; /* NOTE: not the same as divide-by-two ! */
|
||||
encoder->guts->integer_signal_mid_side[0][i] = mid;
|
||||
encoder->guts->integer_signal_mid_side[1][i] = side;
|
||||
encoder->guts->real_signal_mid_side[0][i] = (real)mid;
|
||||
encoder->guts->real_signal_mid_side[1][i] = (real)side;
|
||||
}
|
||||
}
|
||||
encoder->guts->current_sample_number++;
|
||||
}
|
||||
if(i == encoder->blocksize) {
|
||||
if(!encoder_process_frame_(encoder, false)) /* false => not last frame */
|
||||
return false;
|
||||
}
|
||||
} while(j < samples);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/* 'samples' is channel-wide samples, e.g. for 1 second at 44100Hz, 'samples' = 44100 regardless of the number of channels */
|
||||
bool FLAC__encoder_process_interleaved(FLAC__Encoder *encoder, const int32 buf[], unsigned samples)
|
||||
{
|
||||
unsigned i, j, k, channel;
|
||||
int32 x, left = 0, mid, side;
|
||||
const bool ms = encoder->do_mid_side_stereo && encoder->channels == 2;
|
||||
const int32 min_side = -((int64)1 << (encoder->bits_per_sample-1));
|
||||
const int32 max_side = ((int64)1 << (encoder->bits_per_sample-1)) - 1;
|
||||
|
||||
assert(encoder != 0);
|
||||
assert(encoder->state == FLAC__ENCODER_OK);
|
||||
|
||||
j = k = 0;
|
||||
do {
|
||||
for(i = encoder->guts->current_sample_number; i < encoder->blocksize && j < samples; i++, j++, k++) {
|
||||
for(channel = 0; channel < encoder->channels; channel++, k++) {
|
||||
x = buf[k];
|
||||
encoder->guts->integer_signal[channel][i] = x;
|
||||
encoder->guts->real_signal[channel][i] = (real)x;
|
||||
if(ms && encoder->guts->current_frame_can_do_mid_side) {
|
||||
if(channel == 0) {
|
||||
left = x;
|
||||
}
|
||||
else {
|
||||
side = left - x;
|
||||
if(side < min_side || side > max_side) {
|
||||
encoder->guts->current_frame_can_do_mid_side = false;
|
||||
}
|
||||
else {
|
||||
mid = (left + x) >> 1; /* NOTE: not the same as divide-by-two ! */
|
||||
encoder->guts->integer_signal_mid_side[0][i] = mid;
|
||||
encoder->guts->integer_signal_mid_side[1][i] = side;
|
||||
encoder->guts->real_signal_mid_side[0][i] = (real)mid;
|
||||
encoder->guts->real_signal_mid_side[1][i] = (real)side;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
encoder->guts->current_sample_number++;
|
||||
}
|
||||
if(i == encoder->blocksize) {
|
||||
if(!encoder_process_frame_(encoder, false)) /* false => not last frame */
|
||||
return false;
|
||||
}
|
||||
} while(j < samples);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool encoder_process_frame_(FLAC__Encoder *encoder, bool is_last_frame)
|
||||
{
|
||||
FLAC__FrameHeader frame_header;
|
||||
FLAC__BitBuffer *smallest_frame;
|
||||
|
||||
assert(encoder->state == FLAC__ENCODER_OK);
|
||||
|
||||
/*
|
||||
* First do a normal encoding pass
|
||||
*/
|
||||
frame_header.blocksize = encoder->blocksize;
|
||||
frame_header.sample_rate = encoder->sample_rate;
|
||||
frame_header.channels = encoder->channels;
|
||||
frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_INDEPENDENT; /* the default unless the encoder determines otherwise */
|
||||
frame_header.bits_per_sample = encoder->bits_per_sample;
|
||||
frame_header.number.frame_number = encoder->guts->current_frame_number;
|
||||
|
||||
if(!FLAC__bitbuffer_clear(&encoder->guts->frame)) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__frame_add_header(&frame_header, encoder->streamable_subset, is_last_frame, &encoder->guts->frame)) {
|
||||
encoder->state = FLAC__ENCODER_FRAMING_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!encoder_process_subframes_(encoder, is_last_frame, &frame_header, encoder->channels, encoder->guts->integer_signal, encoder->guts->real_signal, &encoder->guts->frame))
|
||||
return false;
|
||||
|
||||
smallest_frame = &encoder->guts->frame;
|
||||
|
||||
/*
|
||||
* Now try a mid-side version if necessary; otherwise, just use the previous step's frame
|
||||
*/
|
||||
if(encoder->do_mid_side_stereo && encoder->guts->current_frame_can_do_mid_side) {
|
||||
int32 *integer_signal[2];
|
||||
real *real_signal[2];
|
||||
|
||||
assert(encoder->channels == 2);
|
||||
|
||||
/* mid-side */
|
||||
frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_MID_SIDE;
|
||||
if(!FLAC__bitbuffer_clear(&encoder->guts->frame_mid_side)) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__frame_add_header(&frame_header, encoder->streamable_subset, is_last_frame, &encoder->guts->frame_mid_side)) {
|
||||
encoder->state = FLAC__ENCODER_FRAMING_ERROR;
|
||||
return false;
|
||||
}
|
||||
integer_signal[0] = encoder->guts->integer_signal_mid_side[0]; /* mid channel */
|
||||
integer_signal[1] = encoder->guts->integer_signal_mid_side[1]; /* side channel */
|
||||
real_signal[0] = encoder->guts->real_signal_mid_side[0]; /* mid channel */
|
||||
real_signal[1] = encoder->guts->real_signal_mid_side[1]; /* side channel */
|
||||
if(!encoder_process_subframes_(encoder, is_last_frame, &frame_header, encoder->channels, integer_signal, real_signal, &encoder->guts->frame_mid_side))
|
||||
return false;
|
||||
if(encoder->guts->frame_mid_side.total_bits < smallest_frame->total_bits)
|
||||
smallest_frame = &encoder->guts->frame_mid_side;
|
||||
|
||||
/* left-side */
|
||||
frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_LEFT_SIDE;
|
||||
if(!FLAC__bitbuffer_clear(&encoder->guts->frame_left_side)) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__frame_add_header(&frame_header, encoder->streamable_subset, is_last_frame, &encoder->guts->frame_left_side)) {
|
||||
encoder->state = FLAC__ENCODER_FRAMING_ERROR;
|
||||
return false;
|
||||
}
|
||||
integer_signal[0] = encoder->guts->integer_signal[0]; /* left channel */
|
||||
integer_signal[1] = encoder->guts->integer_signal_mid_side[1]; /* side channel */
|
||||
real_signal[0] = encoder->guts->real_signal[0]; /* left channel */
|
||||
real_signal[1] = encoder->guts->real_signal_mid_side[1]; /* side channel */
|
||||
if(!encoder_process_subframes_(encoder, is_last_frame, &frame_header, encoder->channels, integer_signal, real_signal, &encoder->guts->frame_left_side))
|
||||
return false;
|
||||
if(encoder->guts->frame_left_side.total_bits < smallest_frame->total_bits)
|
||||
smallest_frame = &encoder->guts->frame_left_side;
|
||||
|
||||
/* right-side */
|
||||
frame_header.channel_assignment = FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE;
|
||||
if(!FLAC__bitbuffer_clear(&encoder->guts->frame_right_side)) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__frame_add_header(&frame_header, encoder->streamable_subset, is_last_frame, &encoder->guts->frame_right_side)) {
|
||||
encoder->state = FLAC__ENCODER_FRAMING_ERROR;
|
||||
return false;
|
||||
}
|
||||
integer_signal[0] = encoder->guts->integer_signal_mid_side[1]; /* side channel */
|
||||
integer_signal[1] = encoder->guts->integer_signal[1]; /* right channel */
|
||||
real_signal[0] = encoder->guts->real_signal_mid_side[1]; /* side channel */
|
||||
real_signal[1] = encoder->guts->real_signal[1]; /* right channel */
|
||||
if(!encoder_process_subframes_(encoder, is_last_frame, &frame_header, encoder->channels, integer_signal, real_signal, &encoder->guts->frame_right_side))
|
||||
return false;
|
||||
if(encoder->guts->frame_right_side.total_bits < smallest_frame->total_bits)
|
||||
smallest_frame = &encoder->guts->frame_right_side;
|
||||
}
|
||||
|
||||
/*
|
||||
* Zero-pad the frame to a byte_boundary
|
||||
*/
|
||||
if(!FLAC__bitbuffer_zero_pad_to_byte_boundary(smallest_frame)) {
|
||||
encoder->state = FLAC__ENCODER_MEMORY_ALLOCATION_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write it
|
||||
*/
|
||||
assert(smallest_frame->bits == 0); /* assert that we're byte-aligned before writing */
|
||||
assert(smallest_frame->total_consumed_bits == 0); /* assert that no reading of the buffer was done */
|
||||
if(encoder->guts->write_callback(encoder, smallest_frame->buffer, smallest_frame->bytes, encoder->blocksize, encoder->guts->current_frame_number, encoder->guts->client_data) != FLAC__ENCODER_WRITE_OK) {
|
||||
encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_WRITING;
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get ready for the next frame
|
||||
*/
|
||||
encoder->guts->current_frame_can_do_mid_side = true;
|
||||
encoder->guts->current_sample_number = 0;
|
||||
encoder->guts->current_frame_number++;
|
||||
encoder->guts->metadata.data.encoding.total_samples += (uint64)encoder->blocksize;
|
||||
encoder->guts->metadata.data.encoding.min_framesize = min(smallest_frame->bytes, encoder->guts->metadata.data.encoding.min_framesize);
|
||||
encoder->guts->metadata.data.encoding.max_framesize = max(smallest_frame->bytes, encoder->guts->metadata.data.encoding.max_framesize);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool encoder_process_subframes_(FLAC__Encoder *encoder, bool is_last_frame, const FLAC__FrameHeader *frame_header, unsigned channels, const int32 *integer_signal[], const real *real_signal[], FLAC__BitBuffer *frame)
|
||||
{
|
||||
real fixed_residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1];
|
||||
real lpc_residual_bits_per_sample;
|
||||
real autoc[FLAC__MAX_LPC_ORDER+1];
|
||||
real lp_coeff[FLAC__MAX_LPC_ORDER][FLAC__MAX_LPC_ORDER];
|
||||
real lpc_error[FLAC__MAX_LPC_ORDER];
|
||||
unsigned channel;
|
||||
unsigned min_lpc_order, max_lpc_order, lpc_order;
|
||||
unsigned min_fixed_order, max_fixed_order, guess_fixed_order, fixed_order;
|
||||
unsigned max_partition_order;
|
||||
unsigned min_qlp_coeff_precision, max_qlp_coeff_precision, qlp_coeff_precision;
|
||||
unsigned rice_parameter;
|
||||
unsigned candidate_bits, best_bits;
|
||||
|
||||
if(is_last_frame) {
|
||||
max_partition_order = 0;
|
||||
}
|
||||
else {
|
||||
unsigned limit = 0, b = encoder->blocksize;
|
||||
while(!(b & 1)) {
|
||||
limit++;
|
||||
b >>= 1;
|
||||
}
|
||||
max_partition_order = min(encoder->rice_optimization_level, limit);
|
||||
}
|
||||
|
||||
for(channel = 0; channel < channels; channel++) {
|
||||
/* verbatim subframe is the baseline against which we measure other compressed subframes */
|
||||
best_bits = encoder_evaluate_verbatim_subframe_(frame_header->blocksize, frame_header->bits_per_sample, &(encoder->guts->best_subframe));
|
||||
|
||||
if(frame_header->blocksize >= FLAC__MAX_FIXED_ORDER) {
|
||||
/* check for constant subframe */
|
||||
guess_fixed_order = FLAC__fixed_compute_best_predictor(integer_signal[channel]+FLAC__MAX_FIXED_ORDER, frame_header->blocksize-FLAC__MAX_FIXED_ORDER, fixed_residual_bits_per_sample);
|
||||
if(fixed_residual_bits_per_sample[1] == 0.0) {
|
||||
candidate_bits = encoder_evaluate_constant_subframe_(integer_signal[channel][0], frame_header->bits_per_sample, &(encoder->guts->candidate_subframe));
|
||||
if(candidate_bits < best_bits) {
|
||||
encoder_promote_candidate_subframe_(encoder);
|
||||
best_bits = candidate_bits;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* encode fixed */
|
||||
if(encoder->do_exhaustive_model_search) {
|
||||
min_fixed_order = 0;
|
||||
max_fixed_order = FLAC__MAX_FIXED_ORDER;
|
||||
}
|
||||
else {
|
||||
min_fixed_order = max_fixed_order = guess_fixed_order;
|
||||
}
|
||||
for(fixed_order = min_fixed_order; fixed_order <= max_fixed_order; fixed_order++) {
|
||||
if(fixed_residual_bits_per_sample[fixed_order] >= (real)frame_header->bits_per_sample)
|
||||
continue; /* don't even try */
|
||||
rice_parameter = (fixed_residual_bits_per_sample[fixed_order] > 0.0)? (unsigned)(fixed_residual_bits_per_sample[fixed_order]+0.5) : 0;
|
||||
if(rice_parameter >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN))
|
||||
rice_parameter = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN) - 1;
|
||||
candidate_bits = encoder_evaluate_fixed_subframe_(integer_signal[channel], encoder->guts->residual[!encoder->guts->best_residual], frame_header->blocksize, frame_header->bits_per_sample, fixed_order, rice_parameter, max_partition_order, &(encoder->guts->candidate_subframe));
|
||||
if(candidate_bits < best_bits) {
|
||||
encoder_promote_candidate_subframe_(encoder);
|
||||
best_bits = candidate_bits;
|
||||
}
|
||||
}
|
||||
|
||||
/* encode lpc */
|
||||
if(encoder->max_lpc_order > 0) {
|
||||
if(encoder->max_lpc_order >= frame_header->blocksize)
|
||||
max_lpc_order = frame_header->blocksize-1;
|
||||
else
|
||||
max_lpc_order = encoder->max_lpc_order;
|
||||
if(max_lpc_order > 0) {
|
||||
FLAC__lpc_compute_autocorrelation(real_signal[channel], frame_header->blocksize, max_lpc_order+1, autoc);
|
||||
FLAC__lpc_compute_lp_coefficients(autoc, max_lpc_order, lp_coeff, lpc_error);
|
||||
if(encoder->do_exhaustive_model_search) {
|
||||
min_lpc_order = 1;
|
||||
}
|
||||
else {
|
||||
unsigned guess_lpc_order = FLAC__lpc_compute_best_order(lpc_error, max_lpc_order, frame_header->blocksize, frame_header->bits_per_sample);
|
||||
min_lpc_order = max_lpc_order = guess_lpc_order;
|
||||
}
|
||||
if(encoder->do_qlp_coeff_prec_search) {
|
||||
min_qlp_coeff_precision = FLAC__MIN_QLP_COEFF_PRECISION;
|
||||
max_qlp_coeff_precision = 32 - frame_header->bits_per_sample - 1;
|
||||
}
|
||||
else {
|
||||
min_qlp_coeff_precision = max_qlp_coeff_precision = encoder->qlp_coeff_precision;
|
||||
}
|
||||
for(lpc_order = min_lpc_order; lpc_order <= max_lpc_order; lpc_order++) {
|
||||
lpc_residual_bits_per_sample = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[lpc_order-1], frame_header->blocksize);
|
||||
if(lpc_residual_bits_per_sample >= (real)frame_header->bits_per_sample)
|
||||
continue; /* don't even try */
|
||||
rice_parameter = (lpc_residual_bits_per_sample > 0.0)? (unsigned)(lpc_residual_bits_per_sample+0.5) : 0;
|
||||
if(rice_parameter >= (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN))
|
||||
rice_parameter = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN) - 1;
|
||||
for(qlp_coeff_precision = min_qlp_coeff_precision; qlp_coeff_precision <= max_qlp_coeff_precision; qlp_coeff_precision++) {
|
||||
candidate_bits = encoder_evaluate_lpc_subframe_(integer_signal[channel], encoder->guts->residual[!encoder->guts->best_residual], lp_coeff[lpc_order-1], frame_header->blocksize, frame_header->bits_per_sample, lpc_order, qlp_coeff_precision, rice_parameter, max_partition_order, &(encoder->guts->candidate_subframe));
|
||||
if(candidate_bits > 0) { /* if == 0, there was a problem quantizing the lpcoeffs */
|
||||
if(candidate_bits < best_bits) {
|
||||
encoder_promote_candidate_subframe_(encoder);
|
||||
best_bits = candidate_bits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* add the best subframe */
|
||||
switch(encoder->guts->best_subframe.type) {
|
||||
case FLAC__SUBFRAME_TYPE_CONSTANT:
|
||||
if(!encoder_generate_constant_subframe_(&(encoder->guts->best_subframe), frame_header->bits_per_sample, frame)) {
|
||||
encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__SUBFRAME_TYPE_FIXED:
|
||||
if(!encoder_generate_fixed_subframe_(&(encoder->guts->best_subframe), encoder->guts->residual[encoder->guts->best_residual], frame_header->blocksize, frame_header->bits_per_sample, frame)) {
|
||||
encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__SUBFRAME_TYPE_LPC:
|
||||
if(!encoder_generate_lpc_subframe_(&(encoder->guts->best_subframe), encoder->guts->residual[encoder->guts->best_residual], frame_header->blocksize, frame_header->bits_per_sample, frame)) {
|
||||
encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case FLAC__SUBFRAME_TYPE_VERBATIM:
|
||||
if(!encoder_generate_verbatim_subframe_(&(encoder->guts->best_subframe), integer_signal[channel], frame_header->blocksize, frame_header->bits_per_sample, frame)) {
|
||||
encoder->state = FLAC__ENCODER_FATAL_ERROR_WHILE_ENCODING;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
unsigned encoder_evaluate_constant_subframe_(const int32 signal, unsigned bits_per_sample, FLAC__SubframeHeader *subframe)
|
||||
{
|
||||
subframe->type = FLAC__SUBFRAME_TYPE_CONSTANT;
|
||||
subframe->data.constant.value = signal;
|
||||
|
||||
return 8 + bits_per_sample;
|
||||
}
|
||||
|
||||
unsigned encoder_evaluate_fixed_subframe_(const int32 signal[], int32 residual[], unsigned blocksize, unsigned bits_per_sample, unsigned order, unsigned rice_parameter, unsigned max_partition_order, FLAC__SubframeHeader *subframe)
|
||||
{
|
||||
unsigned i, residual_bits;
|
||||
const unsigned residual_samples = blocksize - order;
|
||||
|
||||
FLAC__fixed_compute_residual(signal+order, residual_samples, order, residual);
|
||||
|
||||
subframe->type = FLAC__SUBFRAME_TYPE_FIXED;
|
||||
|
||||
subframe->data.fixed.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
|
||||
|
||||
residual_bits = encoder_find_best_partition_order_(residual, residual_samples, order, rice_parameter, max_partition_order, &subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.parameters);
|
||||
|
||||
subframe->data.fixed.order = order;
|
||||
for(i = 0; i < order; i++)
|
||||
subframe->data.fixed.warmup[i] = signal[i];
|
||||
|
||||
return 8 + (order * bits_per_sample) + residual_bits;
|
||||
}
|
||||
|
||||
unsigned encoder_evaluate_lpc_subframe_(const int32 signal[], int32 residual[], const real lp_coeff[], unsigned blocksize, unsigned bits_per_sample, unsigned order, unsigned qlp_coeff_precision, unsigned rice_parameter, unsigned max_partition_order, FLAC__SubframeHeader *subframe)
|
||||
{
|
||||
int32 qlp_coeff[FLAC__MAX_LPC_ORDER];
|
||||
unsigned i, residual_bits;
|
||||
int quantization, ret;
|
||||
const unsigned residual_samples = blocksize - order;
|
||||
|
||||
ret = FLAC__lpc_quantize_coefficients(lp_coeff, order, qlp_coeff_precision, bits_per_sample, qlp_coeff, &quantization);
|
||||
if(ret != 0)
|
||||
return 0; /* this is a hack to indicate to the caller that we can't do lp at this order on this subframe */
|
||||
|
||||
FLAC__lpc_compute_residual_from_qlp_coefficients(signal+order, residual_samples, qlp_coeff, order, quantization, residual);
|
||||
|
||||
subframe->type = FLAC__SUBFRAME_TYPE_LPC;
|
||||
|
||||
subframe->data.lpc.entropy_coding_method.type = FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE;
|
||||
|
||||
residual_bits = encoder_find_best_partition_order_(residual, residual_samples, order, rice_parameter, max_partition_order, &subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.parameters);
|
||||
|
||||
subframe->data.lpc.order = order;
|
||||
subframe->data.lpc.qlp_coeff_precision = qlp_coeff_precision;
|
||||
subframe->data.lpc.quantization_level = quantization;
|
||||
memcpy(subframe->data.lpc.qlp_coeff, qlp_coeff, sizeof(int32)*FLAC__MAX_LPC_ORDER);
|
||||
for(i = 0; i < order; i++)
|
||||
subframe->data.lpc.warmup[i] = signal[i];
|
||||
|
||||
return 8 + 9 + (order * (qlp_coeff_precision + bits_per_sample)) + residual_bits;
|
||||
}
|
||||
|
||||
unsigned encoder_evaluate_verbatim_subframe_(unsigned blocksize, unsigned bits_per_sample, FLAC__SubframeHeader *subframe)
|
||||
{
|
||||
subframe->type = FLAC__SUBFRAME_TYPE_VERBATIM;
|
||||
|
||||
return 8 + (blocksize * bits_per_sample);
|
||||
}
|
||||
|
||||
unsigned encoder_find_best_partition_order_(int32 residual[], unsigned residual_samples, unsigned predictor_order, unsigned rice_parameter, unsigned max_partition_order, unsigned *best_partition_order, unsigned best_parameters[])
|
||||
{
|
||||
unsigned residual_bits, best_residual_bits = 0;
|
||||
unsigned partition_order;
|
||||
unsigned best_parameters_index = 0, parameters[2][1 << FLAC__MAX_RICE_PARTITION_ORDER];
|
||||
|
||||
for(partition_order = 0; partition_order <= max_partition_order; partition_order++) {
|
||||
if(!encoder_set_partitioned_rice_(residual, residual_samples, predictor_order, rice_parameter, partition_order, parameters[!best_parameters_index], &residual_bits)) {
|
||||
assert(best_residual_bits != 0);
|
||||
break;
|
||||
}
|
||||
if(best_residual_bits == 0 || residual_bits < best_residual_bits) {
|
||||
best_residual_bits = residual_bits;
|
||||
*best_partition_order = partition_order;
|
||||
best_parameters_index = !best_parameters_index;
|
||||
}
|
||||
}
|
||||
memcpy(best_parameters, parameters[best_parameters_index], sizeof(unsigned)*(1<<(*best_partition_order)));
|
||||
|
||||
return best_residual_bits;
|
||||
}
|
||||
|
||||
bool encoder_generate_constant_subframe_(const FLAC__SubframeHeader *header, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer)
|
||||
{
|
||||
assert(header->type == FLAC__SUBFRAME_TYPE_CONSTANT);
|
||||
return FLAC__subframe_add_constant(bits_per_sample, header, bitbuffer);
|
||||
}
|
||||
|
||||
bool encoder_generate_fixed_subframe_(const FLAC__SubframeHeader *header, int32 residual[], unsigned blocksize, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer)
|
||||
{
|
||||
assert(header->type == FLAC__SUBFRAME_TYPE_FIXED);
|
||||
return FLAC__subframe_add_fixed(residual, blocksize - header->data.fixed.order, bits_per_sample, header, bitbuffer);
|
||||
}
|
||||
|
||||
bool encoder_generate_lpc_subframe_(const FLAC__SubframeHeader *header, int32 residual[], unsigned blocksize, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer)
|
||||
{
|
||||
assert(header->type == FLAC__SUBFRAME_TYPE_LPC);
|
||||
return FLAC__subframe_add_lpc(residual, blocksize - header->data.lpc.order, bits_per_sample, header, bitbuffer);
|
||||
}
|
||||
|
||||
bool encoder_generate_verbatim_subframe_(const FLAC__SubframeHeader *header, const int32 signal[], unsigned blocksize, unsigned bits_per_sample, FLAC__BitBuffer *bitbuffer)
|
||||
{
|
||||
assert(header->type == FLAC__SUBFRAME_TYPE_VERBATIM);
|
||||
#ifdef NDEBUG
|
||||
(void)header; /* silence compiler warning about unused parameter */
|
||||
#endif
|
||||
return FLAC__subframe_add_verbatim(signal, blocksize, bits_per_sample, bitbuffer);
|
||||
}
|
||||
|
||||
void encoder_promote_candidate_subframe_(FLAC__Encoder *encoder)
|
||||
{
|
||||
assert(encoder->state == FLAC__ENCODER_OK);
|
||||
encoder->guts->best_subframe = encoder->guts->candidate_subframe;
|
||||
encoder->guts->best_residual = !encoder->guts->best_residual;
|
||||
}
|
||||
|
||||
bool encoder_set_partitioned_rice_(const int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameter, const unsigned partition_order, unsigned parameters[], unsigned *bits)
|
||||
{
|
||||
unsigned bits_ = 2 + 3;
|
||||
|
||||
if(partition_order == 0) {
|
||||
unsigned i;
|
||||
parameters[0] = rice_parameter;
|
||||
bits_ += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
|
||||
for(i = 0; i < residual_samples; i++)
|
||||
bits_ += RICE_BITS(residual[i], rice_parameter);
|
||||
}
|
||||
else {
|
||||
unsigned i, j, k = 0, k_last = 0, z;
|
||||
unsigned mean;
|
||||
unsigned parameter, partition_samples;
|
||||
const unsigned max_parameter = (1u << FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN) - 1;
|
||||
for(i = 0; i < (1u<<partition_order); i++) {
|
||||
partition_samples = (residual_samples+predictor_order) >> partition_order;
|
||||
if(i == 0) {
|
||||
if(partition_samples <= predictor_order)
|
||||
return false;
|
||||
else
|
||||
partition_samples -= predictor_order;
|
||||
}
|
||||
mean = partition_samples >> 1;
|
||||
for(j = 0; j < partition_samples; j++, k++)
|
||||
mean += ((residual[k] < 0)? (unsigned)(-residual[k]) : (unsigned)residual[k]);
|
||||
mean /= partition_samples;
|
||||
z = 0x80000000;
|
||||
for(j = 0; j < 32; j++, z >>= 1)
|
||||
if(mean & z)
|
||||
break;
|
||||
parameter = j > 31? 0 : 32 - j - 1;
|
||||
if(parameter > max_parameter)
|
||||
parameter = max_parameter;
|
||||
parameters[i] = parameter;
|
||||
bits_ += FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN;
|
||||
for(j = k_last; j < k; j++)
|
||||
bits_ += RICE_BITS(residual[j], parameter);
|
||||
k_last = k;
|
||||
}
|
||||
}
|
||||
|
||||
*bits = bits_;
|
||||
return true;
|
||||
}
|
340
src/libFLAC/encoder_framing.c
Normal file
340
src/libFLAC/encoder_framing.c
Normal file
@ -0,0 +1,340 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "private/encoder_framing.h"
|
||||
#include "private/crc.h"
|
||||
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
#define max(x,y) ((x)>(y)?(x):(y))
|
||||
|
||||
static bool subframe_add_entropy_coding_method_(FLAC__BitBuffer *bb, const FLAC__EntropyCodingMethod *method);
|
||||
static bool subframe_add_residual_partitioned_rice_(FLAC__BitBuffer *bb, const int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned partition_order);
|
||||
|
||||
bool FLAC__add_metadata_block(const FLAC__StreamMetaData *metadata, FLAC__BitBuffer *bb)
|
||||
{
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->is_last, FLAC__STREAM_METADATA_IS_LAST_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->type, FLAC__STREAM_METADATA_TYPE_LEN))
|
||||
return false;
|
||||
|
||||
assert(metadata->length < (1u << FLAC__STREAM_METADATA_LENGTH_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->length, FLAC__STREAM_METADATA_LENGTH_LEN))
|
||||
return false;
|
||||
|
||||
switch(metadata->type) {
|
||||
case FLAC__METADATA_TYPE_ENCODING:
|
||||
assert(metadata->data.encoding.min_blocksize < (1u << FLAC__STREAM_METADATA_ENCODING_MIN_BLOCK_SIZE_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.min_blocksize, FLAC__STREAM_METADATA_ENCODING_MIN_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
assert(metadata->data.encoding.max_blocksize < (1u << FLAC__STREAM_METADATA_ENCODING_MAX_BLOCK_SIZE_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.max_blocksize, FLAC__STREAM_METADATA_ENCODING_MAX_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
assert(metadata->data.encoding.min_framesize < (1u << FLAC__STREAM_METADATA_ENCODING_MIN_FRAME_SIZE_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.min_framesize, FLAC__STREAM_METADATA_ENCODING_MIN_FRAME_SIZE_LEN))
|
||||
return false;
|
||||
assert(metadata->data.encoding.max_framesize < (1u << FLAC__STREAM_METADATA_ENCODING_MAX_FRAME_SIZE_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.max_framesize, FLAC__STREAM_METADATA_ENCODING_MAX_FRAME_SIZE_LEN))
|
||||
return false;
|
||||
assert(metadata->data.encoding.sample_rate > 0);
|
||||
assert(metadata->data.encoding.sample_rate < (1u << FLAC__STREAM_METADATA_ENCODING_SAMPLE_RATE_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.sample_rate, FLAC__STREAM_METADATA_ENCODING_SAMPLE_RATE_LEN))
|
||||
return false;
|
||||
assert(metadata->data.encoding.channels > 0);
|
||||
assert(metadata->data.encoding.channels <= (1u << FLAC__STREAM_METADATA_ENCODING_CHANNELS_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.channels-1, FLAC__STREAM_METADATA_ENCODING_CHANNELS_LEN))
|
||||
return false;
|
||||
assert(metadata->data.encoding.bits_per_sample > 0);
|
||||
assert(metadata->data.encoding.bits_per_sample <= (1u << FLAC__STREAM_METADATA_ENCODING_BITS_PER_SAMPLE_LEN));
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, metadata->data.encoding.bits_per_sample-1, FLAC__STREAM_METADATA_ENCODING_BITS_PER_SAMPLE_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitbuffer_write_raw_uint64(bb, metadata->data.encoding.total_samples, FLAC__STREAM_METADATA_ENCODING_TOTAL_SAMPLES_LEN))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__frame_add_header(const FLAC__FrameHeader *header, bool streamable_subset, bool is_last_block, FLAC__BitBuffer *bb)
|
||||
{
|
||||
unsigned u, crc_start, blocksize_hint, sample_rate_hint;
|
||||
byte crc;
|
||||
|
||||
assert(bb->bits == 0); /* assert that we're byte-aligned before writing */
|
||||
|
||||
crc_start = bb->bytes;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, FLAC__FRAME_HEADER_SYNC, FLAC__FRAME_HEADER_SYNC_LEN))
|
||||
return false;
|
||||
|
||||
assert(header->blocksize > 0 && header->blocksize <= FLAC__MAX_BLOCK_SIZE);
|
||||
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;
|
||||
default:
|
||||
if(streamable_subset || is_last_block) {
|
||||
if(header->blocksize <= 0x100)
|
||||
blocksize_hint = u = 6;
|
||||
else
|
||||
blocksize_hint = u = 7;
|
||||
}
|
||||
else
|
||||
u = 0;
|
||||
break;
|
||||
}
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, u, FLAC__FRAME_HEADER_BLOCK_SIZE_LEN))
|
||||
return false;
|
||||
|
||||
assert(header->sample_rate > 0 && header->sample_rate < (1u << FLAC__STREAM_METADATA_ENCODING_SAMPLE_RATE_LEN));
|
||||
sample_rate_hint = 0;
|
||||
switch(header->sample_rate) {
|
||||
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(streamable_subset) {
|
||||
if(header->sample_rate % 1000 == 0)
|
||||
sample_rate_hint = u = 12;
|
||||
else if(header->sample_rate % 10 == 0)
|
||||
sample_rate_hint = u = 14;
|
||||
else
|
||||
sample_rate_hint = u = 13;
|
||||
}
|
||||
else
|
||||
u = 0;
|
||||
break;
|
||||
}
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, u, FLAC__FRAME_HEADER_SAMPLE_RATE_LEN))
|
||||
return false;
|
||||
|
||||
assert(header->channels > 0 && header->channels <= (1u << FLAC__STREAM_METADATA_ENCODING_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:
|
||||
assert(header->channels == 2);
|
||||
u = 8;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_RIGHT_SIDE:
|
||||
assert(header->channels == 2);
|
||||
u = 9;
|
||||
break;
|
||||
case FLAC__CHANNEL_ASSIGNMENT_MID_SIDE:
|
||||
assert(header->channels == 2);
|
||||
u = 10;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, u, FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN))
|
||||
return false;
|
||||
|
||||
assert(header->bits_per_sample > 0 && header->bits_per_sample <= (1u << FLAC__STREAM_METADATA_ENCODING_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__bitbuffer_write_raw_uint32(bb, u, FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, 0, FLAC__FRAME_HEADER_ZERO_PAD_LEN))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitbuffer_write_utf8_uint32(bb, header->number.frame_number))
|
||||
return false;
|
||||
|
||||
if(blocksize_hint)
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, header->blocksize-1, (blocksize_hint==6)? 8:16))
|
||||
return false;
|
||||
|
||||
switch(sample_rate_hint) {
|
||||
case 12:
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, header->sample_rate / 1000, 8))
|
||||
return false;
|
||||
break;
|
||||
case 13:
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, header->sample_rate, 16))
|
||||
return false;
|
||||
break;
|
||||
case 14:
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, header->sample_rate / 10, 16))
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
/* write the CRC */
|
||||
assert(bb->buffer[crc_start] == 0xff); /* MAGIC NUMBER for the first byte of the sync code */
|
||||
assert(bb->bits == 0); /* assert that we're byte-aligned */
|
||||
crc = FLAC__crc8(bb->buffer+crc_start, bb->bytes-crc_start);
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, crc, FLAC__FRAME_HEADER_CRC8_LEN))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__subframe_add_constant(unsigned bits_per_sample, const FLAC__SubframeHeader *subframe, FLAC__BitBuffer *bb)
|
||||
{
|
||||
bool ok;
|
||||
|
||||
ok =
|
||||
FLAC__bitbuffer_write_raw_uint32(bb, FLAC__SUBFRAME_HEADER_TYPE_CONSTANT, FLAC__SUBFRAME_HEADER_TYPE_LEN) &&
|
||||
FLAC__bitbuffer_write_raw_int32(bb, subframe->data.constant.value, bits_per_sample)
|
||||
;
|
||||
|
||||
return ok;
|
||||
}
|
||||
|
||||
bool FLAC__subframe_add_fixed(const int32 residual[], unsigned residual_samples, unsigned bits_per_sample, const FLAC__SubframeHeader *subframe, FLAC__BitBuffer *bb)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, FLAC__SUBFRAME_HEADER_TYPE_FIXED | (subframe->data.fixed.order<<1), FLAC__SUBFRAME_HEADER_TYPE_LEN))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < subframe->data.fixed.order; i++)
|
||||
if(!FLAC__bitbuffer_write_raw_int32(bb, subframe->data.fixed.warmup[i], bits_per_sample))
|
||||
return false;
|
||||
|
||||
if(!subframe_add_entropy_coding_method_(bb, &subframe->data.fixed.entropy_coding_method))
|
||||
return false;
|
||||
switch(subframe->data.fixed.entropy_coding_method.type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
if(!subframe_add_residual_partitioned_rice_(bb, residual, residual_samples, subframe->data.fixed.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.order))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__subframe_add_lpc(const int32 residual[], unsigned residual_samples, unsigned bits_per_sample, const FLAC__SubframeHeader *subframe, FLAC__BitBuffer *bb)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, FLAC__SUBFRAME_HEADER_TYPE_LPC | ((subframe->data.lpc.order-1)<<1), FLAC__SUBFRAME_HEADER_TYPE_LEN))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < subframe->data.lpc.order; i++)
|
||||
if(!FLAC__bitbuffer_write_raw_int32(bb, subframe->data.lpc.warmup[i], bits_per_sample))
|
||||
return false;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, subframe->data.lpc.qlp_coeff_precision-1, FLAC__SUBFRAME_HEADER_LPC_QLP_COEFF_PRECISION_LEN))
|
||||
return false;
|
||||
if(!FLAC__bitbuffer_write_raw_int32(bb, subframe->data.lpc.quantization_level, FLAC__SUBFRAME_HEADER_LPC_QLP_SHIFT_LEN))
|
||||
return false;
|
||||
for(i = 0; i < subframe->data.lpc.order; i++)
|
||||
if(!FLAC__bitbuffer_write_raw_int32(bb, subframe->data.lpc.qlp_coeff[i], subframe->data.lpc.qlp_coeff_precision))
|
||||
return false;
|
||||
|
||||
if(!subframe_add_entropy_coding_method_(bb, &subframe->data.lpc.entropy_coding_method))
|
||||
return false;
|
||||
switch(subframe->data.lpc.entropy_coding_method.type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
if(!subframe_add_residual_partitioned_rice_(bb, residual, residual_samples, subframe->data.lpc.order, subframe->data.fixed.entropy_coding_method.data.partitioned_rice.parameters, subframe->data.lpc.entropy_coding_method.data.partitioned_rice.order))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FLAC__subframe_add_verbatim(const int32 signal[], unsigned samples, unsigned bits_per_sample, FLAC__BitBuffer *bb)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, FLAC__SUBFRAME_HEADER_TYPE_VERBATIM, FLAC__SUBFRAME_HEADER_TYPE_LEN))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < samples; i++)
|
||||
if(!FLAC__bitbuffer_write_raw_int32(bb, signal[i], bits_per_sample))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subframe_add_entropy_coding_method_(FLAC__BitBuffer *bb, const FLAC__EntropyCodingMethod *method)
|
||||
{
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, method->type, FLAC__ENTROPY_CODING_METHOD_TYPE_LEN))
|
||||
return false;
|
||||
switch(method->type) {
|
||||
case FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE:
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, method->data.partitioned_rice.order, FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN))
|
||||
return false;
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool subframe_add_residual_partitioned_rice_(FLAC__BitBuffer *bb, const int32 residual[], const unsigned residual_samples, const unsigned predictor_order, const unsigned rice_parameters[], const unsigned partition_order)
|
||||
{
|
||||
if(partition_order == 0) {
|
||||
unsigned i;
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, rice_parameters[0], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN))
|
||||
return false;
|
||||
for(i = 0; i < residual_samples; i++) {
|
||||
if(!FLAC__bitbuffer_write_rice_signed(bb, residual[i], rice_parameters[0]))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
unsigned i, j, k = 0, k_last = 0;
|
||||
unsigned partition_samples;
|
||||
for(i = 0; i < (1u<<partition_order); i++) {
|
||||
if(!FLAC__bitbuffer_write_raw_uint32(bb, rice_parameters[i], FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN))
|
||||
return false;
|
||||
partition_samples = (residual_samples+predictor_order) >> partition_order;
|
||||
if(i == 0)
|
||||
partition_samples -= predictor_order;
|
||||
k += partition_samples;
|
||||
for(j = k_last; j < k; j++)
|
||||
if(!FLAC__bitbuffer_write_rice_signed(bb, residual[j], rice_parameters[i]))
|
||||
return false;
|
||||
k_last = k;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
403
src/libFLAC/file_decoder.c
Normal file
403
src/libFLAC/file_decoder.c
Normal file
@ -0,0 +1,403 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h> /* for malloc() */
|
||||
#include <string.h> /* for strcmp() */
|
||||
#include "FLAC/file_decoder.h"
|
||||
#include "protected/stream_decoder.h"
|
||||
|
||||
typedef struct FLAC__FileDecoderPrivate {
|
||||
FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
|
||||
void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
void (*error_callback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
void *client_data;
|
||||
FILE *file;
|
||||
FLAC__StreamDecoder *stream;
|
||||
/* the rest of these are only used for seeking: */
|
||||
FLAC__StreamMetaData_Encoding metadata; /* we keep this around so we can figure out how to seek quickly */
|
||||
FLAC__FrameHeader last_frame_header; /* holds the info of the last frame we seeked to */
|
||||
uint64 target_sample;
|
||||
} FLAC__FileDecoderPrivate;
|
||||
|
||||
static FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
|
||||
static void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
static void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
static bool seek_to_absolute_sample_(FLAC__FileDecoder *decoder, long filesize, uint64 target_sample);
|
||||
|
||||
FLAC__FileDecoder *FLAC__file_decoder_get_new_instance()
|
||||
{
|
||||
FLAC__FileDecoder *decoder = (FLAC__FileDecoder*)malloc(sizeof(FLAC__FileDecoder));
|
||||
if(decoder != 0) {
|
||||
decoder->state = FLAC__FILE_DECODER_UNINITIALIZED;
|
||||
decoder->guts = 0;
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
|
||||
void FLAC__file_decoder_free_instance(FLAC__FileDecoder *decoder)
|
||||
{
|
||||
free(decoder);
|
||||
}
|
||||
|
||||
FLAC__FileDecoderState FLAC__file_decoder_init(
|
||||
FLAC__FileDecoder *decoder,
|
||||
const char *filename,
|
||||
FLAC__StreamDecoderWriteStatus (*write_callback)(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data),
|
||||
void (*metadata_callback)(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data),
|
||||
void (*error_callback)(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data),
|
||||
void *client_data
|
||||
)
|
||||
{
|
||||
assert(sizeof(int) >= 4); /* we want to die right away if this is not true */
|
||||
assert(decoder != 0);
|
||||
assert(write_callback != 0);
|
||||
assert(metadata_callback != 0);
|
||||
assert(error_callback != 0);
|
||||
assert(decoder->state == FLAC__FILE_DECODER_UNINITIALIZED);
|
||||
assert(decoder->guts == 0);
|
||||
|
||||
decoder->state = FLAC__FILE_DECODER_OK;
|
||||
|
||||
decoder->guts = (FLAC__FileDecoderPrivate*)malloc(sizeof(FLAC__FileDecoderPrivate));
|
||||
if(decoder->guts == 0)
|
||||
return decoder->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR;
|
||||
|
||||
decoder->guts->write_callback = write_callback;
|
||||
decoder->guts->metadata_callback = metadata_callback;
|
||||
decoder->guts->error_callback = error_callback;
|
||||
decoder->guts->client_data = client_data;
|
||||
decoder->guts->stream = 0;
|
||||
|
||||
if(0 == strcmp(filename, "-"))
|
||||
decoder->guts->file = stdin;
|
||||
else
|
||||
decoder->guts->file = fopen(filename, "rb");
|
||||
if(decoder->guts->file == 0)
|
||||
return decoder->state = FLAC__FILE_DECODER_ERROR_OPENING_FILE;
|
||||
|
||||
decoder->guts->stream = FLAC__stream_decoder_get_new_instance();
|
||||
if(FLAC__stream_decoder_init(decoder->guts->stream, read_callback_, write_callback_, metadata_callback_, error_callback_, decoder) != FLAC__STREAM_DECODER_SEARCH_FOR_METADATA)
|
||||
return decoder->state = FLAC__FILE_DECODER_MEMORY_ALLOCATION_ERROR; /* this is based on internal knowledge of FLAC__stream_decoder_init() */
|
||||
|
||||
return decoder->state;
|
||||
}
|
||||
|
||||
void FLAC__file_decoder_finish(FLAC__FileDecoder *decoder)
|
||||
{
|
||||
assert(decoder != 0);
|
||||
if(decoder->state == FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
return;
|
||||
if(decoder->guts != 0) {
|
||||
if(decoder->guts->file != 0 && decoder->guts->file != stdin)
|
||||
fclose(decoder->guts->file);
|
||||
if(decoder->guts->stream != 0) {
|
||||
FLAC__stream_decoder_finish(decoder->guts->stream);
|
||||
FLAC__stream_decoder_free_instance(decoder->guts->stream);
|
||||
}
|
||||
free(decoder->guts);
|
||||
decoder->guts = 0;
|
||||
}
|
||||
decoder->state = FLAC__FILE_DECODER_UNINITIALIZED;
|
||||
}
|
||||
|
||||
bool FLAC__file_decoder_process_whole_file(FLAC__FileDecoder *decoder)
|
||||
{
|
||||
bool ret;
|
||||
assert(decoder != 0);
|
||||
|
||||
if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
|
||||
return true;
|
||||
|
||||
assert(decoder->state == FLAC__FILE_DECODER_OK);
|
||||
|
||||
ret = FLAC__stream_decoder_process_whole_stream(decoder->guts->stream);
|
||||
if(!ret)
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FLAC__file_decoder_process_metadata(FLAC__FileDecoder *decoder)
|
||||
{
|
||||
bool ret;
|
||||
assert(decoder != 0);
|
||||
|
||||
if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
|
||||
return true;
|
||||
|
||||
assert(decoder->state == FLAC__FILE_DECODER_OK);
|
||||
|
||||
ret = FLAC__stream_decoder_process_metadata(decoder->guts->stream);
|
||||
if(!ret)
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FLAC__file_decoder_process_one_frame(FLAC__FileDecoder *decoder)
|
||||
{
|
||||
bool ret;
|
||||
assert(decoder != 0);
|
||||
|
||||
if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
|
||||
return true;
|
||||
|
||||
assert(decoder->state == FLAC__FILE_DECODER_OK);
|
||||
|
||||
ret = FLAC__stream_decoder_process_one_frame(decoder->guts->stream);
|
||||
if(!ret)
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FLAC__file_decoder_process_remaining_frames(FLAC__FileDecoder *decoder)
|
||||
{
|
||||
bool ret;
|
||||
assert(decoder != 0);
|
||||
|
||||
if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE)
|
||||
return true;
|
||||
|
||||
assert(decoder->state == FLAC__FILE_DECODER_OK);
|
||||
|
||||
ret = FLAC__stream_decoder_process_remaining_frames(decoder->guts->stream);
|
||||
if(!ret)
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool FLAC__file_decoder_seek_absolute(FLAC__FileDecoder *decoder, uint64 sample)
|
||||
{
|
||||
long filesize;
|
||||
|
||||
assert(decoder != 0);
|
||||
assert(decoder->state == FLAC__FILE_DECODER_OK);
|
||||
|
||||
decoder->state = FLAC__FILE_DECODER_SEEKING;
|
||||
|
||||
if(!FLAC__stream_decoder_reset(decoder->guts->stream)) {
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
return false;
|
||||
}
|
||||
/* get the file length */
|
||||
if(0 != fseek(decoder->guts->file, 0, SEEK_END)) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
fflush(decoder->guts->file);
|
||||
if(-1 == (filesize = ftell(decoder->guts->file))) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
/* rewind */
|
||||
if(0 != fseek(decoder->guts->file, 0, SEEK_SET)) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__stream_decoder_process_metadata(decoder->guts->stream)) {
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(sample > decoder->guts->metadata.total_samples) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
|
||||
return seek_to_absolute_sample_(decoder, filesize, sample);
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderReadStatus read_callback_(const FLAC__StreamDecoder *decoder, byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
|
||||
(void)decoder;
|
||||
if(feof(file_decoder->guts->file)) {
|
||||
file_decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
|
||||
return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
|
||||
}
|
||||
else if(*bytes > 0) {
|
||||
size_t bytes_read = fread(buffer, sizeof(byte), *bytes, file_decoder->guts->file);
|
||||
if(bytes_read == 0) {
|
||||
if(feof(file_decoder->guts->file)) {
|
||||
file_decoder->state = FLAC__FILE_DECODER_END_OF_FILE;
|
||||
return FLAC__STREAM_DECODER_READ_END_OF_STREAM;
|
||||
}
|
||||
else
|
||||
return FLAC__STREAM_DECODER_READ_ABORT;
|
||||
}
|
||||
else {
|
||||
*bytes = (unsigned)bytes_read;
|
||||
return FLAC__STREAM_DECODER_READ_CONTINUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
return FLAC__STREAM_DECODER_READ_ABORT; /* abort to avoid a deadlock */
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__StreamDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
|
||||
{
|
||||
FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(file_decoder->state == FLAC__FILE_DECODER_SEEKING) {
|
||||
uint64 this_frame_sample = header->number.sample_number;
|
||||
uint64 next_frame_sample = this_frame_sample + (uint64)header->blocksize;
|
||||
uint64 target_sample = file_decoder->guts->target_sample;
|
||||
|
||||
file_decoder->guts->last_frame_header = *header; /* save the header in the guts */
|
||||
if(this_frame_sample <= target_sample && target_sample < next_frame_sample) { /* we hit our target frame */
|
||||
unsigned delta = (unsigned)(target_sample - this_frame_sample);
|
||||
/* kick out of seek mode */
|
||||
file_decoder->state = FLAC__FILE_DECODER_OK;
|
||||
/* shift out the samples before target_sample */
|
||||
if(delta > 0) {
|
||||
unsigned channel;
|
||||
const int32 *newbuffer[FLAC__MAX_CHANNELS];
|
||||
for(channel = 0; channel < header->channels; channel++)
|
||||
newbuffer[channel] = buffer[channel] + delta;
|
||||
file_decoder->guts->last_frame_header.blocksize -= delta;
|
||||
file_decoder->guts->last_frame_header.number.sample_number += (uint64)delta;
|
||||
/* write the relevant samples */
|
||||
return file_decoder->guts->write_callback(file_decoder, &file_decoder->guts->last_frame_header, newbuffer, file_decoder->guts->client_data);
|
||||
}
|
||||
else {
|
||||
/* write the relevant samples */
|
||||
return file_decoder->guts->write_callback(file_decoder, header, buffer, file_decoder->guts->client_data);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
|
||||
}
|
||||
}
|
||||
else {
|
||||
return file_decoder->guts->write_callback(file_decoder, header, buffer, file_decoder->guts->client_data);
|
||||
}
|
||||
}
|
||||
|
||||
void metadata_callback_(const FLAC__StreamDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
|
||||
{
|
||||
FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(metadata->type == FLAC__METADATA_TYPE_ENCODING)
|
||||
file_decoder->guts->metadata = metadata->data.encoding;
|
||||
if(file_decoder->state != FLAC__FILE_DECODER_SEEKING)
|
||||
file_decoder->guts->metadata_callback(file_decoder, metadata, file_decoder->guts->client_data);
|
||||
}
|
||||
|
||||
void error_callback_(const FLAC__StreamDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
FLAC__FileDecoder *file_decoder = (FLAC__FileDecoder *)client_data;
|
||||
(void)decoder;
|
||||
|
||||
if(file_decoder->state != FLAC__FILE_DECODER_SEEKING)
|
||||
file_decoder->guts->error_callback(file_decoder, status, file_decoder->guts->client_data);
|
||||
}
|
||||
|
||||
bool seek_to_absolute_sample_(FLAC__FileDecoder *decoder, long filesize, uint64 target_sample)
|
||||
{
|
||||
long l, r, pos, last_pos = -1;
|
||||
unsigned approx_bytes_per_frame;
|
||||
uint64 last_frame_sample = 0xffffffffffffffff;
|
||||
bool needs_seek;
|
||||
const bool is_variable_blocksize_stream = (decoder->guts->metadata.min_blocksize != decoder->guts->metadata.max_blocksize);
|
||||
|
||||
if(!is_variable_blocksize_stream) {
|
||||
/* we are just guessing here, but we want to guess high, not low */
|
||||
/* note there are no () around 'decoder->guts->metadata.bits_per_sample/8' to keep precision up since it's an integer calulation */
|
||||
approx_bytes_per_frame = decoder->guts->metadata.min_blocksize * decoder->guts->metadata.channels * decoder->guts->metadata.bits_per_sample/8 + 64;
|
||||
}
|
||||
else
|
||||
approx_bytes_per_frame = 1152 * decoder->guts->metadata.channels * decoder->guts->metadata.bits_per_sample/8 + 64;
|
||||
|
||||
/* Now we need to use the metadata and the filelength to search to the frame with the correct sample */
|
||||
if(-1 == (l = ftell(decoder->guts->file))) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
l -= FLAC__stream_decoder_input_bytes_unconsumed(decoder->guts->stream);
|
||||
#ifdef _MSC_VER
|
||||
/* with VC++ you have to spoon feed it the casting */
|
||||
pos = l + (long)((double)(int64)target_sample / (double)(int64)decoder->guts->metadata.total_samples * (double)(filesize-l+1)) - approx_bytes_per_frame;
|
||||
#else
|
||||
pos = l + (long)((double)target_sample / (double)decoder->guts->metadata.total_samples * (double)(filesize-l+1)) - approx_bytes_per_frame;
|
||||
#endif
|
||||
r = filesize - ((decoder->guts->metadata.channels * decoder->guts->metadata.bits_per_sample * FLAC__MAX_BLOCK_SIZE) / 8 + 64);
|
||||
if(pos >= r)
|
||||
pos = r-1;
|
||||
if(pos < l)
|
||||
pos = l;
|
||||
needs_seek = true;
|
||||
|
||||
decoder->guts->target_sample = target_sample;
|
||||
while(1) {
|
||||
if(needs_seek) {
|
||||
if(-1 == fseek(decoder->guts->file, pos, SEEK_SET)) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
if(!FLAC__stream_decoder_flush(decoder->guts->stream)) {
|
||||
decoder->state = FLAC__FILE_DECODER_STREAM_ERROR;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if(!FLAC__stream_decoder_process_one_frame(decoder->guts->stream)) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
/* our write callback will change the state when it gets to the target frame */
|
||||
if(decoder->state != FLAC__FILE_DECODER_SEEKING) {
|
||||
break;
|
||||
}
|
||||
else { /* we need to narrow the search */
|
||||
uint64 this_frame_sample = decoder->guts->last_frame_header.number.sample_number;
|
||||
if(this_frame_sample == last_frame_sample) {
|
||||
/* our last move backwards wasn't big enough */
|
||||
pos -= (last_pos - pos);
|
||||
needs_seek = true;
|
||||
}
|
||||
else {
|
||||
if(target_sample < this_frame_sample) {
|
||||
last_pos = pos;
|
||||
approx_bytes_per_frame = decoder->guts->last_frame_header.blocksize * decoder->guts->last_frame_header.channels * decoder->guts->last_frame_header.bits_per_sample/8 + 64;
|
||||
pos -= approx_bytes_per_frame;
|
||||
needs_seek = true;
|
||||
}
|
||||
else {
|
||||
last_pos = pos;
|
||||
if(-1 == (pos = ftell(decoder->guts->file))) {
|
||||
decoder->state = FLAC__FILE_DECODER_SEEK_ERROR;
|
||||
return false;
|
||||
}
|
||||
pos -= FLAC__stream_decoder_input_bytes_unconsumed(decoder->guts->stream);
|
||||
needs_seek = false;
|
||||
}
|
||||
}
|
||||
if(pos < l)
|
||||
pos = l;
|
||||
last_frame_sample = this_frame_sample;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
159
src/libFLAC/fixed.c
Normal file
159
src/libFLAC/fixed.c
Normal file
@ -0,0 +1,159 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "private/fixed.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) ((x)<0? -(x) : (x))
|
||||
|
||||
unsigned FLAC__fixed_compute_best_predictor(const int32 data[], unsigned data_len, real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1])
|
||||
{
|
||||
int32 last_error_0 = data[-1];
|
||||
int32 last_error_1 = data[-1] - data[-2];
|
||||
int32 last_error_2 = last_error_1 - (data[-2] - data[-3]);
|
||||
int32 last_error_3 = last_error_2 - (data[-2] - 2*data[-3] + data[-4]);
|
||||
int32 error_0, error_1, error_2, error_3, error_4;
|
||||
int32 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_0 = data[i] ; total_error_0 += local_abs(error_0);
|
||||
error_1 = error_0 - last_error_0; total_error_1 += local_abs(error_1);
|
||||
error_2 = error_1 - last_error_1; total_error_2 += local_abs(error_2);
|
||||
error_3 = error_2 - last_error_2; total_error_3 += local_abs(error_3);
|
||||
error_4 = error_3 - last_error_3; total_error_4 += local_abs(error_4);
|
||||
|
||||
last_error_0 = error_0;
|
||||
last_error_1 = error_1;
|
||||
last_error_2 = error_2;
|
||||
last_error_3 = error_3;
|
||||
}
|
||||
|
||||
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|) */
|
||||
residual_bits_per_sample[0] = (real)((total_error_0 > 0 && data_len > 0) ? log(M_LN2 * total_error_0 / (real) data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[1] = (real)((total_error_1 > 0 && data_len > 0) ? log(M_LN2 * total_error_1 / (real) data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[2] = (real)((total_error_2 > 0 && data_len > 0) ? log(M_LN2 * total_error_2 / (real) data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[3] = (real)((total_error_3 > 0 && data_len > 0) ? log(M_LN2 * total_error_3 / (real) data_len) / M_LN2 : 0.0);
|
||||
residual_bits_per_sample[4] = (real)((total_error_4 > 0 && data_len > 0) ? log(M_LN2 * total_error_4 / (real) data_len) / M_LN2 : 0.0);
|
||||
|
||||
return order;
|
||||
}
|
||||
|
||||
void FLAC__fixed_compute_residual(const int32 data[], unsigned data_len, unsigned order, int32 residual[])
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
residual[i] = data[i];
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
residual[i] = data[i] - data[i-1];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
/* == data[i] - 2*data[i-1] + data[i-2] */
|
||||
residual[i] = data[i] - (data[i-1] << 1) + data[i-2];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
/* == data[i] - 3*data[i-1] + 3*data[i-2] - data[i-3] */
|
||||
residual[i] = data[i] - (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) - data[i-3];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
/* == data[i] - 4*data[i-1] + 6*data[i-2] - 4*data[i-3] + data[i-4] */
|
||||
residual[i] = data[i] - ((data[i-1]+data[i-3])<<2) + ((data[i-2]<<2) + (data[i-2]<<1)) + data[i-4];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__fixed_restore_signal(const int32 residual[], unsigned data_len, unsigned order, int32 data[])
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
switch(order) {
|
||||
case 0:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
data[i] = residual[i];
|
||||
}
|
||||
break;
|
||||
case 1:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
data[i] = residual[i] + data[i-1];
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
/* == residual[i] + 2*data[i-1] - data[i-2] */
|
||||
data[i] = residual[i] + (data[i-1]<<1) - data[i-2];
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
/* residual[i] + 3*data[i-1] - 3*data[i-2]) + data[i-3] */
|
||||
data[i] = residual[i] + (((data[i-1]-data[i-2])<<1) + (data[i-1]-data[i-2])) + data[i-3];
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
/* == residual[i] + 4*data[i-1] - 6*data[i-2] + 4*data[i-3] - data[i-4] */
|
||||
data[i] = residual[i] + ((data[i-1]+data[i-3])<<2) - ((data[i-2]<<2) + (data[i-2]<<1)) - data[i-4];
|
||||
}
|
||||
break;
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
}
|
66
src/libFLAC/format.c
Normal file
66
src/libFLAC/format.c
Normal file
@ -0,0 +1,66 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include "FLAC/format.h"
|
||||
|
||||
const unsigned FLAC__MAJOR_VERSION = 0;
|
||||
const unsigned FLAC__MINOR_VERSION = 2;
|
||||
|
||||
const byte FLAC__STREAM_SYNC_STRING[4] = { 'f','L','a','C' };
|
||||
const unsigned FLAC__STREAM_SYNC = 0x664C6143;
|
||||
const unsigned FLAC__STREAM_SYNC_LEN = 32; /* bits */;
|
||||
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_MIN_BLOCK_SIZE_LEN = 16; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_MAX_BLOCK_SIZE_LEN = 16; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_MIN_FRAME_SIZE_LEN = 24; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_MAX_FRAME_SIZE_LEN = 24; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_SAMPLE_RATE_LEN = 20; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_CHANNELS_LEN = 3; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_BITS_PER_SAMPLE_LEN = 5; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_TOTAL_SAMPLES_LEN = 36; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_ENCODING_LENGTH = 18; /* bytes */
|
||||
|
||||
const unsigned FLAC__STREAM_METADATA_IS_LAST_LEN = 1; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_TYPE_LEN = 7; /* bits */
|
||||
const unsigned FLAC__STREAM_METADATA_LENGTH_LEN = 24; /* bits */
|
||||
|
||||
const unsigned FLAC__FRAME_HEADER_SYNC = 0x1fe;
|
||||
const unsigned FLAC__FRAME_HEADER_SYNC_LEN = 9; /* bits */
|
||||
const unsigned FLAC__FRAME_HEADER_BLOCK_SIZE_LEN = 3; /* bits */
|
||||
const unsigned FLAC__FRAME_HEADER_SAMPLE_RATE_LEN = 4; /* bits */
|
||||
const unsigned FLAC__FRAME_HEADER_CHANNEL_ASSIGNMENT_LEN = 4; /* bits */
|
||||
const unsigned FLAC__FRAME_HEADER_BITS_PER_SAMPLE_LEN = 3; /* bits */
|
||||
const unsigned FLAC__FRAME_HEADER_ZERO_PAD_LEN = 1; /* bits */
|
||||
const unsigned FLAC__FRAME_HEADER_CRC8_LEN = 8; /* bits */
|
||||
|
||||
const unsigned FLAC__ENTROPY_CODING_METHOD_TYPE_LEN = 2; /* bits */
|
||||
const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_ORDER_LEN = 4; /* bits */
|
||||
const unsigned FLAC__ENTROPY_CODING_METHOD_PARTITIONED_RICE_PARAMETER_LEN = 4; /* bits */
|
||||
|
||||
const unsigned FLAC__SUBFRAME_HEADER_LPC_QLP_COEFF_PRECISION_LEN = 4; /* bits */
|
||||
const unsigned FLAC__SUBFRAME_HEADER_LPC_QLP_SHIFT_LEN = 5; /* bits */
|
||||
const unsigned FLAC__SUBFRAME_HEADER_LPC_RICE_PARAMETER_LEN = 4; /* bits */
|
||||
|
||||
const unsigned FLAC__SUBFRAME_HEADER_TYPE_CONSTANT = 0x00;
|
||||
const unsigned FLAC__SUBFRAME_HEADER_TYPE_VERBATIM = 0x02;
|
||||
const unsigned FLAC__SUBFRAME_HEADER_TYPE_FIXED = 0x10;
|
||||
const unsigned FLAC__SUBFRAME_HEADER_TYPE_LPC = 0x40;
|
||||
const unsigned FLAC__SUBFRAME_HEADER_TYPE_LEN = 8; /* bits */
|
29
src/libFLAC/include/private/all.h
Normal file
29
src/libFLAC/include/private/all.h
Normal file
@ -0,0 +1,29 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__ALL_H
|
||||
#define FLAC__PRIVATE__ALL_H
|
||||
|
||||
#include "bitbuffer.h"
|
||||
#include "crc.h"
|
||||
#include "encoder_framing.h"
|
||||
#include "fixed.h"
|
||||
#include "lpc.h"
|
||||
|
||||
#endif
|
64
src/libFLAC/include/private/bitbuffer.h
Normal file
64
src/libFLAC/include/private/bitbuffer.h
Normal file
@ -0,0 +1,64 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__BITBUFFER_H
|
||||
#define FLAC__PRIVATE__BITBUFFER_H
|
||||
|
||||
#include <stdio.h> /* for FILE */
|
||||
#include "FLAC/ordinals.h"
|
||||
|
||||
typedef struct {
|
||||
byte *buffer;
|
||||
unsigned capacity; /* in bytes */
|
||||
unsigned bytes, bits;
|
||||
unsigned total_bits; /* must always == 8*bytes+bits */
|
||||
unsigned consumed_bytes, consumed_bits;
|
||||
unsigned total_consumed_bits; /* must always == 8*consumed_bytes+consumed_bits */
|
||||
} FLAC__BitBuffer;
|
||||
|
||||
void FLAC__bitbuffer_init(FLAC__BitBuffer *bb);
|
||||
bool FLAC__bitbuffer_init_from(FLAC__BitBuffer *bb, const byte buffer[], unsigned bytes);
|
||||
bool FLAC__bitbuffer_concatenate_aligned(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src);
|
||||
void FLAC__bitbuffer_free(FLAC__BitBuffer *bb); /* does not 'free(buffer)' */
|
||||
bool FLAC__bitbuffer_clear(FLAC__BitBuffer *bb);
|
||||
bool FLAC__bitbuffer_clone(FLAC__BitBuffer *dest, const FLAC__BitBuffer *src);
|
||||
bool FLAC__bitbuffer_write_zeroes(FLAC__BitBuffer *bb, unsigned bits);
|
||||
bool FLAC__bitbuffer_write_raw_uint32(FLAC__BitBuffer *bb, uint32 val, unsigned bits);
|
||||
bool FLAC__bitbuffer_write_raw_int32(FLAC__BitBuffer *bb, int32 val, unsigned bits);
|
||||
bool FLAC__bitbuffer_write_raw_uint64(FLAC__BitBuffer *bb, uint64 val, unsigned bits);
|
||||
bool FLAC__bitbuffer_write_raw_int64(FLAC__BitBuffer *bb, int64 val, unsigned bits);
|
||||
bool FLAC__bitbuffer_write_rice_signed(FLAC__BitBuffer *bb, int val, unsigned parameter);
|
||||
bool FLAC__bitbuffer_write_rice_signed_guarded(FLAC__BitBuffer *bb, int val, unsigned parameter, unsigned max_bits, bool *overflow);
|
||||
bool FLAC__bitbuffer_write_utf8_uint32(FLAC__BitBuffer *bb, uint32 val);
|
||||
bool FLAC__bitbuffer_write_utf8_uint64(FLAC__BitBuffer *bb, uint64 val);
|
||||
bool FLAC__bitbuffer_zero_pad_to_byte_boundary(FLAC__BitBuffer *bb);
|
||||
bool FLAC__bitbuffer_peek_bit(FLAC__BitBuffer *bb, unsigned *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_bit(FLAC__BitBuffer *bb, unsigned *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_bit_to_uint32(FLAC__BitBuffer *bb, uint32 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_bit_to_uint64(FLAC__BitBuffer *bb, uint64 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_raw_uint32(FLAC__BitBuffer *bb, uint32 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_raw_int32(FLAC__BitBuffer *bb, int32 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_raw_uint64(FLAC__BitBuffer *bb, uint64 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_raw_int64(FLAC__BitBuffer *bb, int64 *val, unsigned bits, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_rice_signed(FLAC__BitBuffer *bb, int *val, unsigned parameter, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data);
|
||||
bool FLAC__bitbuffer_read_utf8_uint32(FLAC__BitBuffer *bb, uint32 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data, byte *raw, unsigned *rawlen);
|
||||
bool FLAC__bitbuffer_read_utf8_uint64(FLAC__BitBuffer *bb, uint64 *val, bool (*read_callback)(byte buffer[], unsigned *bytes, void *client_data), void *client_data, byte *raw, unsigned *rawlen);
|
||||
void FLAC__bitbuffer_dump(const FLAC__BitBuffer *bb, FILE *out);
|
||||
|
||||
#endif
|
30
src/libFLAC/include/private/crc.h
Normal file
30
src/libFLAC/include/private/crc.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__CRC_H
|
||||
#define FLAC__PRIVATE__CRC_H
|
||||
|
||||
#include "FLAC/ordinals.h"
|
||||
|
||||
/* 8 bit CRC generator, MSB shifted first
|
||||
** polynomial = x^8 + x^2 + x^1 + 1
|
||||
*/
|
||||
byte FLAC__crc8(const byte *data, const unsigned len);
|
||||
|
||||
#endif
|
33
src/libFLAC/include/private/encoder_framing.h
Normal file
33
src/libFLAC/include/private/encoder_framing.h
Normal file
@ -0,0 +1,33 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__ENCODER_FRAMING_H
|
||||
#define FLAC__PRIVATE__ENCODER_FRAMING_H
|
||||
|
||||
#include "FLAC/format.h"
|
||||
#include "bitbuffer.h"
|
||||
|
||||
bool FLAC__add_metadata_block(const FLAC__StreamMetaData *metadata, FLAC__BitBuffer *bb);
|
||||
bool FLAC__frame_add_header(const FLAC__FrameHeader *header, bool streamable_subset, bool is_last_block, FLAC__BitBuffer *bb);
|
||||
bool FLAC__subframe_add_constant(unsigned bits_per_sample, const FLAC__SubframeHeader *subframe, FLAC__BitBuffer *bb);
|
||||
bool FLAC__subframe_add_fixed(const int32 residual[], unsigned residual_samples, unsigned bits_per_sample, const FLAC__SubframeHeader *subframe, FLAC__BitBuffer *bb);
|
||||
bool FLAC__subframe_add_lpc(const int32 residual[], unsigned residual_samples, unsigned bits_per_sample, const FLAC__SubframeHeader *subframe, FLAC__BitBuffer *bb);
|
||||
bool FLAC__subframe_add_verbatim(const int32 signal[], unsigned samples, unsigned bits_per_sample, FLAC__BitBuffer *bb);
|
||||
|
||||
#endif
|
65
src/libFLAC/include/private/fixed.h
Normal file
65
src/libFLAC/include/private/fixed.h
Normal file
@ -0,0 +1,65 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__FIXED_H
|
||||
#define FLAC__PRIVATE__FIXED_H
|
||||
|
||||
#include "FLAC/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.
|
||||
*
|
||||
* IN data[0,data_len-1]
|
||||
* IN data_len
|
||||
* OUT residual_bits_per_sample[0,FLAC__MAX_FIXED_ORDER]
|
||||
*/
|
||||
unsigned FLAC__fixed_compute_best_predictor(const int32 data[], unsigned data_len, real residual_bits_per_sample[FLAC__MAX_FIXED_ORDER+1]);
|
||||
|
||||
/*
|
||||
* 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 int32 data[], unsigned data_len, unsigned order, 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 int32 residual[], unsigned data_len, unsigned order, int32 data[]);
|
||||
|
||||
#endif
|
142
src/libFLAC/include/private/lpc.h
Normal file
142
src/libFLAC/include/private/lpc.h
Normal file
@ -0,0 +1,142 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PRIVATE__LPC_H
|
||||
#define FLAC__PRIVATE__LPC_H
|
||||
|
||||
#include "FLAC/ordinals.h"
|
||||
|
||||
#define FLAC__MAX_LPC_ORDER (32u)
|
||||
|
||||
/*
|
||||
* 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 real data[], unsigned data_len, unsigned lag, real autoc[]);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
* 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 real autoc[], unsigned max_order, real lp_coeff[][FLAC__MAX_LPC_ORDER], real error[]);
|
||||
|
||||
/*
|
||||
* FLAC__lpc_quantize_coefficients()
|
||||
* --------------------------------------------------------------------
|
||||
* Quantizes the LP coefficients. NOTE: precision + bits_per_sample
|
||||
* must be less than 32 (sizeof(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
|
||||
* IN bits_per_sample > 0 bits per sample of the originial signal
|
||||
* OUT qlp_coeff[0,order-1] quantized coefficients
|
||||
* OUT bits # of bits to shift right to get approximated
|
||||
* LP coefficients. NOTE: could be negative,
|
||||
* but |*bits| will always be <= precision
|
||||
* RETURN 0 => quantization OK
|
||||
* 1 => coefficients vary too much to quantize to the desired
|
||||
* precision. 'bits' is unset
|
||||
* 2 => coefficients are all zero, which is bad. 'bits' is unset
|
||||
*/
|
||||
int FLAC__lpc_quantize_coefficients(const real lp_coeff[], unsigned order, unsigned precision, unsigned bits_per_sample, int32 qlp_coeff[], int *bits);
|
||||
|
||||
/*
|
||||
* 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 int32 data[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 residual[]);
|
||||
|
||||
/*
|
||||
* 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 int32 residual[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 data[]);
|
||||
|
||||
/*
|
||||
* 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
|
||||
*/
|
||||
real FLAC__lpc_compute_expected_bits_per_residual_sample(real lpc_error, unsigned total_samples);
|
||||
|
||||
/*
|
||||
* 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 bits_per_signal_sample # of bits per sample in the original signal
|
||||
* RETURN [1,max_order] best order
|
||||
*/
|
||||
unsigned FLAC__lpc_compute_best_order(const real lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample);
|
||||
|
||||
#endif
|
28
src/libFLAC/include/protected/stream_decoder.h
Normal file
28
src/libFLAC/include/protected/stream_decoder.h
Normal file
@ -0,0 +1,28 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__PROTECTED__STREAM_DECODER_H
|
||||
#define FLAC__PROTECTED__STREAM_DECODER_H
|
||||
|
||||
#include "FLAC/stream_decoder.h"
|
||||
|
||||
/* only useful to the file_decoder */
|
||||
unsigned FLAC__stream_decoder_input_bytes_unconsumed(FLAC__StreamDecoder *decoder);
|
||||
|
||||
#endif
|
238
src/libFLAC/lpc.c
Normal file
238
src/libFLAC/lpc.c
Normal file
@ -0,0 +1,238 @@
|
||||
/* libFLAC - Free Lossless Audio Coder library
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 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
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||
* Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include "FLAC/format.h"
|
||||
#include "private/lpc.h"
|
||||
|
||||
#ifndef M_LN2
|
||||
/* math.h in VC++ doesn't seem to have this (how Microsoft is that?) */
|
||||
#define M_LN2 0.69314718055994530942
|
||||
#endif
|
||||
|
||||
void FLAC__lpc_compute_autocorrelation(const real data[], unsigned data_len, unsigned lag, real autoc[])
|
||||
{
|
||||
real d;
|
||||
unsigned i;
|
||||
|
||||
assert(lag > 0);
|
||||
assert(lag <= data_len);
|
||||
|
||||
while(lag--) {
|
||||
for(i = lag, d = 0.0; i < data_len; i++)
|
||||
d += data[i] * data[i - lag];
|
||||
autoc[lag] = d;
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC__lpc_compute_lp_coefficients(const real autoc[], unsigned max_order, real lp_coeff[][FLAC__MAX_LPC_ORDER], real error[])
|
||||
{
|
||||
unsigned i, j;
|
||||
real r, err, ref[FLAC__MAX_LPC_ORDER], lpc[FLAC__MAX_LPC_ORDER];
|
||||
|
||||
assert(0 < max_order);
|
||||
assert(max_order <= FLAC__MAX_LPC_ORDER);
|
||||
assert(autoc[0] != 0.0);
|
||||
|
||||
err = autoc[0];
|
||||
|
||||
for(i = 0; i < max_order; i++) {
|
||||
/* Sum up this iteration's reflection coefficient. */
|
||||
r =- autoc[i+1];
|
||||
for(j = 0; j < i; j++)
|
||||
r -= lpc[j] * autoc[i-j];
|
||||
ref[i] = (r/=err);
|
||||
|
||||
/* Update LPC coefficients and total error. */
|
||||
lpc[i]=r;
|
||||
for(j = 0; j < (i>>1); j++) {
|
||||
real tmp = lpc[j];
|
||||
lpc[j] += r * lpc[i-1-j];
|
||||
lpc[i-1-j] += r * tmp;
|
||||
}
|
||||
if(i & 1)
|
||||
lpc[j] += lpc[j] * r;
|
||||
|
||||
err *= (1.0 - r * r);
|
||||
|
||||
/* save this order */
|
||||
for(j = 0; j <= i; j++)
|
||||
lp_coeff[i][j] = -lpc[j]; /* N.B. why do we have to negate here? */
|
||||
error[i] = err;
|
||||
}
|
||||
}
|
||||
|
||||
int FLAC__lpc_quantize_coefficients(const real lp_coeff[], unsigned order, unsigned precision, unsigned bits_per_sample, int32 qlp_coeff[], int *bits)
|
||||
{
|
||||
unsigned i;
|
||||
real d, rprecision = (real)precision, maxlog = -1e99, minlog = 1e99;
|
||||
|
||||
assert(bits_per_sample > 0);
|
||||
assert(bits_per_sample <= sizeof(int32)*8);
|
||||
assert(precision >= FLAC__MIN_QLP_COEFF_PRECISION);
|
||||
assert(precision + bits_per_sample < sizeof(int32)*8);
|
||||
#ifdef NDEBUG
|
||||
(void)bits_per_sample; /* silence compiler warning about unused parameter */
|
||||
#endif
|
||||
|
||||
for(i = 0; i < order; i++) {
|
||||
if(lp_coeff[i] == 0.0)
|
||||
continue;
|
||||
d = log(fabs(lp_coeff[i])) / M_LN2;
|
||||
if(d > maxlog)
|
||||
maxlog = d;
|
||||
if(d < minlog)
|
||||
minlog = d;
|
||||
}
|
||||
if(maxlog < minlog)
|
||||
return 2;
|
||||
else if(maxlog - minlog >= (real)(precision+1))
|
||||
return 1;
|
||||
else if((rprecision-1.0) - maxlog >= (real)(precision+1))
|
||||
rprecision = (real)precision + maxlog + 1.0;
|
||||
|
||||
*bits = (int)floor((rprecision-1.0) - maxlog); /* '-1' because bits can be negative and the sign bit costs 1 bit */
|
||||
if(*bits > (int)precision || *bits <= -(int)precision) {
|
||||
fprintf(stderr, "@@@ FLAC__lpc_quantize_coefficients(): ERROR: *bits=%d, maxlog=%f, minlog=%f, precision=%u, rprecision=%f\n", *bits, maxlog, minlog, precision, rprecision);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if(*bits != 0) { /* just to avoid wasting time... */
|
||||
for(i = 0; i < order; i++)
|
||||
qlp_coeff[i] = (int32)floor(lp_coeff[i] * (real)(1 << *bits));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FLAC__lpc_compute_residual_from_qlp_coefficients(const int32 data[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 residual[])
|
||||
{
|
||||
#ifdef FLAC_OVERFLOW_DETECT
|
||||
int64 sumo;
|
||||
#endif
|
||||
unsigned i, j;
|
||||
int32 sum;
|
||||
const int32 *history;
|
||||
|
||||
#ifdef FLAC_OVERFLOW_DETECT_VERBOSE
|
||||
fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization);
|
||||
for(i=0;i<order;i++)
|
||||
fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]);
|
||||
fprintf(stderr,"\n");
|
||||
#endif
|
||||
assert(order > 0);
|
||||
|
||||
for(i = 0; i < data_len; i++) {
|
||||
#ifdef FLAC_OVERFLOW_DETECT
|
||||
sumo = 0;
|
||||
#endif
|
||||
sum = 0;
|
||||
history = data;
|
||||
for(j = 0; j < order; j++) {
|
||||
sum += qlp_coeff[j] * (*(--history));
|
||||
#ifdef FLAC_OVERFLOW_DETECT
|
||||
sumo += (int64)qlp_coeff[j] * (int64)(*history);
|
||||
if(sumo > 2147483647ll || sumo < -2147483648ll)
|
||||
fprintf(stderr,"FLAC__lpc_compute_residual_from_qlp_coefficients: OVERFLOW, sumo=%lld\n",sumo);
|
||||
#endif
|
||||
}
|
||||
*(residual++) = *(data++) - (sum >> lp_quantization);
|
||||
}
|
||||
|
||||
/* Here's a slightly slower but clearer version:
|
||||
for(i = 0; i < data_len; i++) {
|
||||
sum = 0;
|
||||
history = &(data[i]);
|
||||
for(j = 0; j < order; j++)
|
||||
sum += qlp_coeff[j] * (*(--history));
|
||||
residual[i] = data[i] - (sum >> lp_quantization);
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
void FLAC__lpc_restore_signal(const int32 residual[], unsigned data_len, const int32 qlp_coeff[], unsigned order, int lp_quantization, int32 data[])
|
||||
{
|
||||
#ifdef FLAC_OVERFLOW_DETECT
|
||||
int64 sumo;
|
||||
#endif
|
||||
unsigned i, j;
|
||||
int32 sum, *history;
|
||||
|
||||
#ifdef FLAC_OVERFLOW_DETECT_VERBOSE
|
||||
fprintf(stderr,"FLAC__lpc_restore_signal: data_len=%d, order=%u, lpq=%d",data_len,order,lp_quantization);
|
||||
for(i=0;i<order;i++)
|
||||
fprintf(stderr,", q[%u]=%d",i,qlp_coeff[i]);
|
||||
fprintf(stderr,"\n");
|
||||
#endif
|
||||
assert(order > 0);
|
||||
|
||||
for(i = 0; i < data_len; i++) {
|
||||
#ifdef FLAC_OVERFLOW_DETECT
|
||||
sumo = 0;
|
||||
#endif
|
||||
sum = 0;
|
||||
history = data+i;
|
||||
for(j = 0; j < order; j++) {
|
||||
sum += qlp_coeff[j] * (*(--history));
|
||||
#ifdef FLAC_OVERFLOW_DETECT
|
||||
sumo += (int64)qlp_coeff[j] * (int64)(*history);
|
||||
if(sumo > 2147483647ll || sumo < -2147483648ll)
|
||||
fprintf(stderr,"FLAC__lpc_restore_signal: OVERFLOW, sumo=%lld\n",sumo);
|
||||
#endif
|
||||
}
|
||||
data[i] = residual[i] + (sum >> lp_quantization);
|
||||
}
|
||||
}
|
||||
|
||||
real FLAC__lpc_compute_expected_bits_per_residual_sample(real lpc_error, unsigned total_samples)
|
||||
{
|
||||
real escale;
|
||||
|
||||
assert(lpc_error >= 0.0); /* the error can never be negative */
|
||||
assert(total_samples > 0);
|
||||
|
||||
escale = 0.5 * M_LN2 * M_LN2 / (real)total_samples;
|
||||
|
||||
if(lpc_error > 0.0)
|
||||
return 0.5 * log(escale * lpc_error) / M_LN2;
|
||||
else
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
unsigned FLAC__lpc_compute_best_order(const real lpc_error[], unsigned max_order, unsigned total_samples, unsigned bits_per_signal_sample)
|
||||
{
|
||||
unsigned order, best_order;
|
||||
real best_bits, tmp_bits;
|
||||
|
||||
assert(max_order > 0);
|
||||
|
||||
best_order = 0;
|
||||
best_bits = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[0], total_samples) * (real)total_samples;
|
||||
|
||||
for(order = 1; order < max_order; order++) {
|
||||
tmp_bits = FLAC__lpc_compute_expected_bits_per_residual_sample(lpc_error[order], total_samples) * (real)(total_samples - order) + (real)(order * bits_per_signal_sample);
|
||||
if(tmp_bits < best_bits) {
|
||||
best_order = order;
|
||||
best_bits = tmp_bits;
|
||||
}
|
||||
}
|
||||
|
||||
return best_order+1; /* +1 since index of lpc_error[] is order-1 */
|
||||
}
|
1114
src/libFLAC/stream_decoder.c
Normal file
1114
src/libFLAC/stream_decoder.c
Normal file
File diff suppressed because it is too large
Load Diff
23
src/plugin_winamp2/Makefile.vc
Normal file
23
src/plugin_winamp2/Makefile.vc
Normal file
@ -0,0 +1,23 @@
|
||||
!include <win32.mak>
|
||||
|
||||
!IFNDEF NODEBUG
|
||||
.c.obj:
|
||||
$(cc) /GX $(cdebug) $(cflags) $(cvarsdll) /I "..\..\include" /I ".\include" -DSTRICT -YX /Od /D "_DEBUG" $<
|
||||
!else
|
||||
.c.obj:
|
||||
$(cc) $(cdebug) $(cflags) $(cvarsdll) /I "..\..\include" /I ".\include" -DSTRICT -YX -DNODEBUG $<
|
||||
!endif
|
||||
|
||||
C_FILES= \
|
||||
in_flac.c
|
||||
|
||||
OBJS= $(C_FILES:.c=.obj)
|
||||
|
||||
all: in_flac.dll
|
||||
|
||||
in_flac.dll: $(OBJS)
|
||||
link.exe /dll /libpath:"..\..\obj\lib" -out:../../obj/bin/$*.dll $(OBJS) libFLAC.lib user32.lib kernel32.lib
|
||||
|
||||
clean:
|
||||
-del *.obj *.pch
|
||||
-del ..\..\obj\bin\in_flac.*
|
104
src/plugin_winamp2/in2.h
Normal file
104
src/plugin_winamp2/in2.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* Standard Winamp input-plugin header
|
||||
*/
|
||||
|
||||
#include "out.h"
|
||||
|
||||
// note: exported symbol is now winampGetInModule2.
|
||||
|
||||
#define IN_VER 0x100
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version; // module type (IN_VER)
|
||||
char *description; // description of module, with version string
|
||||
|
||||
HWND hMainWindow; // winamp's main window (filled in by winamp)
|
||||
HINSTANCE hDllInstance; // DLL instance handle (Also filled in by winamp)
|
||||
|
||||
char *FileExtensions; // "mp3\0Layer 3 MPEG\0mp2\0Layer 2 MPEG\0mpg\0Layer 1 MPEG\0"
|
||||
// May be altered from Config, so the user can select what they want
|
||||
|
||||
int is_seekable; // is this stream seekable?
|
||||
int UsesOutputPlug; // does this plug-in use the output plug-ins? (musn't ever change, ever :)
|
||||
|
||||
void (*Config)(HWND hwndParent); // configuration dialog
|
||||
void (*About)(HWND hwndParent); // about dialog
|
||||
|
||||
void (*Init)(); // called at program init
|
||||
void (*Quit)(); // called at program quit
|
||||
|
||||
void (*GetFileInfo)(char *file, char *title, int *length_in_ms); // if file == NULL, current playing is used
|
||||
int (*InfoBox)(char *file, HWND hwndParent);
|
||||
|
||||
int (*IsOurFile)(char *fn); // called before extension checks, to allow detection of mms://, etc
|
||||
// playback stuff
|
||||
int (*Play)(char *fn); // return zero on success, -1 on file-not-found, some other value on other (stopping winamp) error
|
||||
void (*Pause)(); // pause stream
|
||||
void (*UnPause)(); // unpause stream
|
||||
int (*IsPaused)(); // ispaused? return 1 if paused, 0 if not
|
||||
void (*Stop)(); // stop (unload) stream
|
||||
|
||||
// time stuff
|
||||
int (*GetLength)(); // get length in ms
|
||||
int (*GetOutputTime)(); // returns current output time in ms. (usually returns outMod->GetOutputTime()
|
||||
void (*SetOutputTime)(int time_in_ms); // seeks to point in stream (in ms). Usually you signal yoru thread to seek, which seeks and calls outMod->Flush()..
|
||||
|
||||
// volume stuff
|
||||
void (*SetVolume)(int volume); // from 0 to 255.. usually just call outMod->SetVolume
|
||||
void (*SetPan)(int pan); // from -127 to 127.. usually just call outMod->SetPan
|
||||
|
||||
// in-window builtin vis stuff
|
||||
|
||||
void (*SAVSAInit)(int maxlatency_in_ms, int srate); // call once in Play(). maxlatency_in_ms should be the value returned from outMod->Open()
|
||||
// call after opening audio device with max latency in ms and samplerate
|
||||
void (*SAVSADeInit)(); // call in Stop()
|
||||
|
||||
|
||||
// simple vis supplying mode
|
||||
void (*SAAddPCMData)(void *PCMData, int nch, int bps, int timestamp);
|
||||
// sets the spec data directly from PCM data
|
||||
// quick and easy way to get vis working :)
|
||||
// needs at least 576 samples :)
|
||||
|
||||
// advanced vis supplying mode, only use if you're cool. Use SAAddPCMData for most stuff.
|
||||
int (*SAGetMode)(); // gets csa (the current type (4=ws,2=osc,1=spec))
|
||||
// use when calling SAAdd()
|
||||
void (*SAAdd)(void *data, int timestamp, int csa); // sets the spec data, filled in by winamp
|
||||
|
||||
|
||||
// vis stuff (plug-in)
|
||||
// simple vis supplying mode
|
||||
void (*VSAAddPCMData)(void *PCMData, int nch, int bps, int timestamp); // sets the vis data directly from PCM data
|
||||
// quick and easy way to get vis working :)
|
||||
// needs at least 576 samples :)
|
||||
|
||||
// advanced vis supplying mode, only use if you're cool. Use VSAAddPCMData for most stuff.
|
||||
int (*VSAGetMode)(int *specNch, int *waveNch); // use to figure out what to give to VSAAdd
|
||||
void (*VSAAdd)(void *data, int timestamp); // filled in by winamp, called by plug-in
|
||||
|
||||
|
||||
// call this in Play() to tell the vis plug-ins the current output params.
|
||||
void (*VSASetInfo)(int nch, int srate);
|
||||
|
||||
|
||||
// dsp plug-in processing:
|
||||
// (filled in by winamp, called by input plug)
|
||||
|
||||
// returns 1 if active (which means that the number of samples returned by dsp_dosamples
|
||||
// could be greater than went in.. Use it to estimate if you'll have enough room in the
|
||||
// output buffer
|
||||
int (*dsp_isactive)();
|
||||
|
||||
// returns number of samples to output. This can be as much as twice numsamples.
|
||||
// be sure to allocate enough buffer for samples, then.
|
||||
int (*dsp_dosamples)(short int *samples, int numsamples, int bps, int nch, int srate);
|
||||
|
||||
|
||||
// eq stuff
|
||||
void (*EQSet)(int on, char data[10], int preamp); // 0-64 each, 31 is +0, 0 is +12, 63 is -12. Do nothing to ignore.
|
||||
|
||||
// info setting (filled in by winamp)
|
||||
void (*SetInfo)(int bitrate, int srate, int stereo, int synched); // if -1, changes ignored? :)
|
||||
|
||||
Out_Module *outMod; // filled in by winamp, optionally used :)
|
||||
} In_Module;
|
425
src/plugin_winamp2/in_flac.c
Normal file
425
src/plugin_winamp2/in_flac.c
Normal file
@ -0,0 +1,425 @@
|
||||
/* in_flac - Winamp FLAC input plugin
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <windows.h>
|
||||
#include <mmreg.h>
|
||||
#include <msacm.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "in2.h"
|
||||
#include "FLAC/all.h"
|
||||
|
||||
BOOL WINAPI _DllMainCRTStartup(HANDLE hInst, ULONG ul_reason_for_call, LPVOID lpReserved)
|
||||
{
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/* post this to the main window at end of file (after playback as stopped) */
|
||||
#define WM_WA_MPEG_EOF WM_USER+2
|
||||
|
||||
typedef struct {
|
||||
bool abort_flag;
|
||||
unsigned total_samples;
|
||||
unsigned bits_per_sample;
|
||||
unsigned channels;
|
||||
unsigned sample_rate;
|
||||
unsigned length_in_ms;
|
||||
} stream_info_struct;
|
||||
|
||||
static bool stream_init(const char *infile);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
|
||||
static void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
static void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
|
||||
In_Module mod; /* the output module (declared near the bottom of this file) */
|
||||
char lastfn[MAX_PATH]; /* currently playing file (used for getting info on the current file) */
|
||||
int decode_pos_ms; /* current decoding position, in milliseconds */
|
||||
int paused; /* are we paused? */
|
||||
int seek_needed; /* if != -1, it is the point that the decode thread should seek to, in ms. */
|
||||
int16 reservoir[FLAC__MAX_BLOCK_SIZE * 2]; /* 2 for max channels */
|
||||
char sample_buffer[576 * 2 * (16/8) * 2]; /* 2 for max channels, (16/8) for max bytes per sample, and 2 for who knows what */
|
||||
unsigned samples_in_reservoir;
|
||||
static stream_info_struct stream_info;
|
||||
static FLAC__FileDecoder *decoder;
|
||||
|
||||
int killDecodeThread=0; /* the kill switch for the decode thread */
|
||||
HANDLE thread_handle=INVALID_HANDLE_VALUE; /* the handle to the decode thread */
|
||||
|
||||
DWORD WINAPI __stdcall DecodeThread(void *b); /* the decode thread procedure */
|
||||
|
||||
void config(HWND hwndParent)
|
||||
{
|
||||
MessageBox(hwndParent, "No configuration.", "Configuration", MB_OK);
|
||||
/* if we had a configuration we'd want to write it here :) */
|
||||
}
|
||||
void about(HWND hwndParent)
|
||||
{
|
||||
MessageBox(hwndParent,"Winamp FLAC Plugin v0.2, by Josh Coalson\nSee http://flac.sourceforge.net/","About FLAC Plugin",MB_OK);
|
||||
}
|
||||
|
||||
void init()
|
||||
{
|
||||
decoder = FLAC__file_decoder_get_new_instance();
|
||||
}
|
||||
|
||||
void quit()
|
||||
{
|
||||
if(decoder)
|
||||
FLAC__file_decoder_free_instance(decoder);
|
||||
}
|
||||
|
||||
int isourfile(char *fn) { return 0; }
|
||||
/* used for detecting URL streams.. unused here. strncmp(fn,"http://",7) to detect HTTP streams, etc */
|
||||
|
||||
int play(char *fn)
|
||||
{
|
||||
int maxlatency;
|
||||
int thread_id;
|
||||
HANDLE input_file=INVALID_HANDLE_VALUE;
|
||||
|
||||
if(0 == decoder) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
input_file = CreateFile(fn,GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
|
||||
if (input_file == INVALID_HANDLE_VALUE) {
|
||||
return 1;
|
||||
}
|
||||
CloseHandle(input_file);
|
||||
|
||||
if(!stream_init(fn)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
strcpy(lastfn,fn);
|
||||
paused=0;
|
||||
decode_pos_ms=0;
|
||||
seek_needed=-1;
|
||||
samples_in_reservoir = 0;
|
||||
|
||||
maxlatency = mod.outMod->Open(stream_info.sample_rate, stream_info.channels, stream_info.bits_per_sample, -1,-1);
|
||||
if (maxlatency < 0) { /* error opening device */
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* dividing by 1000 for the first parameter of setinfo makes it */
|
||||
/* display 'H'... for hundred.. i.e. 14H Kbps. */
|
||||
mod.SetInfo((stream_info.sample_rate*stream_info.bits_per_sample*stream_info.channels)/1000,stream_info.sample_rate/1000,stream_info.channels,1);
|
||||
|
||||
/* initialize vis stuff */
|
||||
mod.SAVSAInit(maxlatency,stream_info.sample_rate);
|
||||
mod.VSASetInfo(stream_info.sample_rate,stream_info.channels);
|
||||
|
||||
mod.outMod->SetVolume(-666); /* set the output plug-ins default volume */
|
||||
|
||||
killDecodeThread=0;
|
||||
thread_handle = (HANDLE) CreateThread(NULL,0,(LPTHREAD_START_ROUTINE) DecodeThread,(void *) &killDecodeThread,0,&thread_id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void pause()
|
||||
{
|
||||
paused=1;
|
||||
mod.outMod->Pause(1);
|
||||
}
|
||||
|
||||
void unpause()
|
||||
{
|
||||
paused=0;
|
||||
mod.outMod->Pause(0);
|
||||
}
|
||||
int ispaused()
|
||||
{
|
||||
return paused;
|
||||
}
|
||||
|
||||
void stop()
|
||||
{
|
||||
if (thread_handle != INVALID_HANDLE_VALUE) {
|
||||
killDecodeThread=1;
|
||||
if (WaitForSingleObject(thread_handle,INFINITE) == WAIT_TIMEOUT) {
|
||||
MessageBox(mod.hMainWindow,"error asking thread to die!\n","error killing decode thread",0);
|
||||
TerminateThread(thread_handle,0);
|
||||
}
|
||||
CloseHandle(thread_handle);
|
||||
thread_handle = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
if(decoder) {
|
||||
if(decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder);
|
||||
}
|
||||
|
||||
mod.outMod->Close();
|
||||
|
||||
mod.SAVSADeInit();
|
||||
}
|
||||
|
||||
int getlength()
|
||||
{
|
||||
return (int)stream_info.length_in_ms;
|
||||
}
|
||||
|
||||
int getoutputtime()
|
||||
{
|
||||
return decode_pos_ms+(mod.outMod->GetOutputTime()-mod.outMod->GetWrittenTime());
|
||||
}
|
||||
|
||||
void setoutputtime(int time_in_ms)
|
||||
{
|
||||
seek_needed=time_in_ms;
|
||||
}
|
||||
|
||||
void setvolume(int volume) { mod.outMod->SetVolume(volume); }
|
||||
void setpan(int pan) { mod.outMod->SetPan(pan); }
|
||||
|
||||
int infoDlg(char *fn, HWND hwnd)
|
||||
{
|
||||
/* TODO: implement info dialog. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
void getfileinfo(char *filename, char *title, int *length_in_ms)
|
||||
{
|
||||
if (!filename || !*filename) { /* currently playing file */
|
||||
if (length_in_ms)
|
||||
*length_in_ms=getlength();
|
||||
if (title) {
|
||||
char *p=lastfn+strlen(lastfn);
|
||||
while (*p != '\\' && p >= lastfn) p--;
|
||||
strcpy(title,++p);
|
||||
}
|
||||
}
|
||||
else { /* some other file */
|
||||
if (length_in_ms) {
|
||||
FLAC__FileDecoder *tmp_decoder = FLAC__file_decoder_get_new_instance();
|
||||
stream_info_struct tmp_stream_info;
|
||||
tmp_stream_info.abort_flag = false;
|
||||
if(FLAC__file_decoder_init(tmp_decoder, filename, write_callback, metadata_callback, error_callback, &tmp_stream_info) != FLAC__FILE_DECODER_OK)
|
||||
return;
|
||||
if(!FLAC__file_decoder_process_metadata(tmp_decoder))
|
||||
return;
|
||||
|
||||
*length_in_ms = (int)tmp_stream_info.length_in_ms;
|
||||
|
||||
if(tmp_decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(tmp_decoder);
|
||||
FLAC__file_decoder_free_instance(tmp_decoder);
|
||||
}
|
||||
if (title) {
|
||||
char *p=filename+strlen(filename);
|
||||
while (*p != '\\' && p >= filename) p--;
|
||||
strcpy(title,++p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void eq_set(int on, char data[10], int preamp)
|
||||
{
|
||||
}
|
||||
|
||||
DWORD WINAPI __stdcall DecodeThread(void *b)
|
||||
{
|
||||
int done=0;
|
||||
|
||||
while (! *((int *)b) ) {
|
||||
unsigned channels = stream_info.channels;
|
||||
unsigned bits_per_sample = stream_info.bits_per_sample;
|
||||
unsigned bytes_per_sample = (bits_per_sample+7)/8;
|
||||
unsigned sample_rate = stream_info.sample_rate;
|
||||
if (seek_needed != -1) {
|
||||
const double distance = (double)seek_needed / (double)getlength();
|
||||
unsigned target_sample = (unsigned)(distance * (double)stream_info.total_samples);
|
||||
if(FLAC__file_decoder_seek_absolute(decoder, (uint64)target_sample)) {
|
||||
decode_pos_ms = (int)(distance * (double)getlength());
|
||||
seek_needed=-1;
|
||||
done=0;
|
||||
mod.outMod->Flush(decode_pos_ms);
|
||||
}
|
||||
}
|
||||
if (done) {
|
||||
if (!mod.outMod->IsPlaying()) {
|
||||
PostMessage(mod.hMainWindow,WM_WA_MPEG_EOF,0,0);
|
||||
return 0;
|
||||
}
|
||||
Sleep(10);
|
||||
}
|
||||
else if (mod.outMod->CanWrite() >= ((int)(576*channels*bytes_per_sample) << (mod.dsp_isactive()?1:0))) {
|
||||
while(samples_in_reservoir < 576) {
|
||||
if(decoder->state == FLAC__FILE_DECODER_END_OF_FILE) {
|
||||
done = 1;
|
||||
break;
|
||||
}
|
||||
else if(!FLAC__file_decoder_process_one_frame(decoder))
|
||||
break;
|
||||
}
|
||||
|
||||
if (samples_in_reservoir == 0) {
|
||||
done=1;
|
||||
}
|
||||
else {
|
||||
unsigned i, n = min(samples_in_reservoir, 576), delta;
|
||||
int l;
|
||||
signed short *ssbuffer = (signed short *)sample_buffer;
|
||||
|
||||
for(i = 0; i < n*channels; i++)
|
||||
ssbuffer[i] = reservoir[i];
|
||||
delta = i;
|
||||
for( ; i < samples_in_reservoir*channels; i++)
|
||||
reservoir[i-delta] = reservoir[i];
|
||||
samples_in_reservoir -= n;
|
||||
l = n * channels * bytes_per_sample;
|
||||
|
||||
mod.SAAddPCMData((char *)sample_buffer,channels,bits_per_sample,decode_pos_ms);
|
||||
mod.VSAAddPCMData((char *)sample_buffer,channels,bits_per_sample,decode_pos_ms);
|
||||
decode_pos_ms+=(576*1000)/sample_rate;
|
||||
if (mod.dsp_isactive())
|
||||
l=mod.dsp_dosamples((short *)sample_buffer,n/channels/bytes_per_sample,bits_per_sample,channels,sample_rate) * (channels*bytes_per_sample);
|
||||
mod.outMod->Write(sample_buffer,l);
|
||||
}
|
||||
}
|
||||
else Sleep(20);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
In_Module mod =
|
||||
{
|
||||
IN_VER,
|
||||
"Reference FLAC Player v0.0"
|
||||
#ifdef __alpha
|
||||
"(AXP)"
|
||||
#else
|
||||
"(x86)"
|
||||
#endif
|
||||
,
|
||||
0, /* hMainWindow */
|
||||
0, /* hDllInstance */
|
||||
"FLAC\0FLAC Audio File (*.FLAC)\0"
|
||||
,
|
||||
1, /* is_seekable */
|
||||
1, /* uses output */
|
||||
config,
|
||||
about,
|
||||
init,
|
||||
quit,
|
||||
getfileinfo,
|
||||
infoDlg,
|
||||
isourfile,
|
||||
play,
|
||||
pause,
|
||||
unpause,
|
||||
ispaused,
|
||||
stop,
|
||||
|
||||
getlength,
|
||||
getoutputtime,
|
||||
setoutputtime,
|
||||
|
||||
setvolume,
|
||||
setpan,
|
||||
|
||||
0,0,0,0,0,0,0,0,0, /* vis stuff */
|
||||
|
||||
|
||||
0,0, /* dsp */
|
||||
|
||||
eq_set,
|
||||
|
||||
NULL, /* setinfo */
|
||||
|
||||
0 /* out_mod */
|
||||
|
||||
};
|
||||
|
||||
__declspec( dllexport ) In_Module * winampGetInModule2()
|
||||
{
|
||||
return &mod;
|
||||
}
|
||||
|
||||
|
||||
/***********************************************************************
|
||||
* local routines
|
||||
**********************************************************************/
|
||||
bool stream_init(const char *infile)
|
||||
{
|
||||
if(FLAC__file_decoder_init(decoder, infile, write_callback, metadata_callback, error_callback, &stream_info) != FLAC__FILE_DECODER_OK) {
|
||||
MessageBox(mod.hMainWindow,"ERROR initializing decoder, state = %d\n","ERROR initializing decoder",0);
|
||||
return false;
|
||||
}
|
||||
|
||||
stream_info.abort_flag = false;
|
||||
if(!FLAC__file_decoder_process_metadata(decoder)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_callback(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
|
||||
{
|
||||
stream_info_struct *stream_info = (stream_info_struct *)client_data;
|
||||
unsigned bps = stream_info->bits_per_sample, channels = stream_info->channels;
|
||||
unsigned wide_samples = header->blocksize, wide_sample, sample, channel, offset;
|
||||
|
||||
(void)decoder;
|
||||
|
||||
if(stream_info->abort_flag)
|
||||
return FLAC__STREAM_DECODER_WRITE_ABORT;
|
||||
|
||||
offset = samples_in_reservoir * channels;
|
||||
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
reservoir[offset+sample] = (int16)buffer[channel][wide_sample];
|
||||
|
||||
samples_in_reservoir += wide_samples;
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
|
||||
}
|
||||
|
||||
void metadata_callback(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
|
||||
{
|
||||
stream_info_struct *stream_info = (stream_info_struct *)client_data;
|
||||
(void)decoder;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_ENCODING) {
|
||||
assert(metadata->data.encoding.total_samples < 0x100000000); /* this plugin can only handle < 4 gigasamples */
|
||||
stream_info->total_samples = (unsigned)(metadata->data.encoding.total_samples&0xffffffff);
|
||||
stream_info->bits_per_sample = metadata->data.encoding.bits_per_sample;
|
||||
stream_info->channels = metadata->data.encoding.channels;
|
||||
stream_info->sample_rate = metadata->data.encoding.sample_rate;
|
||||
|
||||
if(stream_info->bits_per_sample != 16) {
|
||||
MessageBox(mod.hMainWindow,"ERROR: plugin can only handle 16-bit samples\n","ERROR: plugin can only handle 16-bit samples",0);
|
||||
stream_info->abort_flag = true;
|
||||
return;
|
||||
}
|
||||
stream_info->length_in_ms = stream_info->total_samples * 10 / (stream_info->sample_rate / 100);
|
||||
}
|
||||
}
|
||||
|
||||
void error_callback(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
stream_info_struct *stream_info = (stream_info_struct *)client_data;
|
||||
(void)decoder;
|
||||
if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
|
||||
stream_info->abort_flag = true;
|
||||
}
|
55
src/plugin_winamp2/out.h
Normal file
55
src/plugin_winamp2/out.h
Normal file
@ -0,0 +1,55 @@
|
||||
/* Standard Winamp output-plugin header
|
||||
*/
|
||||
|
||||
#define OUT_VER 0x10
|
||||
|
||||
typedef struct
|
||||
{
|
||||
int version; // module version (OUT_VER)
|
||||
char *description; // description of module, with version string
|
||||
int id; // module id. each input module gets its own. non-nullsoft modules should
|
||||
// be >= 65536.
|
||||
|
||||
HWND hMainWindow; // winamp's main window (filled in by winamp)
|
||||
HINSTANCE hDllInstance; // DLL instance handle (filled in by winamp)
|
||||
|
||||
void (*Config)(HWND hwndParent); // configuration dialog
|
||||
void (*About)(HWND hwndParent); // about dialog
|
||||
|
||||
void (*Init)(); // called when loaded
|
||||
void (*Quit)(); // called when unloaded
|
||||
|
||||
int (*Open)(int samplerate, int numchannels, int bitspersamp, int bufferlenms, int prebufferms);
|
||||
// returns >=0 on success, <0 on failure
|
||||
// NOTENOTENOTE: bufferlenms and prebufferms are ignored in most if not all output plug-ins.
|
||||
// ... so don't expect the max latency returned to be what you asked for.
|
||||
// returns max latency in ms (0 for diskwriters, etc)
|
||||
// bufferlenms and prebufferms must be in ms. 0 to use defaults.
|
||||
// prebufferms must be <= bufferlenms
|
||||
|
||||
void (*Close)(); // close the ol' output device.
|
||||
|
||||
int (*Write)(char *buf, int len);
|
||||
// 0 on success. Len == bytes to write (<= 8192 always). buf is straight audio data.
|
||||
// 1 returns not able to write (yet). Non-blocking, always.
|
||||
|
||||
int (*CanWrite)(); // returns number of bytes possible to write at a given time.
|
||||
// Never will decrease unless you call Write (or Close, heh)
|
||||
|
||||
int (*IsPlaying)(); // non0 if output is still going or if data in buffers waiting to be
|
||||
// written (i.e. closing while IsPlaying() returns 1 would truncate the song
|
||||
|
||||
int (*Pause)(int pause); // returns previous pause state
|
||||
|
||||
void (*SetVolume)(int volume); // volume is 0-255
|
||||
void (*SetPan)(int pan); // pan is -128 to 128
|
||||
|
||||
void (*Flush)(int t); // flushes buffers and restarts output at time t (in ms)
|
||||
// (used for seeking)
|
||||
|
||||
int (*GetOutputTime)(); // returns played time in MS
|
||||
int (*GetWrittenTime)(); // returns time written in MS (used for synching up vis stuff)
|
||||
|
||||
} Out_Module;
|
||||
|
||||
|
14
src/plugin_xmms/Makefile
Normal file
14
src/plugin_xmms/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
LIB_NAME = libxmms-flac
|
||||
INCLUDES = $(shell xmms-config --cflags) -I./include -I../../include
|
||||
LIBS = ../../obj/lib/libFLAC.a
|
||||
|
||||
OBJS = \
|
||||
plugin.o
|
||||
|
||||
include ../../build/lib.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
393
src/plugin_xmms/plugin.c
Normal file
393
src/plugin_xmms/plugin.c
Normal file
@ -0,0 +1,393 @@
|
||||
/* libxmms-flac - XMMS FLAC input plugin
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "xmms/plugin.h"
|
||||
#include "xmms/util.h"
|
||||
#include "FLAC/all.h"
|
||||
|
||||
typedef struct {
|
||||
byte raw[128];
|
||||
char title[31];
|
||||
char artist[31];
|
||||
char album[31];
|
||||
char comment[31];
|
||||
unsigned year;
|
||||
unsigned track; /* may be 0 if v1 (not v1.1) tag */
|
||||
unsigned genre;
|
||||
char description[1024]; /* the formatted description passed to xmms */
|
||||
} id3v1_struct;
|
||||
|
||||
typedef struct {
|
||||
bool abort_flag;
|
||||
bool is_playing;
|
||||
bool eof;
|
||||
unsigned total_samples;
|
||||
unsigned bits_per_sample;
|
||||
unsigned channels;
|
||||
unsigned sample_rate;
|
||||
unsigned length_in_msec;
|
||||
int seek_to_in_sec;
|
||||
} file_info_struct;
|
||||
|
||||
static void FLAC_XMMS__init();
|
||||
static int FLAC_XMMS__is_our_file(char *filename);
|
||||
static void FLAC_XMMS__play_file(char *filename);
|
||||
static void FLAC_XMMS__stop();
|
||||
static void FLAC_XMMS__pause(short p);
|
||||
static void FLAC_XMMS__seek(int time);
|
||||
static int FLAC_XMMS__get_time();
|
||||
static void FLAC_XMMS__cleanup();
|
||||
static void FLAC_XMMS__get_song_info(char *filename, char **title, int *length);
|
||||
|
||||
static void *play_loop_(void *arg);
|
||||
static bool decoder_init_(const char *filename);
|
||||
static bool get_id3v1_tag_(const char *filename, id3v1_struct *tag);
|
||||
static FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data);
|
||||
static void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data);
|
||||
static void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data);
|
||||
|
||||
|
||||
InputPlugin flac_ip =
|
||||
{
|
||||
NULL,
|
||||
NULL,
|
||||
"FLAC Player v" FLAC__VERSION_STRING,
|
||||
FLAC_XMMS__init,
|
||||
NULL,
|
||||
NULL,
|
||||
FLAC_XMMS__is_our_file,
|
||||
NULL,
|
||||
FLAC_XMMS__play_file,
|
||||
FLAC_XMMS__stop,
|
||||
FLAC_XMMS__pause,
|
||||
FLAC_XMMS__seek,
|
||||
NULL,
|
||||
FLAC_XMMS__get_time,
|
||||
NULL,
|
||||
NULL,
|
||||
FLAC_XMMS__cleanup,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
FLAC_XMMS__get_song_info,
|
||||
NULL, /* file_info_box */
|
||||
NULL
|
||||
};
|
||||
|
||||
static int16 reservoir_[FLAC__MAX_BLOCK_SIZE * 2]; /* 2 for max channels */
|
||||
static unsigned reservoir_samples_;
|
||||
static FLAC__FileDecoder *decoder_;
|
||||
static file_info_struct file_info_;
|
||||
static pthread_t decode_thread_;
|
||||
static bool audio_error_ = false;
|
||||
|
||||
InputPlugin *get_iplugin_info()
|
||||
{
|
||||
flac_ip.description = g_strdup_printf("FLAC Player v%u.%u", FLAC__MAJOR_VERSION, FLAC__MINOR_VERSION);
|
||||
return &flac_ip;
|
||||
}
|
||||
|
||||
void FLAC_XMMS__init()
|
||||
{
|
||||
decoder_ = FLAC__file_decoder_get_new_instance();
|
||||
}
|
||||
|
||||
int FLAC_XMMS__is_our_file(char *filename)
|
||||
{
|
||||
char *ext;
|
||||
|
||||
ext = strrchr(filename, '.');
|
||||
if (ext)
|
||||
if (!strcasecmp(ext, ".flac") || !strcasecmp(ext, ".fla"))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void FLAC_XMMS__play_file(char *filename)
|
||||
{
|
||||
FILE *f;
|
||||
id3v1_struct tag;
|
||||
|
||||
if(0 == (f = fopen(filename, "r")))
|
||||
return;
|
||||
fclose(f);
|
||||
|
||||
if(!decoder_init_(filename))
|
||||
return;
|
||||
|
||||
reservoir_samples_ = 0;
|
||||
audio_error_ = false;
|
||||
file_info_.is_playing = true;
|
||||
file_info_.eof = false;
|
||||
|
||||
if (flac_ip.output->open_audio(FMT_S16_NE, file_info_.sample_rate, file_info_.channels) == 0) {
|
||||
audio_error_ = true;
|
||||
if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder_);
|
||||
return;
|
||||
}
|
||||
|
||||
(void)get_id3v1_tag_(filename, &tag);
|
||||
flac_ip.set_info(tag.description, file_info_.length_in_msec, file_info_.sample_rate * file_info_.channels * file_info_.bits_per_sample, file_info_.sample_rate, file_info_.channels);
|
||||
|
||||
file_info_.seek_to_in_sec = -1;
|
||||
pthread_create(&decode_thread_, NULL, play_loop_, NULL);
|
||||
}
|
||||
|
||||
void FLAC_XMMS__stop()
|
||||
{
|
||||
if(file_info_.is_playing) {
|
||||
file_info_.is_playing = false;
|
||||
pthread_join(decode_thread_, NULL);
|
||||
flac_ip.output->close_audio();
|
||||
if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder_);
|
||||
}
|
||||
}
|
||||
|
||||
void FLAC_XMMS__pause(short p)
|
||||
{
|
||||
flac_ip.output->pause(p);
|
||||
}
|
||||
|
||||
void FLAC_XMMS__seek(int time)
|
||||
{
|
||||
file_info_.seek_to_in_sec = time;
|
||||
file_info_.eof = false;
|
||||
|
||||
while(file_info_.seek_to_in_sec != -1)
|
||||
xmms_usleep(10000);
|
||||
}
|
||||
|
||||
int FLAC_XMMS__get_time()
|
||||
{
|
||||
if(audio_error_)
|
||||
return -2;
|
||||
if(!file_info_.is_playing || (file_info_.eof && !flac_ip.output->buffer_playing()))
|
||||
return -1;
|
||||
else
|
||||
return flac_ip.output->output_time();
|
||||
}
|
||||
|
||||
void FLAC_XMMS__cleanup()
|
||||
{
|
||||
if(decoder_)
|
||||
FLAC__file_decoder_free_instance(decoder_);
|
||||
}
|
||||
|
||||
void FLAC_XMMS__get_song_info(char *filename, char **title, int *length_in_msec)
|
||||
{
|
||||
id3v1_struct tag;
|
||||
|
||||
if(title) {
|
||||
(void)get_id3v1_tag_(filename, &tag);
|
||||
*title = g_malloc(strlen(tag.description)+1);
|
||||
strcpy(*title, tag.description);
|
||||
}
|
||||
if(length_in_msec) {
|
||||
FLAC__FileDecoder *tmp_decoder = FLAC__file_decoder_get_new_instance();
|
||||
file_info_struct tmp_file_info;
|
||||
if(0 == tmp_decoder) {
|
||||
*length_in_msec = -1;
|
||||
return;
|
||||
}
|
||||
tmp_file_info.abort_flag = false;
|
||||
if(FLAC__file_decoder_init(tmp_decoder, filename, write_callback_, metadata_callback_, error_callback_, &tmp_file_info) != FLAC__FILE_DECODER_OK) {
|
||||
*length_in_msec = -1;
|
||||
return;
|
||||
}
|
||||
if(!FLAC__file_decoder_process_metadata(tmp_decoder)) {
|
||||
*length_in_msec = -1;
|
||||
return;
|
||||
}
|
||||
|
||||
*length_in_msec = (int)tmp_file_info.length_in_msec;
|
||||
|
||||
if(tmp_decoder->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(tmp_decoder);
|
||||
FLAC__file_decoder_free_instance(tmp_decoder);
|
||||
}
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* local routines
|
||||
**********************************************************************/
|
||||
|
||||
void *play_loop_(void *arg)
|
||||
{
|
||||
|
||||
(void)arg;
|
||||
|
||||
while(file_info_.is_playing) {
|
||||
if(!file_info_.eof) {
|
||||
(void)FLAC__file_decoder_process_one_frame(decoder_);
|
||||
if(reservoir_samples_ > 0) {
|
||||
unsigned bytes = reservoir_samples_ * ((file_info_.bits_per_sample+7)/8) * file_info_.channels;
|
||||
flac_ip.add_vis_pcm(flac_ip.output->written_time(), FMT_S16_NE, file_info_.channels, bytes, (char*)reservoir_);
|
||||
while(flac_ip.output->buffer_free() < (int)bytes && file_info_.is_playing && file_info_.seek_to_in_sec == -1)
|
||||
xmms_usleep(10000);
|
||||
if(file_info_.is_playing && file_info_.seek_to_in_sec == -1)
|
||||
flac_ip.output->write_audio((char*)reservoir_, bytes);
|
||||
reservoir_samples_ = 0;
|
||||
}
|
||||
else {
|
||||
file_info_.eof = true;
|
||||
xmms_usleep(10000);
|
||||
}
|
||||
}
|
||||
else
|
||||
xmms_usleep(10000);
|
||||
if (file_info_.seek_to_in_sec != -1) {
|
||||
const double distance = (double)file_info_.seek_to_in_sec * 1000.0 / (double)file_info_.length_in_msec;
|
||||
unsigned target_sample = (unsigned)(distance * (double)file_info_.total_samples);
|
||||
if(FLAC__file_decoder_seek_absolute(decoder_, (uint64)target_sample)) {
|
||||
flac_ip.output->flush(file_info_.seek_to_in_sec * 1000);
|
||||
file_info_.seek_to_in_sec = -1;
|
||||
file_info_.eof = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if(decoder_ && decoder_->state != FLAC__FILE_DECODER_UNINITIALIZED)
|
||||
FLAC__file_decoder_finish(decoder_);
|
||||
|
||||
/* are these two calls necessary? */
|
||||
flac_ip.output->buffer_free();
|
||||
flac_ip.output->buffer_free();
|
||||
|
||||
pthread_exit(NULL);
|
||||
return 0; /* to silence the compiler warning about not returning a value */
|
||||
}
|
||||
|
||||
bool decoder_init_(const char *filename)
|
||||
{
|
||||
if(decoder_ == 0)
|
||||
return false;
|
||||
|
||||
if(FLAC__file_decoder_init(decoder_, filename, write_callback_, metadata_callback_, error_callback_, &file_info_) != FLAC__FILE_DECODER_OK)
|
||||
return false;
|
||||
|
||||
file_info_.abort_flag = false;
|
||||
|
||||
if(!FLAC__file_decoder_process_metadata(decoder_))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool get_id3v1_tag_(const char *filename, id3v1_struct *tag)
|
||||
{
|
||||
const char *temp;
|
||||
FILE *f = fopen(filename, "rb");
|
||||
memset(tag, 0, sizeof(id3v1_struct));
|
||||
|
||||
/* set the description to the filename by default */
|
||||
temp = strrchr(filename, '/');
|
||||
if(!temp)
|
||||
temp = filename;
|
||||
else
|
||||
temp++;
|
||||
strcpy(tag->description, temp);
|
||||
*strrchr(tag->description, '.') = '\0';
|
||||
|
||||
if(0 == f)
|
||||
return false;
|
||||
if(-1 == fseek(f, -128, SEEK_END)) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
if(fread(tag->raw, 1, 128, f) < 128) {
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
fclose(f);
|
||||
if(strncmp(tag->raw, "TAG", 3))
|
||||
return false;
|
||||
else {
|
||||
char year_str[5];
|
||||
|
||||
memcpy(tag->title, tag->raw+3, 30);
|
||||
memcpy(tag->artist, tag->raw+33, 30);
|
||||
memcpy(tag->album, tag->raw+63, 30);
|
||||
memcpy(year_str, tag->raw+93, 4); year_str[4] = '\0'; tag->year = atoi(year_str);
|
||||
memcpy(tag->comment, tag->raw+97, 30);
|
||||
tag->genre = (unsigned)((byte)tag->raw[127]);
|
||||
tag->track = (unsigned)((byte)tag->raw[126]);
|
||||
|
||||
sprintf(tag->description, "%s - %s", tag->artist, tag->title);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
FLAC__StreamDecoderWriteStatus write_callback_(const FLAC__FileDecoder *decoder, const FLAC__FrameHeader *header, const int32 *buffer[], void *client_data)
|
||||
{
|
||||
file_info_struct *file_info = (file_info_struct *)client_data;
|
||||
unsigned bps = file_info->bits_per_sample, channels = file_info->channels;
|
||||
unsigned wide_samples = header->blocksize, wide_sample, sample, channel;
|
||||
|
||||
(void)decoder;
|
||||
|
||||
if(file_info->abort_flag)
|
||||
return FLAC__STREAM_DECODER_WRITE_ABORT;
|
||||
|
||||
assert(bps == 16);
|
||||
|
||||
for(sample = wide_sample = 0; wide_sample < wide_samples; wide_sample++)
|
||||
for(channel = 0; channel < channels; channel++, sample++)
|
||||
reservoir_[sample] = (int16)buffer[channel][wide_sample];
|
||||
|
||||
reservoir_samples_ = wide_samples;
|
||||
|
||||
return FLAC__STREAM_DECODER_WRITE_CONTINUE;
|
||||
}
|
||||
|
||||
void metadata_callback_(const FLAC__FileDecoder *decoder, const FLAC__StreamMetaData *metadata, void *client_data)
|
||||
{
|
||||
file_info_struct *file_info = (file_info_struct *)client_data;
|
||||
(void)decoder;
|
||||
if(metadata->type == FLAC__METADATA_TYPE_ENCODING) {
|
||||
assert(metadata->data.encoding.total_samples < 0x100000000); /* this plugin can only handle < 4 gigasamples */
|
||||
file_info->total_samples = (unsigned)(metadata->data.encoding.total_samples&0xffffffff);
|
||||
file_info->bits_per_sample = metadata->data.encoding.bits_per_sample;
|
||||
file_info->channels = metadata->data.encoding.channels;
|
||||
file_info->sample_rate = metadata->data.encoding.sample_rate;
|
||||
|
||||
if(file_info->bits_per_sample != 16) {
|
||||
file_info->abort_flag = true;
|
||||
return;
|
||||
}
|
||||
file_info->length_in_msec = file_info->total_samples * 10 / (file_info->sample_rate / 100);
|
||||
}
|
||||
}
|
||||
|
||||
void error_callback_(const FLAC__FileDecoder *decoder, FLAC__StreamDecoderErrorStatus status, void *client_data)
|
||||
{
|
||||
file_info_struct *file_info = (file_info_struct *)client_data;
|
||||
(void)decoder;
|
||||
if(status != FLAC__STREAM_DECODER_ERROR_LOST_SYNC)
|
||||
file_info->abort_flag = true;
|
||||
}
|
13
src/test_streams/Makefile
Normal file
13
src/test_streams/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
PROGRAM_NAME = test_streams
|
||||
INCLUDES = -I./include -I../../include
|
||||
LIBS = -lm
|
||||
OBJS = \
|
||||
main.o
|
||||
|
||||
include ../../build/exe.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
258
src/test_streams/main.c
Normal file
258
src/test_streams/main.c
Normal file
@ -0,0 +1,258 @@
|
||||
/* test_streams - Simple test pattern generator
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include "FLAC/ordinals.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
static const char *mode = "wb";
|
||||
#else
|
||||
static const char *mode = "w";
|
||||
#endif
|
||||
|
||||
static bool is_big_endian_host;
|
||||
|
||||
static void swap16(int16 *i)
|
||||
{
|
||||
unsigned char *x = (unsigned char *)i, b;
|
||||
if(!is_big_endian_host) {
|
||||
b = x[0];
|
||||
x[0] = x[1];
|
||||
x[1] = b;
|
||||
}
|
||||
}
|
||||
|
||||
/* a mono one-sample 16bps stream */
|
||||
static bool generate_01()
|
||||
{
|
||||
FILE *f;
|
||||
int16 x = -32768;
|
||||
|
||||
if(0 == (f = fopen("test01.raw", mode)))
|
||||
return false;
|
||||
|
||||
swap16(&x);
|
||||
if(fwrite(&x, sizeof(x), 1, f) < 1)
|
||||
goto foo;
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a stereo one-sample 16bps stream */
|
||||
static bool generate_02()
|
||||
{
|
||||
FILE *f;
|
||||
int16 xl = -32768, xr = 32767;
|
||||
|
||||
if(0 == (f = fopen("test02.raw", mode)))
|
||||
return false;
|
||||
|
||||
swap16(&xl);
|
||||
swap16(&xr);
|
||||
|
||||
if(fwrite(&xl, sizeof(xl), 1, f) < 1)
|
||||
goto foo;
|
||||
if(fwrite(&xr, sizeof(xr), 1, f) < 1)
|
||||
goto foo;
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a mono five-sample 16bps stream */
|
||||
static bool generate_03()
|
||||
{
|
||||
FILE *f;
|
||||
int16 x[] = { -25, 0, 25, 50, 100 };
|
||||
unsigned i;
|
||||
|
||||
if(0 == (f = fopen("test03.raw", mode)))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < 5; i++)
|
||||
swap16(x+i);
|
||||
|
||||
if(fwrite(&x, sizeof(int16), 5, f) < 5)
|
||||
goto foo;
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a stereo five-sample 16bps stream */
|
||||
static bool generate_04()
|
||||
{
|
||||
FILE *f;
|
||||
int16 x[] = { -25, 500, 0, 400, 25, 300, 50, 200, 100, 100 };
|
||||
unsigned i;
|
||||
|
||||
if(0 == (f = fopen("test04.raw", mode)))
|
||||
return false;
|
||||
|
||||
for(i = 0; i < 10; i++)
|
||||
swap16(x+i);
|
||||
|
||||
if(fwrite(&x, sizeof(int16), 10, f) < 10)
|
||||
goto foo;
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a mono full-scale deflection 8bps stream */
|
||||
static bool generate_fsd8(const char *fn, const int pattern[], unsigned reps)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned rep, p;
|
||||
|
||||
assert(pattern != 0);
|
||||
|
||||
if(0 == (f = fopen(fn, mode)))
|
||||
return false;
|
||||
|
||||
for(rep = 0; rep < reps; rep++) {
|
||||
for(p = 0; pattern[p]; p++) {
|
||||
signed char x = pattern[p] > 0? 127 : -128;
|
||||
if(fwrite(&x, sizeof(x), 1, f) < 1)
|
||||
goto foo;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a mono full-scale deflection 16bps stream */
|
||||
static bool generate_fsd16(const char *fn, const int pattern[], unsigned reps)
|
||||
{
|
||||
FILE *f;
|
||||
unsigned rep, p;
|
||||
|
||||
assert(pattern != 0);
|
||||
|
||||
if(0 == (f = fopen(fn, mode)))
|
||||
return false;
|
||||
|
||||
for(rep = 0; rep < reps; rep++) {
|
||||
for(p = 0; pattern[p]; p++) {
|
||||
int16 x = pattern[p] > 0? 32767 : -32768;
|
||||
swap16(&x);
|
||||
if(fwrite(&x, sizeof(x), 1, f) < 1)
|
||||
goto foo;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
/* a mono sine-wave 16bps stream */
|
||||
static bool generate_sine16(const char *fn, const double sample_rate, const unsigned samples, const double f1, const double a1, const double f2, const double a2)
|
||||
{
|
||||
const signed short full_scale = 32767;
|
||||
const double delta1 = 2.0 * M_PI / ( sample_rate / f1);
|
||||
const double delta2 = 2.0 * M_PI / ( sample_rate / f2);
|
||||
FILE *f;
|
||||
double theta1, theta2;
|
||||
unsigned i;
|
||||
|
||||
if(0 == (f = fopen(fn, mode)))
|
||||
return false;
|
||||
|
||||
for(i = 0, theta1 = theta2 = 0.0; i < samples; i++, theta1 += delta1, theta2 += delta2) {
|
||||
double val = (a1*sin(theta1) + a2*sin(theta2))*(double)full_scale;
|
||||
int16 v = (int16)(val + 0.5);
|
||||
swap16(&v);
|
||||
if(fwrite(&v, sizeof(v), 1, f) < 1)
|
||||
goto foo;
|
||||
}
|
||||
|
||||
fclose(f);
|
||||
return true;
|
||||
foo:
|
||||
fclose(f);
|
||||
return false;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
uint32 test = 1;
|
||||
|
||||
int pattern01[] = { 1, -1, 0 };
|
||||
int pattern02[] = { 1, 1, -1, 0 };
|
||||
int pattern03[] = { 1, -1, -1, 0 };
|
||||
int pattern04[] = { 1, -1, 1, -1, 0 };
|
||||
int pattern05[] = { 1, -1, -1, 1, 0 };
|
||||
int pattern06[] = { 1, -1, 1, 1, -1, 0 };
|
||||
int pattern07[] = { 1, -1, -1, 1, -1, 0 };
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
is_big_endian_host = (*((byte*)(&test)))? false : true;
|
||||
|
||||
if(!generate_01()) return 1;
|
||||
if(!generate_02()) return 1;
|
||||
if(!generate_03()) return 1;
|
||||
if(!generate_04()) return 1;
|
||||
|
||||
if(!generate_fsd8("fsd8-01.raw", pattern01, 100)) return 1;
|
||||
if(!generate_fsd8("fsd8-02.raw", pattern02, 100)) return 1;
|
||||
if(!generate_fsd8("fsd8-03.raw", pattern03, 100)) return 1;
|
||||
if(!generate_fsd8("fsd8-04.raw", pattern04, 100)) return 1;
|
||||
if(!generate_fsd8("fsd8-05.raw", pattern05, 100)) return 1;
|
||||
if(!generate_fsd8("fsd8-06.raw", pattern06, 100)) return 1;
|
||||
if(!generate_fsd8("fsd8-07.raw", pattern07, 100)) return 1;
|
||||
|
||||
if(!generate_fsd16("fsd16-01.raw", pattern01, 100)) return 1;
|
||||
if(!generate_fsd16("fsd16-02.raw", pattern02, 100)) return 1;
|
||||
if(!generate_fsd16("fsd16-03.raw", pattern03, 100)) return 1;
|
||||
if(!generate_fsd16("fsd16-04.raw", pattern04, 100)) return 1;
|
||||
if(!generate_fsd16("fsd16-05.raw", pattern05, 100)) return 1;
|
||||
if(!generate_fsd16("fsd16-06.raw", pattern06, 100)) return 1;
|
||||
if(!generate_fsd16("fsd16-07.raw", pattern07, 100)) return 1;
|
||||
|
||||
if(!generate_sine16("sine-01.raw", 44100.0, 80000, 441.0, 0.50, 441.0, 0.49)) return 1;
|
||||
if(!generate_sine16("sine-02.raw", 44100.0, 80000, 441.0, 0.61, 661.5, 0.37)) return 1;
|
||||
if(!generate_sine16("sine-03.raw", 44100.0, 80000, 441.0, 0.50, 882.0, 0.49)) return 1;
|
||||
if(!generate_sine16("sine-04.raw", 44100.0, 80000, 441.0, 0.50, 4410.0, 0.49)) return 1;
|
||||
if(!generate_sine16("sine-05.raw", 44100.0, 50000, 8820.0, 0.70, 4410.0, 0.29)) return 1;
|
||||
|
||||
return 0;
|
||||
}
|
14
src/test_unit/Makefile
Normal file
14
src/test_unit/Makefile
Normal file
@ -0,0 +1,14 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
|
||||
PROGRAM_NAME = test_unit
|
||||
INCLUDES = -I../libFLAC/include -I../../include
|
||||
LIBS = -lFLAC -lm
|
||||
OBJS = \
|
||||
bitbuffer.o \
|
||||
main.o
|
||||
|
||||
include ../../build/exe.mk
|
||||
|
||||
# DO NOT DELETE THIS LINE -- make depend depends on it.
|
629
src/test_unit/bitbuffer.c
Normal file
629
src/test_unit/bitbuffer.c
Normal file
@ -0,0 +1,629 @@
|
||||
/* test_unit - Simple FLAC unit tester
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "private/bitbuffer.h" /* from the libFLAC private include area */
|
||||
|
||||
static bool dummy_read_callback(byte buffer[], unsigned *bytes, void *client_data)
|
||||
{
|
||||
(void)buffer, (void)bytes, (void)client_data;
|
||||
return true;
|
||||
}
|
||||
|
||||
int test_bitbuffer()
|
||||
{
|
||||
FLAC__BitBuffer bb, bb_zero, bb_one, bbcopy;
|
||||
bool ok;
|
||||
unsigned i, j;
|
||||
static byte test_pattern1[19] = { 0xaa, 0xf0, 0xaa, 0xbe, 0xaa, 0xaa, 0xaa, 0xa8, 0x30, 0x0a, 0xaa, 0xaa, 0xaa, 0xad, 0xea, 0xdb, 0xee, 0xfa, 0xce };
|
||||
|
||||
printf("testing init... OK\n");
|
||||
FLAC__bitbuffer_init(&bb);
|
||||
FLAC__bitbuffer_init(&bb_zero);
|
||||
FLAC__bitbuffer_init(&bb_one);
|
||||
FLAC__bitbuffer_init(&bbcopy);
|
||||
|
||||
printf("testing clear... ");
|
||||
ok = FLAC__bitbuffer_clear(&bb) && FLAC__bitbuffer_clear(&bb_zero) && FLAC__bitbuffer_clear(&bb_one) && FLAC__bitbuffer_clear(&bbcopy);
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok)
|
||||
return 1;
|
||||
|
||||
printf("setting up bb_one... ");
|
||||
ok = FLAC__bitbuffer_write_raw_uint32(&bb_one, 1, 7) && FLAC__bitbuffer_read_raw_uint32(&bb_one, &i, 6, dummy_read_callback, 0);
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok)
|
||||
return 1;
|
||||
FLAC__bitbuffer_dump(&bb_one, stdout);
|
||||
|
||||
printf("capacity = %u\n", bb.capacity);
|
||||
|
||||
printf("testing zeroes, raw_uint32*... ");
|
||||
ok =
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0x1, 1) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0x1, 2) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xa, 5) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xf0, 8) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0x2aa, 10) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xf, 4) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xaaaaaaaa, 32) &&
|
||||
FLAC__bitbuffer_write_zeroes(&bb, 4) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0x3, 2) &&
|
||||
FLAC__bitbuffer_write_zeroes(&bb, 8) &&
|
||||
FLAC__bitbuffer_write_raw_uint64(&bb, 0xaaaaaaaadeadbeef, 64) &&
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xace, 12)
|
||||
;
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1));
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 0) {
|
||||
printf("FAILED bit count %u != 0\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing raw_uint32 some more... ");
|
||||
ok = FLAC__bitbuffer_write_raw_uint32(&bb, 0x3d, 6);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1));
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 6) {
|
||||
printf("FAILED bit count %u != 6\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes] != 0x3d) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing concatenate_aligned (bb_zero)... ");
|
||||
ok = FLAC__bitbuffer_concatenate_aligned(&bb, &bb_zero);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1));
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 6) {
|
||||
printf("FAILED bit count %u != 6\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes] != 0x3d) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing concatenate_aligned (bb_one)... ");
|
||||
ok = FLAC__bitbuffer_concatenate_aligned(&bb, &bb_one);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1));
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 7) {
|
||||
printf("FAILED bit count %u != 7\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes] != 0x7b) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing concatenate_aligned (bb_one again)... ");
|
||||
(void)FLAC__bitbuffer_write_raw_uint32(&bb_one, 1, 1);
|
||||
(void)FLAC__bitbuffer_read_raw_uint32(&bb_one, &i, 1, dummy_read_callback, 0);
|
||||
ok = FLAC__bitbuffer_concatenate_aligned(&bb, &bb_one);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)+1) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1)+1);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 0) {
|
||||
printf("FAILED bit count %u != 0\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes-1] != 0xf7) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing concatenate_aligned (bb_four)... ");
|
||||
(void)FLAC__bitbuffer_clear(&bb_one);
|
||||
(void)FLAC__bitbuffer_write_raw_uint32(&bb_one, 8, 4);
|
||||
ok = FLAC__bitbuffer_concatenate_aligned(&bb, &bb_one);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)+1) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1)+1);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 4) {
|
||||
printf("FAILED bit count %u != 4\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes] != 0x08) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing concatenate_aligned (bb_eight)... ");
|
||||
(void)FLAC__bitbuffer_read_raw_uint32(&bb_one, &i, 4, dummy_read_callback, 0);
|
||||
(void)FLAC__bitbuffer_write_raw_uint32(&bb_one, 0xaa, 8);
|
||||
ok = FLAC__bitbuffer_concatenate_aligned(&bb, &bb_one);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)+2) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1)+2);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 4) {
|
||||
printf("FAILED bit count %u != 4\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes-1] != 0x8a || bb.buffer[bb.bytes] != 0x0a) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing concatenate_aligned (bb_seventeen)... ");
|
||||
(void)FLAC__bitbuffer_write_raw_uint32(&bb_one, 0x155, 9);
|
||||
ok = FLAC__bitbuffer_concatenate_aligned(&bb, &bb_one);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != sizeof(test_pattern1)+4) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, sizeof(test_pattern1)+4);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != 5) {
|
||||
printf("FAILED bit count %u != 5\n", bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != 8*bb.bytes+bb.bits) {
|
||||
printf("FAILED total_bits count %u != %u (%u:%u)\n", bb.total_bits, 8*bb.bytes+bb.bits, bb.bytes, bb.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, test_pattern1, sizeof(byte)*sizeof(test_pattern1)) != 0 || bb.buffer[bb.bytes-3] != 0x8a || bb.buffer[bb.bytes-2] != 0xaa || bb.buffer[bb.bytes-1] != 0xaa || bb.buffer[bb.bytes] != 0x15) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
|
||||
printf("testing utf8_uint32(0x00000000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x00000000);
|
||||
ok = bb.total_bits == 8 && bb.buffer[0] == 0;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x0000007F)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x0000007F);
|
||||
ok = bb.total_bits == 8 && bb.buffer[0] == 0x7F;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x00000080)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x00000080);
|
||||
ok = bb.total_bits == 16 && bb.buffer[0] == 0xC2 && bb.buffer[1] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x000007FF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x000007FF);
|
||||
ok = bb.total_bits == 16 && bb.buffer[0] == 0xDF && bb.buffer[1] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x00000800)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x00000800);
|
||||
ok = bb.total_bits == 24 && bb.buffer[0] == 0xE0 && bb.buffer[1] == 0xA0 && bb.buffer[2] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x0000FFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x0000FFFF);
|
||||
ok = bb.total_bits == 24 && bb.buffer[0] == 0xEF && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x00010000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x00010000);
|
||||
ok = bb.total_bits == 32 && bb.buffer[0] == 0xF0 && bb.buffer[1] == 0x90 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x001FFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x001FFFFF);
|
||||
ok = bb.total_bits == 32 && bb.buffer[0] == 0xF7 && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x00200000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x00200000);
|
||||
ok = bb.total_bits == 40 && bb.buffer[0] == 0xF8 && bb.buffer[1] == 0x88 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80 && bb.buffer[4] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x03FFFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x03FFFFFF);
|
||||
ok = bb.total_bits == 40 && bb.buffer[0] == 0xFB && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF && bb.buffer[4] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x04000000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x04000000);
|
||||
ok = bb.total_bits == 48 && bb.buffer[0] == 0xFC && bb.buffer[1] == 0x84 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80 && bb.buffer[4] == 0x80 && bb.buffer[5] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint32(0x7FFFFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint32(&bb, 0x7FFFFFFF);
|
||||
ok = bb.total_bits == 48 && bb.buffer[0] == 0xFD && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF && bb.buffer[4] == 0xBF && bb.buffer[5] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000000000000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000000000000);
|
||||
ok = bb.total_bits == 8 && bb.buffer[0] == 0;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x000000000000007F)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x000000000000007F);
|
||||
ok = bb.total_bits == 8 && bb.buffer[0] == 0x7F;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000000000080)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000000000080);
|
||||
ok = bb.total_bits == 16 && bb.buffer[0] == 0xC2 && bb.buffer[1] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x00000000000007FF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x00000000000007FF);
|
||||
ok = bb.total_bits == 16 && bb.buffer[0] == 0xDF && bb.buffer[1] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000000000800)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000000000800);
|
||||
ok = bb.total_bits == 24 && bb.buffer[0] == 0xE0 && bb.buffer[1] == 0xA0 && bb.buffer[2] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x000000000000FFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x000000000000FFFF);
|
||||
ok = bb.total_bits == 24 && bb.buffer[0] == 0xEF && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000000010000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000000010000);
|
||||
ok = bb.total_bits == 32 && bb.buffer[0] == 0xF0 && bb.buffer[1] == 0x90 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x00000000001FFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x00000000001FFFFF);
|
||||
ok = bb.total_bits == 32 && bb.buffer[0] == 0xF7 && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000000200000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000000200000);
|
||||
ok = bb.total_bits == 40 && bb.buffer[0] == 0xF8 && bb.buffer[1] == 0x88 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80 && bb.buffer[4] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000003FFFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000003FFFFFF);
|
||||
ok = bb.total_bits == 40 && bb.buffer[0] == 0xFB && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF && bb.buffer[4] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000004000000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000004000000);
|
||||
ok = bb.total_bits == 48 && bb.buffer[0] == 0xFC && bb.buffer[1] == 0x84 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80 && bb.buffer[4] == 0x80 && bb.buffer[5] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x000000007FFFFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x000000007FFFFFFF);
|
||||
ok = bb.total_bits == 48 && bb.buffer[0] == 0xFD && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF && bb.buffer[4] == 0xBF && bb.buffer[5] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000080000000)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000080000000);
|
||||
ok = bb.total_bits == 56 && bb.buffer[0] == 0xFE && bb.buffer[1] == 0x82 && bb.buffer[2] == 0x80 && bb.buffer[3] == 0x80 && bb.buffer[4] == 0x80 && bb.buffer[5] == 0x80 && bb.buffer[6] == 0x80;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing utf8_uint64(0x0000000FFFFFFFFF)... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_utf8_uint64(&bb, 0x0000000FFFFFFFFF);
|
||||
ok = bb.total_bits == 56 && bb.buffer[0] == 0xFE && bb.buffer[1] == 0xBF && bb.buffer[2] == 0xBF && bb.buffer[3] == 0xBF && bb.buffer[4] == 0xBF && bb.buffer[5] == 0xBF && bb.buffer[6] == 0xBF;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("testing grow... ");
|
||||
FLAC__bitbuffer_clear(&bb);
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xa, 4);
|
||||
j = bb.capacity;
|
||||
for(i = 0; i < j; i++)
|
||||
FLAC__bitbuffer_write_raw_uint32(&bb, 0xaa, 8);
|
||||
ok = bb.total_bits = i*8+4 && bb.buffer[0] == 0xaa && bb.buffer[i] == 0xa;
|
||||
printf("%s\n", ok?"OK":"FAILED");
|
||||
if(!ok) {
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("capacity = %u\n", bb.capacity);
|
||||
|
||||
printf("testing clone... ");
|
||||
ok = FLAC__bitbuffer_clone(&bbcopy, &bb);
|
||||
if(!ok) {
|
||||
printf("FAILED\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
FLAC__bitbuffer_dump(&bbcopy, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bytes != bbcopy.bytes) {
|
||||
printf("FAILED byte count %u != %u\n", bb.bytes, bbcopy.bytes);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
FLAC__bitbuffer_dump(&bbcopy, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.bits != bbcopy.bits) {
|
||||
printf("FAILED bit count %u != %u\n", bb.bits, bbcopy.bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
FLAC__bitbuffer_dump(&bbcopy, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(bb.total_bits != bbcopy.total_bits) {
|
||||
printf("FAILED total_bits count %u != %u\n", bb.total_bits, bbcopy.total_bits);
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
FLAC__bitbuffer_dump(&bbcopy, stdout);
|
||||
return 1;
|
||||
}
|
||||
if(memcmp(bb.buffer, bbcopy.buffer, sizeof(byte)*bb.capacity) != 0) {
|
||||
printf("FAILED pattern match\n");
|
||||
FLAC__bitbuffer_dump(&bb, stdout);
|
||||
FLAC__bitbuffer_dump(&bbcopy, stdout);
|
||||
return 1;
|
||||
}
|
||||
printf("OK\n");
|
||||
|
||||
printf("testing free... OK\n");
|
||||
FLAC__bitbuffer_free(&bb);
|
||||
FLAC__bitbuffer_free(&bbcopy);
|
||||
|
||||
printf("\nPASSED!\n");
|
||||
return 0;
|
||||
}
|
24
src/test_unit/bitbuffer.h
Normal file
24
src/test_unit/bitbuffer.h
Normal file
@ -0,0 +1,24 @@
|
||||
/* test_unit - Simple FLAC unit tester
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#ifndef FLAC__TEST_UNIT_BITBUFFER_H
|
||||
#define FLAC__TEST_UNIT_BITBUFFER_H
|
||||
|
||||
int test_bitbuffer();
|
||||
|
||||
#endif
|
26
src/test_unit/main.c
Normal file
26
src/test_unit/main.c
Normal file
@ -0,0 +1,26 @@
|
||||
/* test_unit - Simple FLAC unit tester
|
||||
* Copyright (C) 2000 Josh Coalson
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* This program 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.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include "bitbuffer.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
if(0 != test_bitbuffer())
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
13
test/Makefile
Normal file
13
test/Makefile
Normal file
@ -0,0 +1,13 @@
|
||||
#
|
||||
# GNU makefile
|
||||
#
|
||||
all: clean
|
||||
./test_unit.sh
|
||||
./test_streams.sh
|
||||
|
||||
debug: all
|
||||
|
||||
release: all
|
||||
|
||||
clean:
|
||||
rm -f *.raw *.flac *.cmp *.log
|
71
test/test_streams.sh
Executable file
71
test/test_streams.sh
Executable file
@ -0,0 +1,71 @@
|
||||
#!/bin/sh
|
||||
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../obj/lib
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
if ../obj/bin/test_streams ; then : ; else
|
||||
echo "ERROR during test_streams" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
FLAC=../obj/bin/flac
|
||||
|
||||
test_file ()
|
||||
{
|
||||
name=$1
|
||||
channels=$2
|
||||
bps=$3
|
||||
encode_options="$4"
|
||||
|
||||
echo "### ENCODE $name ########################################" >> ./encode.log
|
||||
echo -n "$name: encode..."
|
||||
if $FLAC -s -fb -fs 44100 -fp $bps -fc $channels -0 -l 8 -m -e $encode_options $name.raw $name.flac 2>>./encode.log ; then : ; else
|
||||
echo "ERROR during encode of $name" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
echo "### DECODE $name ########################################" >> ./decode.log
|
||||
echo -n "decode..."
|
||||
if $FLAC -s -fb -d -fr $name.flac $name.cmp 2>>./decode.log ; then : ; else
|
||||
echo "ERROR during decode of $name" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
echo -n "compare..."
|
||||
if cmp $name.raw $name.cmp ; then : ; else
|
||||
echo "ERROR during compare of $name" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
echo OK
|
||||
}
|
||||
|
||||
echo "Testing small files..."
|
||||
test_file test01 1 16
|
||||
test_file test02 2 16
|
||||
test_file test03 1 16
|
||||
test_file test04 2 16
|
||||
|
||||
echo "Testing 8-bit full-scale deflection streams..."
|
||||
for b in 01 02 03 04 05 06 07 ; do
|
||||
test_file fsd8-$b 1 8 "-q 15"
|
||||
done
|
||||
|
||||
echo "Testing 16-bit full-scale deflection streams..."
|
||||
for b in 01 02 03 04 05 06 07 ; do
|
||||
test_file fsd16-$b 1 16 "-q 15"
|
||||
done
|
||||
|
||||
echo "Testing sine wave streams..."
|
||||
for b in 01 02 03 04 05 ; do
|
||||
test_file sine-$b 1 16 ""
|
||||
done
|
||||
|
||||
echo "Testing some frame header variations..."
|
||||
test_file sine-02 1 16 "--lax -b 16"
|
||||
test_file sine-02 1 16 "--lax -b 65535"
|
||||
test_file sine-02 1 16 "-b 16"
|
||||
test_file sine-02 1 16 "-b 65535"
|
||||
test_file sine-02 1 16 "--lax -fs 9"
|
||||
test_file sine-02 1 16 "--lax -fs 90"
|
||||
test_file sine-02 1 16 "--lax -fs 90000"
|
||||
test_file sine-02 1 16 "-fs 9"
|
||||
test_file sine-02 1 16 "-fs 90"
|
||||
test_file sine-02 1 16 "-fs 90000"
|
9
test/test_unit.sh
Executable file
9
test/test_unit.sh
Executable file
@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
LD_LIBRARY_PATH=$LD_LIBRARY_PATH:../obj/lib
|
||||
export LD_LIBRARY_PATH
|
||||
|
||||
if ../obj/bin/test_unit ; then : ; else
|
||||
echo "ERROR during testgen" 1>&2
|
||||
exit 1
|
||||
fi
|
Loading…
Reference in New Issue
Block a user