Added libsndfile
This commit is contained in:
14
project/jni/sndfile/AUTHORS
Normal file
14
project/jni/sndfile/AUTHORS
Normal file
@@ -0,0 +1,14 @@
|
||||
The main author of libsndfile is Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
apart from code in the following directories:
|
||||
|
||||
- src/GSM610 : Written by Jutta Degener <jutta@cs.tu-berlin.de> and Carsten
|
||||
Bormann <cabo@cs.tu-berlin.de>. They should not be contacted in relation to
|
||||
libsndfile or the GSM 6.10 code that is part of libsndfile. Their original
|
||||
code can be found at:
|
||||
|
||||
http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||
|
||||
- src/G72x : Released by Sun Microsystems, Inc. to the public domain. Minor
|
||||
modifications were required to integrate these files into libsndfile. The
|
||||
changes are listed in src/G72x/ChangeLog.
|
||||
|
||||
22
project/jni/sndfile/Android.mk
Normal file
22
project/jni/sndfile/Android.mk
Normal file
@@ -0,0 +1,22 @@
|
||||
LOCAL_PATH := $(call my-dir)
|
||||
|
||||
include $(CLEAR_VARS)
|
||||
|
||||
LOCAL_MODULE := sndfile
|
||||
|
||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/src $(LOCAL_PATH)/../ogg/include $(LOCAL_PATH)/../vorbis/include $(LOCAL_PATH)/../flac/include
|
||||
LOCAL_CFLAGS := -DHAVE_CONFIG_H
|
||||
|
||||
LOCAL_CPP_EXTENSION := .cpp
|
||||
|
||||
APP_SUBDIRS := $(patsubst $(LOCAL_PATH)/%, %, $(shell find $(LOCAL_PATH)/src -type d))
|
||||
LOCAL_SRC_FILES := $(foreach F, $(APP_SUBDIRS), $(addprefix $(F)/,$(notdir $(wildcard $(LOCAL_PATH)/$(F)/*.cpp))))
|
||||
LOCAL_SRC_FILES += $(foreach F, $(APP_SUBDIRS), $(addprefix $(F)/,$(notdir $(wildcard $(LOCAL_PATH)/$(F)/*.c))))
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := flac vorbis ogg
|
||||
|
||||
LOCAL_SHARED_LIBRARIES :=
|
||||
|
||||
LOCAL_LDLIBS :=
|
||||
|
||||
include $(BUILD_SHARED_LIBRARY)
|
||||
503
project/jni/sndfile/COPYING
Normal file
503
project/jni/sndfile/COPYING
Normal file
@@ -0,0 +1,503 @@
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
Version 2.1, February 1999
|
||||
|
||||
Copyright (C) 1991, 1999 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 Lesser GPL. It also counts
|
||||
as the successor of the GNU Library Public License, version 2, hence
|
||||
the version number 2.1.]
|
||||
|
||||
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 Lesser General Public License, applies to some
|
||||
specially designated software packages--typically libraries--of the
|
||||
Free Software Foundation and other authors who decide to use it. You
|
||||
can use it too, but we suggest you first think carefully about whether
|
||||
this license or the ordinary General Public License is the better
|
||||
strategy to use in any particular case, based on the explanations below.
|
||||
|
||||
When we speak of free software, we are referring to freedom of use,
|
||||
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 and use pieces of
|
||||
it in new free programs; and that you are informed that you can do
|
||||
these things.
|
||||
|
||||
To protect your rights, we need to make restrictions that forbid
|
||||
distributors to deny you these rights or to ask you to surrender these
|
||||
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 other code 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.
|
||||
|
||||
We protect your rights with a two-step method: (1) we copyright the
|
||||
library, and (2) we offer you this license, which gives you legal
|
||||
permission to copy, distribute and/or modify the library.
|
||||
|
||||
To protect each distributor, we want to make it very clear that
|
||||
there is no warranty for the free library. Also, if the library is
|
||||
modified by someone else and passed on, the recipients should know
|
||||
that what they have is not the original version, so that the original
|
||||
author's reputation will not be affected by problems that might be
|
||||
introduced by others.
|
||||
|
||||
Finally, software patents pose a constant threat to the existence of
|
||||
any free program. We wish to make sure that a company cannot
|
||||
effectively restrict the users of a free program by obtaining a
|
||||
restrictive license from a patent holder. Therefore, we insist that
|
||||
any patent license obtained for a version of the library must be
|
||||
consistent with the full freedom of use specified in this license.
|
||||
|
||||
Most GNU software, including some libraries, is covered by the
|
||||
ordinary GNU General Public License. This license, the GNU Lesser
|
||||
General Public License, applies to certain designated libraries, and
|
||||
is quite different from the ordinary General Public License. We use
|
||||
this license for certain libraries in order to permit linking those
|
||||
libraries into non-free programs.
|
||||
|
||||
When a program is linked with a library, whether statically or using
|
||||
a shared library, the combination of the two is legally speaking a
|
||||
combined work, a derivative of the original library. The ordinary
|
||||
General Public License therefore permits such linking only if the
|
||||
entire combination fits its criteria of freedom. The Lesser General
|
||||
Public License permits more lax criteria for linking other code with
|
||||
the library.
|
||||
|
||||
We call this license the "Lesser" General Public License because it
|
||||
does Less to protect the user's freedom than the ordinary General
|
||||
Public License. It also provides other free software developers Less
|
||||
of an advantage over competing non-free programs. These disadvantages
|
||||
are the reason we use the ordinary General Public License for many
|
||||
libraries. However, the Lesser license provides advantages in certain
|
||||
special circumstances.
|
||||
|
||||
For example, on rare occasions, there may be a special need to
|
||||
encourage the widest possible use of a certain library, so that it becomes
|
||||
a de-facto standard. To achieve this, non-free programs must be
|
||||
allowed to use the library. A more frequent case is that a free
|
||||
library does the same job as widely used non-free libraries. In this
|
||||
case, there is little to gain by limiting the free library to free
|
||||
software only, so we use the Lesser General Public License.
|
||||
|
||||
In other cases, permission to use a particular library in non-free
|
||||
programs enables a greater number of people to use a large body of
|
||||
free software. For example, permission to use the GNU C Library in
|
||||
non-free programs enables many more people to use the whole GNU
|
||||
operating system, as well as its variant, the GNU/Linux operating
|
||||
system.
|
||||
|
||||
Although the Lesser General Public License is Less protective of the
|
||||
users' freedom, it does ensure that the user of a program that is
|
||||
linked with the Library has the freedom and the wherewithal to run
|
||||
that program using a modified version of the Library.
|
||||
|
||||
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, whereas the latter must
|
||||
be combined with the library in order to run.
|
||||
|
||||
GNU LESSER GENERAL PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. This License Agreement applies to any software library or other
|
||||
program which contains a notice placed by the copyright holder or
|
||||
other authorized party saying it may be distributed under the terms of
|
||||
this Lesser 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 combine 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) Use a suitable shared library mechanism for linking with the
|
||||
Library. A suitable mechanism is one that (1) uses at run time a
|
||||
copy of the library already present on the user's computer system,
|
||||
rather than copying library functions into the executable, and (2)
|
||||
will operate properly with a modified version of the library, if
|
||||
the user installs one, as long as the modified version is
|
||||
interface-compatible with the version that the work was made with.
|
||||
|
||||
c) 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.
|
||||
|
||||
d) 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.
|
||||
|
||||
e) 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 materials to be 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 with
|
||||
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 Lesser 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 Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with this library; if not, write to the Free Software
|
||||
Foundation, Inc., 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!
|
||||
|
||||
9051
project/jni/sndfile/ChangeLog
Normal file
9051
project/jni/sndfile/ChangeLog
Normal file
File diff suppressed because it is too large
Load Diff
182
project/jni/sndfile/INSTALL
Normal file
182
project/jni/sndfile/INSTALL
Normal file
@@ -0,0 +1,182 @@
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
These are generic installation instructions.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, a file
|
||||
`config.cache' that saves the results of its tests to speed up
|
||||
reconfiguring, and a file `config.log' containing compiler output
|
||||
(useful mainly for debugging `configure').
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If at some point `config.cache'
|
||||
contains results you don't want to keep, you may remove or edit it.
|
||||
|
||||
The file `configure.in' is used to create `configure' by a program
|
||||
called `autoconf'. You only need `configure.in' if you want to change
|
||||
it or regenerate `configure' using a newer version of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system. If you're
|
||||
using `csh' on an old version of System V, you might need to type
|
||||
`sh ./configure' instead to prevent `csh' from trying to execute
|
||||
`configure' itself.
|
||||
|
||||
Running `configure' takes awhile. While running, it prints some
|
||||
messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that
|
||||
the `configure' script does not know about. You can give `configure'
|
||||
initial values for variables by setting them in the environment. Using
|
||||
a Bourne-compatible shell, you can do that on the command line like
|
||||
this:
|
||||
CC=c89 CFLAGS=-O2 LIBS=-lposix ./configure
|
||||
|
||||
Or on systems that have the `env' program, you can do it like this:
|
||||
env CPPFLAGS=-I/usr/local/include LDFLAGS=-s ./configure
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you must use a version of `make' that
|
||||
supports the `VPATH' variable, such as GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
If you have to use a `make' that does not supports the `VPATH'
|
||||
variable, you have to compile the package for one architecture at a time
|
||||
in the source code directory. After you have installed the package for
|
||||
one architecture, use `make distclean' before reconfiguring for another
|
||||
architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' will install the package's files in
|
||||
`/usr/local/bin', `/usr/local/man', etc. You can specify an
|
||||
installation prefix other than `/usr/local' by giving `configure' the
|
||||
option `--prefix=PATH'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
give `configure' the option `--exec-prefix=PATH', the package will use
|
||||
PATH as the prefix for installing programs and libraries.
|
||||
Documentation and other data files will still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=PATH' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' can not figure out
|
||||
automatically, but needs to determine by the type of host the package
|
||||
will run on. Usually `configure' can figure that out, but if it prints
|
||||
a message saying it can not guess the host type, give it the
|
||||
`--host=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name with three fields:
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the host type.
|
||||
|
||||
If you are building compiler tools for cross-compiling, you can also
|
||||
use the `--target=TYPE' option to select the type of system they will
|
||||
produce code for and the `--build=TYPE' option to select the type of
|
||||
system on which you are compiling the package.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share,
|
||||
you can create a site shell script called `config.site' that gives
|
||||
default values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Operation Controls
|
||||
==================
|
||||
|
||||
`configure' recognizes the following options to control how it
|
||||
operates.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Use and save the results of the tests in FILE instead of
|
||||
`./config.cache'. Set FILE to `/dev/null' to disable caching, for
|
||||
debugging `configure'.
|
||||
|
||||
`--help'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`--version'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options.
|
||||
175
project/jni/sndfile/NEWS
Normal file
175
project/jni/sndfile/NEWS
Normal file
@@ -0,0 +1,175 @@
|
||||
Version 1.0.25 (2011-07-13)
|
||||
* Fix for Secunia Advisory SA45125, heap overflow in PAF file handler.
|
||||
* Accept broken WAV files with blockalign == 0.
|
||||
* Minor bug fixes and improvements.
|
||||
|
||||
Version 1.0.24 (2011-03-23)
|
||||
* WAV files now have an 18 byte u-law and A-law fmt chunk.
|
||||
* Document virtual I/O functionality.
|
||||
* Two new methods rawHandle() and takeOwnership() in sndfile.hh.
|
||||
* AIFF fix for non-zero offset value in SSND chunk.
|
||||
* Minor bug fixes and improvements.
|
||||
|
||||
Version 1.0.23 (2010-10-10)
|
||||
* Add version metadata to Windows DLL.
|
||||
* Add a missing 'inline' to sndfile.hh.
|
||||
* Update docs.
|
||||
* Minor bug fixes and improvements.
|
||||
|
||||
Version 1.0.22 (2010-10-04)
|
||||
* Couple of fixes for SDS file writer.
|
||||
* Fixes arising from static analysis.
|
||||
* Handle FLAC files with ID3 meta data at start of file.
|
||||
* Handle FLAC files which report zero length.
|
||||
* Other minor bug fixes and improvements.
|
||||
|
||||
Version 1.0.21 (2009-12-13)
|
||||
* Add a couple of new binary programs to programs/ dir.
|
||||
* Remove sndfile-jackplay (now in sndfile-tools package).
|
||||
* Add windows only function sf_wchar_open().
|
||||
* Bunch of minor bug fixes.
|
||||
|
||||
Version 1.0.20 (2009-05-14)
|
||||
* Fix potential heap overflow in VOC file parser (Tobias Klein, http://www.trapkit.de/).
|
||||
|
||||
Version 1.0.19 (2009-03-02)
|
||||
* Fix for CVE-2009-0186 (Alin Rad Pop, Secunia Research).
|
||||
* Huge number of minor bug fixes as a result of static analysis.
|
||||
|
||||
Version 1.0.18 (2009-02-07)
|
||||
* Add Ogg/Vorbis support (thanks to John ffitch).
|
||||
* Remove captive FLAC library.
|
||||
* Many new features and bug fixes.
|
||||
* Generate Win32 and Win64 pre-compiled binaries.
|
||||
|
||||
Version 1.0.17 (2006-08-31)
|
||||
* Add sndfile.hh C++ wrapper.
|
||||
* Update Win32 MinGW build instructions.
|
||||
* Minor bug fixes and cleanups.
|
||||
|
||||
Version 1.0.16 (2006-04-30)
|
||||
* Add support for Broadcast (BEXT) chunks in WAV files.
|
||||
* Implement new commands SFC_GET_SIGNAL_MAX and SFC_GET_MAX_ALL_CHANNELS.
|
||||
* Add support for RIFX (big endian WAV variant).
|
||||
* Fix configure script bugs.
|
||||
* Fix bug in INST and MARK chunk writing for AIFF files.
|
||||
|
||||
Version 1.0.15 (2006-03-16)
|
||||
* Fix some ia64 issues.
|
||||
* Fix precompiled DLL.
|
||||
* Minor bug fixes.
|
||||
|
||||
Version 1.0.14 (2006-02-19)
|
||||
* Really fix MinGW compile problems.
|
||||
* Minor bug fixes.
|
||||
|
||||
Version 1.0.13 (2006-01-21)
|
||||
* Fix for MinGW compiler problems.
|
||||
* Allow readin/write of instrument chunks from WAV and AIFF files.
|
||||
* Compile problem fix for Solaris compiler.
|
||||
* Minor cleanups and bug fixes.
|
||||
|
||||
Version 1.0.12 (2005-09-30)
|
||||
* Add support for FLAC and Apple's Core Audio Format (CAF).
|
||||
* Add virtual I/O interface (still needs docs).
|
||||
* Cygwin and other Win32 fixes.
|
||||
* Minor bug fixes and cleanups.
|
||||
|
||||
Version 1.0.11 (2004-11-15)
|
||||
* Add support for SD2 files.
|
||||
* Add read support for loop info in WAV and AIFF files.
|
||||
* Add more tests.
|
||||
* Improve type safety.
|
||||
* Minor optimisations and bug fixes.
|
||||
|
||||
Version 1.0.10 (2004-06-15)
|
||||
* Fix AIFF read/write mode bugs.
|
||||
* Add support for compiling Win32 DLLS using MinGW.
|
||||
* Fix problems resulting in failed compiles with gcc-2.95.
|
||||
* Improve test suite.
|
||||
* Minor bug fixes.
|
||||
|
||||
Version 1.0.9 (2004-03-30)
|
||||
* Add handling of AVR (Audio Visual Research) files.
|
||||
* Improve handling of WAVEFORMATEXTENSIBLE WAV files.
|
||||
* Fix for using pipes on Win32.
|
||||
|
||||
Version 1.0.8 (2004-03-14)
|
||||
* Correct peak chunk handing for files with > 16 tracks.
|
||||
* Fix for WAV files with huge number of CUE chunks.
|
||||
|
||||
Version 1.0.7 (2004-02-25)
|
||||
* Fix clip mode detection on ia64, MIPS and other CPUs.
|
||||
* Fix two MacOSX build problems.
|
||||
|
||||
Version 1.0.6 (2004-02-08)
|
||||
* Added support for native Win32 file access API (Ross Bencina).
|
||||
* New mode to add clippling then a converting from float/double to integer
|
||||
would otherwise wrap around.
|
||||
* Fixed a bug in reading/writing files > 2Gig on Linux, Solaris and others.
|
||||
* Many minor bug fixes.
|
||||
* Other random fixes for Win32.
|
||||
|
||||
Version 1.0.5 (2003-05-03)
|
||||
* Added support for HTK files.
|
||||
* Added new function sf_open_fd() to allow for secure opening of temporary
|
||||
files as well as reading/writing sound files embedded within larger
|
||||
container files.
|
||||
* Added string support for AIFF files.
|
||||
* Minor bug fixes and code cleanups.
|
||||
|
||||
Version 1.0.4 (2003-02-02)
|
||||
* Added suport of PVF and XI files.
|
||||
* Added functionality for setting and retreiving strings from sound files.
|
||||
* Minor code cleanups and bug fixes.
|
||||
|
||||
Version 1.0.3 (2002-12-09)
|
||||
* Minor bug fixes.
|
||||
|
||||
Version 1.0.2 (2002-11-24)
|
||||
* Added support for VOX ADPCM.
|
||||
* Improved error reporting.
|
||||
* Added version scripting on Linux and Solaris.
|
||||
* Minor bug fixes.
|
||||
|
||||
Version 1.0.1 (2002-09-14)
|
||||
* Added MAT and MAT5 file formats.
|
||||
* Minor bug fixes.
|
||||
|
||||
Version 1.0.0 (2002-08-16)
|
||||
* Final release for 1.0.0.
|
||||
|
||||
Version 1.0.0rc6 (2002-08-14)
|
||||
* Release candidate 6 for the 1.0.0 series.
|
||||
* MacOS9 fixes.
|
||||
|
||||
Version 1.0.0rc5 (2002-08-10)
|
||||
* Release candidate 5 for the 1.0.0 series.
|
||||
* Changed the definition of sf_count_t which was causing problems when
|
||||
libsndfile was compiled with other libraries (ie WxWindows).
|
||||
* Minor bug fixes.
|
||||
* Documentation cleanup.
|
||||
|
||||
Version 1.0.0rc4 (2002-08-03)
|
||||
* Release candidate 4 for the 1.0.0 series.
|
||||
* Minor bug fixes.
|
||||
* Fix broken Win32 "make check".
|
||||
|
||||
Version 1.0.0rc3 (2002-08-02)
|
||||
* Release candidate 3 for the 1.0.0 series.
|
||||
* Fix bug where libsndfile was reading beyond the end of the data chunk.
|
||||
* Added on-the-fly header updates on write.
|
||||
* Fix a couple of documentation issues.
|
||||
|
||||
Version 1.0.0rc2 (2002-06-24)
|
||||
* Release candidate 2 for the 1.0.0 series.
|
||||
* Fix compile problem for Win32.
|
||||
|
||||
Version 1.0.0rc1 (2002-06-24)
|
||||
* Release candidate 1 for the 1.0.0 series.
|
||||
|
||||
Version 0.0.28 (2002-04-27)
|
||||
* Last offical release of 0.0.X series of the library.
|
||||
|
||||
Version 0.0.8 (1999-02-16)
|
||||
* First offical release.
|
||||
65
project/jni/sndfile/README
Normal file
65
project/jni/sndfile/README
Normal file
@@ -0,0 +1,65 @@
|
||||
This is libsndfile, 1.0.25
|
||||
|
||||
libsndfile is a library of C routines for reading and writing
|
||||
files containing sampled audio data.
|
||||
|
||||
The src/ directory contains the source code for library itself.
|
||||
|
||||
The doc/ directory contains the libsndfile documentation.
|
||||
|
||||
The examples/ directory contains examples of how to write code using
|
||||
libsndfile.
|
||||
|
||||
The tests/ directory contains programs which link against libsndfile
|
||||
and test its functionality.
|
||||
|
||||
The src/GSM610 directory contains code written by Jutta Degener and Carsten
|
||||
Bormann. Their original code can be found at :
|
||||
http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||
|
||||
The src/G72x directory contains code written and released by Sun Microsystems
|
||||
under a suitably free license.
|
||||
|
||||
|
||||
LINUX
|
||||
-----
|
||||
Whereever possible, you should use the packages supplied by your Linux
|
||||
distribution.
|
||||
|
||||
If you really do need to compile from source it should be as easy as:
|
||||
|
||||
./configure
|
||||
make
|
||||
make install
|
||||
|
||||
Since libsndfile optionally links against libFLAC, libogg and libvorbis, you
|
||||
will need to install appropriate versions of these libraries before running
|
||||
configure as above.
|
||||
|
||||
|
||||
UNIX
|
||||
----
|
||||
Compile as for Linux.
|
||||
|
||||
|
||||
Win32/Win64
|
||||
-----------
|
||||
The default Windows compilers are nowhere near compliant with the 1999 ISO
|
||||
C Standard and hence not able to compile libsndfile.
|
||||
|
||||
Please use the libsndfile binaries available on the libsndfile web site.
|
||||
|
||||
|
||||
MacOSX
|
||||
------
|
||||
Building on MacOSX should be the same as building it on any other Unix.
|
||||
|
||||
|
||||
CONTACTS
|
||||
--------
|
||||
|
||||
libsndfile was written by Erik de Castro Lopo (erikd AT mega-nerd DOT com).
|
||||
The libsndfile home page is at :
|
||||
|
||||
http://www.mega-nerd.com/libsndfile/
|
||||
|
||||
1
project/jni/sndfile/include/sndfile.h
Symbolic link
1
project/jni/sndfile/include/sndfile.h
Symbolic link
@@ -0,0 +1 @@
|
||||
../src/sndfile.h
|
||||
1
project/jni/sndfile/include/sndfile.hh
Symbolic link
1
project/jni/sndfile/include/sndfile.hh
Symbolic link
@@ -0,0 +1 @@
|
||||
../src/sndfile.hh
|
||||
50
project/jni/sndfile/src/G72x/ChangeLog
Normal file
50
project/jni/sndfile/src/G72x/ChangeLog
Normal file
@@ -0,0 +1,50 @@
|
||||
2001-06-05 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
|
||||
* g72x.c
|
||||
Added {} in function update () to prevent 'ambiguous else' warning messages.
|
||||
|
||||
2000-07-14 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
|
||||
* g72x.c
|
||||
Modified g72x_init_state () to fit in with the new structure of the code.
|
||||
Implemented g72x_encode_block () and g72x_decode_block ().
|
||||
|
||||
2000-07-12 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
|
||||
* g72x.h
|
||||
Moved nearly all definitions and function prototypes from this file have been
|
||||
moved to private.h.
|
||||
Added an enum defining the 4 different G72x ADPCM codecs.
|
||||
Added new function prototypes to define a cleaner interface to the encoder
|
||||
and decoder. This new interface also allows samples to be processed in blocks
|
||||
rather than on a sample by sample basis like the original code.
|
||||
|
||||
* private.h
|
||||
Added prototypes moved from g72x.h.
|
||||
Changed struct g72x_state to a typedef struct { .. } G72x_PRIVATE.
|
||||
Added fields to G72x_PRIVATE required for working on blocks of samples.
|
||||
|
||||
2000-06-07 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
|
||||
* g72x.c
|
||||
Fixed all compiler warnings.
|
||||
Removed functions tandem_adjust() which is not required by libsndfile.
|
||||
|
||||
* g721.c
|
||||
Fixed all compiler warnings.
|
||||
Removed functions tandem_adjust_alaw() and tandem_adjust_ulaw () which are not
|
||||
required by libsndfile.
|
||||
Removed second parameter to g721_encoder () which is not required.
|
||||
|
||||
* g72x.h
|
||||
Removed in_coding and out_coding parameters from all functions. These allowed
|
||||
g72x encoding/decoding to/from A-law or u-law and are not required by libsndfile.
|
||||
Removed unneeded defines for A-law, u-law and linear encoding.
|
||||
|
||||
* g723_16.c
|
||||
Removed second parameter (in_coding) for g723_16_encoder().
|
||||
Removed second parameter (out_coding) for g723_16_decoder().
|
||||
|
||||
* private.h
|
||||
New file containing prototypes and tyepdefs private to G72x code.
|
||||
|
||||
0
project/jni/sndfile/src/G72x/README
Normal file
0
project/jni/sndfile/src/G72x/README
Normal file
94
project/jni/sndfile/src/G72x/README.original
Normal file
94
project/jni/sndfile/src/G72x/README.original
Normal file
@@ -0,0 +1,94 @@
|
||||
The files in this directory comprise ANSI-C language reference implementations
|
||||
of the CCITT (International Telegraph and Telephone Consultative Committee)
|
||||
G.711, G.721 and G.723 voice compressions. They have been tested on Sun
|
||||
SPARCstations and passed 82 out of 84 test vectors published by CCITT
|
||||
(Dec. 20, 1988) for G.721 and G.723. [The two remaining test vectors,
|
||||
which the G.721 decoder implementation for u-law samples did not pass,
|
||||
may be in error because they are identical to two other vectors for G.723_40.]
|
||||
|
||||
This source code is released by Sun Microsystems, Inc. to the public domain.
|
||||
Please give your acknowledgement in product literature if this code is used
|
||||
in your product implementation.
|
||||
|
||||
Sun Microsystems supports some CCITT audio formats in Solaris 2.0 system
|
||||
software. However, Sun's implementations have been optimized for higher
|
||||
performance on SPARCstations.
|
||||
|
||||
|
||||
The source files for CCITT conversion routines in this directory are:
|
||||
|
||||
g72x.h header file for g721.c, g723_24.c and g723_40.c
|
||||
g711.c CCITT G.711 u-law and A-law compression
|
||||
g72x.c common denominator of G.721 and G.723 ADPCM codes
|
||||
g721.c CCITT G.721 32Kbps ADPCM coder (with g72x.c)
|
||||
g723_24.c CCITT G.723 24Kbps ADPCM coder (with g72x.c)
|
||||
g723_40.c CCITT G.723 40Kbps ADPCM coder (with g72x.c)
|
||||
|
||||
|
||||
Simple conversions between u-law, A-law, and 16-bit linear PCM are invoked
|
||||
as follows:
|
||||
|
||||
unsigned char ucode, acode;
|
||||
short pcm_val;
|
||||
|
||||
ucode = linear2ulaw(pcm_val);
|
||||
ucode = alaw2ulaw(acode);
|
||||
|
||||
acode = linear2alaw(pcm_val);
|
||||
acode = ulaw2alaw(ucode);
|
||||
|
||||
pcm_val = ulaw2linear(ucode);
|
||||
pcm_val = alaw2linear(acode);
|
||||
|
||||
|
||||
The other CCITT compression routines are invoked as follows:
|
||||
|
||||
#include "g72x.h"
|
||||
|
||||
struct g72x_state state;
|
||||
int sample, code;
|
||||
|
||||
g72x_init_state(&state);
|
||||
code = {g721,g723_24,g723_40}_encoder(sample, coding, &state);
|
||||
sample = {g721,g723_24,g723_40}_decoder(code, coding, &state);
|
||||
|
||||
where
|
||||
coding = AUDIO_ENCODING_ULAW for 8-bit u-law samples
|
||||
AUDIO_ENCODING_ALAW for 8-bit A-law samples
|
||||
AUDIO_ENCODING_LINEAR for 16-bit linear PCM samples
|
||||
|
||||
|
||||
|
||||
This directory also includes the following sample programs:
|
||||
|
||||
encode.c CCITT ADPCM encoder
|
||||
decode.c CCITT ADPCM decoder
|
||||
Makefile makefile for the sample programs
|
||||
|
||||
|
||||
The sample programs contain examples of how to call the various compression
|
||||
routines and pack/unpack the bits. The sample programs read byte streams from
|
||||
stdin and write to stdout. The input/output data is raw data (no file header
|
||||
or other identifying information is embedded). The sample programs are
|
||||
invoked as follows:
|
||||
|
||||
encode [-3|4|5] [-a|u|l] <infile >outfile
|
||||
decode [-3|4|5] [-a|u|l] <infile >outfile
|
||||
where:
|
||||
-3 encode to (decode from) G.723 24kbps (3-bit) data
|
||||
-4 encode to (decode from) G.721 32kbps (4-bit) data [the default]
|
||||
-5 encode to (decode from) G.723 40kbps (5-bit) data
|
||||
-a encode from (decode to) A-law data
|
||||
-u encode from (decode to) u-law data [the default]
|
||||
-l encode from (decode to) 16-bit linear data
|
||||
|
||||
Examples:
|
||||
# Read 16-bit linear and output G.721
|
||||
encode -4 -l <pcmfile >g721file
|
||||
|
||||
# Read 40Kbps G.723 and output A-law
|
||||
decode -5 -a <g723file >alawfile
|
||||
|
||||
# Compress and then decompress u-law data using 24Kbps G.723
|
||||
encode -3 <ulawin | deoced -3 >ulawout
|
||||
|
||||
155
project/jni/sndfile/src/G72x/g721.c
Normal file
155
project/jni/sndfile/src/G72x/g721.c
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g721.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g721_encoder(), g721_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.721 ADPCM
|
||||
* coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which
|
||||
* take advantage of work station attributes, such as hardware 2's
|
||||
* complement arithmetic and large memory. Specifically, certain time
|
||||
* consuming operations such as multiplications are replaced
|
||||
* with lookup tables and software 2's complement operations are
|
||||
* replaced with hardware 2's complement.
|
||||
*
|
||||
* The deviation from the bit level specification (lookup tables)
|
||||
* preserves the bit level performance specifications.
|
||||
*
|
||||
* As outlined in the G.721 Recommendation, the algorithm is broken
|
||||
* down into modules. Each section of code below is preceded by
|
||||
* the name of the module which it is implementing.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "g72x.h"
|
||||
#include "g72x_priv.h"
|
||||
|
||||
static short qtab_721[7] = {-124, 80, 178, 246, 300, 349, 400};
|
||||
/*
|
||||
* Maps G.721 code word to reconstructed scale factor normalized log
|
||||
* magnitude values.
|
||||
*/
|
||||
static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
|
||||
425, 373, 323, 273, 213, 135, 4, -2048};
|
||||
|
||||
/* Maps G.721 code word to log of scale factor multiplier. */
|
||||
static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
|
||||
1122, 355, 198, 112, 64, 41, 18, -12};
|
||||
/*
|
||||
* Maps G.721 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
|
||||
0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
|
||||
|
||||
/*
|
||||
* g721_encoder()
|
||||
*
|
||||
* Encodes the input vale of linear PCM, A-law or u-law data sl and returns
|
||||
* the resulting code. -1 is returned for unknown input coding value.
|
||||
*/
|
||||
int
|
||||
g721_encoder(
|
||||
int sl,
|
||||
G72x_STATE *state_ptr)
|
||||
{
|
||||
short sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short sr; /* ADDB */
|
||||
short y; /* MIX */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
/* linearize input sample to 14-bit PCM */
|
||||
sl >>= 2; /* 14-bit dynamic range */
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
se = (sezi + predictor_pole(state_ptr)) >> 1; /* estimated signal */
|
||||
|
||||
d = sl - se; /* estimation difference */
|
||||
|
||||
/* quantize the prediction difference */
|
||||
y = step_size(state_ptr); /* quantizer step size */
|
||||
i = quantize(d, y, qtab_721, 7); /* i = ADPCM code */
|
||||
|
||||
dq = reconstruct(i & 8, _dqlntab[i], y); /* quantized est diff */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconst. signal */
|
||||
|
||||
dqsez = sr + sez - se; /* pole prediction diff. */
|
||||
|
||||
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g721_decoder()
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* Decodes a 4-bit code of G.721 encoded data of i and
|
||||
* returns the resulting linear PCM, A-law or u-law value.
|
||||
* return -1 for unknown out_coding value.
|
||||
*/
|
||||
int
|
||||
g721_decoder(
|
||||
int i,
|
||||
G72x_STATE *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x0f; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* dynamic quantizer step size */
|
||||
|
||||
dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(4, y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
/* sr was 14-bit dynamic range */
|
||||
return (sr << 2);
|
||||
}
|
||||
|
||||
162
project/jni/sndfile/src/G72x/g723_16.c
Normal file
162
project/jni/sndfile/src/G72x/g723_16.c
Normal file
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
/* 16kbps version created, used 24kbps code and changing as little as possible.
|
||||
* G.726 specs are available from ITU's gopher or WWW site (http://www.itu.ch)
|
||||
* If any errors are found, please contact me at mrand@tamu.edu
|
||||
* -Marc Randolph
|
||||
*/
|
||||
|
||||
/*
|
||||
* g723_16.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g723_16_encoder(), g723_16_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.726 16 Kbps
|
||||
* ADPCM coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which take advantage
|
||||
* of workstation attributes, such as hardware 2's complement arithmetic.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "g72x.h"
|
||||
#include "g72x_priv.h"
|
||||
|
||||
/*
|
||||
* Maps G.723_16 code word to reconstructed scale factor normalized log
|
||||
* magnitude values. Comes from Table 11/G.726
|
||||
*/
|
||||
static short _dqlntab[4] = { 116, 365, 365, 116};
|
||||
|
||||
/* Maps G.723_16 code word to log of scale factor multiplier.
|
||||
*
|
||||
* _witab[4] is actually {-22 , 439, 439, -22}, but FILTD wants it
|
||||
* as WI << 5 (multiplied by 32), so we'll do that here
|
||||
*/
|
||||
static short _witab[4] = {-704, 14048, 14048, -704};
|
||||
|
||||
/*
|
||||
* Maps G.723_16 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
|
||||
/* Comes from FUNCTF */
|
||||
static short _fitab[4] = {0, 0xE00, 0xE00, 0};
|
||||
|
||||
/* Comes from quantizer decision level tables (Table 7/G.726)
|
||||
*/
|
||||
static short qtab_723_16[1] = {261};
|
||||
|
||||
|
||||
/*
|
||||
* g723_16_encoder()
|
||||
*
|
||||
* Encodes a linear PCM, A-law or u-law input sample and returns its 2-bit code.
|
||||
* Returns -1 if invalid input coding value.
|
||||
*/
|
||||
int
|
||||
g723_16_encoder(
|
||||
int sl,
|
||||
G72x_STATE *state_ptr)
|
||||
{
|
||||
short sei, sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
/* linearize input sample to 14-bit PCM */
|
||||
sl >>= 2; /* sl of 14-bit dynamic range */
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
d = sl - se; /* d = estimation diff. */
|
||||
|
||||
/* quantize prediction difference d */
|
||||
y = step_size(state_ptr); /* quantizer step size */
|
||||
i = quantize(d, y, qtab_723_16, 1); /* i = ADPCM code */
|
||||
|
||||
/* Since quantize() only produces a three level output
|
||||
* (1, 2, or 3), we must create the fourth one on our own
|
||||
*/
|
||||
if (i == 3) /* i code for the zero region */
|
||||
if ((d & 0x8000) == 0) /* If d > 0, i=3 isn't right... */
|
||||
i = 0;
|
||||
|
||||
dq = reconstruct(i & 2, _dqlntab[i], y); /* quantized diff. */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
|
||||
|
||||
dqsez = sr + sez - se; /* pole prediction diff. */
|
||||
|
||||
update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g723_16_decoder()
|
||||
*
|
||||
* Decodes a 2-bit CCITT G.723_16 ADPCM code and returns
|
||||
* the resulting 16-bit linear PCM, A-law or u-law sample value.
|
||||
* -1 is returned if the output coding is unknown.
|
||||
*/
|
||||
int
|
||||
g723_16_decoder(
|
||||
int i,
|
||||
G72x_STATE *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x03; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
dq = reconstruct(i & 0x02, _dqlntab[i], y); /* unquantize pred diff */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(2, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
/* sr was of 14-bit dynamic range */
|
||||
return (sr << 2);
|
||||
}
|
||||
|
||||
139
project/jni/sndfile/src/G72x/g723_24.c
Normal file
139
project/jni/sndfile/src/G72x/g723_24.c
Normal file
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g723_24.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g723_24_encoder(), g723_24_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.723 24 Kbps
|
||||
* ADPCM coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which take advantage
|
||||
* of workstation attributes, such as hardware 2's complement arithmetic.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "g72x.h"
|
||||
#include "g72x_priv.h"
|
||||
|
||||
/*
|
||||
* Maps G.723_24 code word to reconstructed scale factor normalized log
|
||||
* magnitude values.
|
||||
*/
|
||||
static short _dqlntab[8] = {-2048, 135, 273, 373, 373, 273, 135, -2048};
|
||||
|
||||
/* Maps G.723_24 code word to log of scale factor multiplier. */
|
||||
static short _witab[8] = {-128, 960, 4384, 18624, 18624, 4384, 960, -128};
|
||||
|
||||
/*
|
||||
* Maps G.723_24 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
static short _fitab[8] = {0, 0x200, 0x400, 0xE00, 0xE00, 0x400, 0x200, 0};
|
||||
|
||||
static short qtab_723_24[3] = {8, 218, 331};
|
||||
|
||||
/*
|
||||
* g723_24_encoder()
|
||||
*
|
||||
* Encodes a linear PCM, A-law or u-law input sample and returns its 3-bit code.
|
||||
* Returns -1 if invalid input coding value.
|
||||
*/
|
||||
int
|
||||
g723_24_encoder(
|
||||
int sl,
|
||||
G72x_STATE *state_ptr)
|
||||
{
|
||||
short sei, sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
/* linearize input sample to 14-bit PCM */
|
||||
sl >>= 2; /* sl of 14-bit dynamic range */
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
d = sl - se; /* d = estimation diff. */
|
||||
|
||||
/* quantize prediction difference d */
|
||||
y = step_size(state_ptr); /* quantizer step size */
|
||||
i = quantize(d, y, qtab_723_24, 3); /* i = ADPCM code */
|
||||
dq = reconstruct(i & 4, _dqlntab[i], y); /* quantized diff. */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x3FFF) : se + dq; /* reconstructed signal */
|
||||
|
||||
dqsez = sr + sez - se; /* pole prediction diff. */
|
||||
|
||||
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g723_24_decoder()
|
||||
*
|
||||
* Decodes a 3-bit CCITT G.723_24 ADPCM code and returns
|
||||
* the resulting 16-bit linear PCM, A-law or u-law sample value.
|
||||
* -1 is returned if the output coding is unknown.
|
||||
*/
|
||||
int
|
||||
g723_24_decoder(
|
||||
int i,
|
||||
G72x_STATE *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x07; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
dq = reconstruct(i & 0x04, _dqlntab[i], y); /* unquantize pred diff */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : (se + dq); /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(3, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (sr << 2); /* sr was of 14-bit dynamic range */
|
||||
}
|
||||
|
||||
153
project/jni/sndfile/src/G72x/g723_40.c
Normal file
153
project/jni/sndfile/src/G72x/g723_40.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g723_40.c
|
||||
*
|
||||
* Description:
|
||||
*
|
||||
* g723_40_encoder(), g723_40_decoder()
|
||||
*
|
||||
* These routines comprise an implementation of the CCITT G.723 40Kbps
|
||||
* ADPCM coding algorithm. Essentially, this implementation is identical to
|
||||
* the bit level description except for a few deviations which
|
||||
* take advantage of workstation attributes, such as hardware 2's
|
||||
* complement arithmetic.
|
||||
*
|
||||
* The deviation from the bit level specification (lookup tables),
|
||||
* preserves the bit level performance specifications.
|
||||
*
|
||||
* As outlined in the G.723 Recommendation, the algorithm is broken
|
||||
* down into modules. Each section of code below is preceded by
|
||||
* the name of the module which it is implementing.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "g72x.h"
|
||||
#include "g72x_priv.h"
|
||||
|
||||
/*
|
||||
* Maps G.723_40 code word to ructeconstructed scale factor normalized log
|
||||
* magnitude values.
|
||||
*/
|
||||
static short _dqlntab[32] = {-2048, -66, 28, 104, 169, 224, 274, 318,
|
||||
358, 395, 429, 459, 488, 514, 539, 566,
|
||||
566, 539, 514, 488, 459, 429, 395, 358,
|
||||
318, 274, 224, 169, 104, 28, -66, -2048};
|
||||
|
||||
/* Maps G.723_40 code word to log of scale factor multiplier. */
|
||||
static short _witab[32] = {448, 448, 768, 1248, 1280, 1312, 1856, 3200,
|
||||
4512, 5728, 7008, 8960, 11456, 14080, 16928, 22272,
|
||||
22272, 16928, 14080, 11456, 8960, 7008, 5728, 4512,
|
||||
3200, 1856, 1312, 1280, 1248, 768, 448, 448};
|
||||
|
||||
/*
|
||||
* Maps G.723_40 code words to a set of values whose long and short
|
||||
* term averages are computed and then compared to give an indication
|
||||
* how stationary (steady state) the signal is.
|
||||
*/
|
||||
static short _fitab[32] = {0, 0, 0, 0, 0, 0x200, 0x200, 0x200,
|
||||
0x200, 0x200, 0x400, 0x600, 0x800, 0xA00, 0xC00, 0xC00,
|
||||
0xC00, 0xC00, 0xA00, 0x800, 0x600, 0x400, 0x200, 0x200,
|
||||
0x200, 0x200, 0x200, 0, 0, 0, 0, 0};
|
||||
|
||||
static short qtab_723_40[15] = {-122, -16, 68, 139, 198, 250, 298, 339,
|
||||
378, 413, 445, 475, 502, 528, 553};
|
||||
|
||||
/*
|
||||
* g723_40_encoder()
|
||||
*
|
||||
* Encodes a 16-bit linear PCM, A-law or u-law input sample and retuens
|
||||
* the resulting 5-bit CCITT G.723 40Kbps code.
|
||||
* Returns -1 if the input coding value is invalid.
|
||||
*/
|
||||
int g723_40_encoder (int sl, G72x_STATE *state_ptr)
|
||||
{
|
||||
short sei, sezi, se, sez; /* ACCUM */
|
||||
short d; /* SUBTA */
|
||||
short y; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dqsez; /* ADDC */
|
||||
short dq, i;
|
||||
|
||||
/* linearize input sample to 14-bit PCM */
|
||||
sl >>= 2; /* sl of 14-bit dynamic range */
|
||||
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
d = sl - se; /* d = estimation difference */
|
||||
|
||||
/* quantize prediction difference */
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
i = quantize(d, y, qtab_723_40, 15); /* i = ADPCM code */
|
||||
|
||||
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* quantized diff */
|
||||
|
||||
sr = (dq < 0) ? se - (dq & 0x7FFF) : se + dq; /* reconstructed signal */
|
||||
|
||||
dqsez = sr + sez - se; /* dqsez = pole prediction diff. */
|
||||
|
||||
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* g723_40_decoder()
|
||||
*
|
||||
* Decodes a 5-bit CCITT G.723 40Kbps code and returns
|
||||
* the resulting 16-bit linear PCM, A-law or u-law sample value.
|
||||
* -1 is returned if the output coding is unknown.
|
||||
*/
|
||||
int g723_40_decoder (int i, G72x_STATE *state_ptr)
|
||||
{
|
||||
short sezi, sei, sez, se; /* ACCUM */
|
||||
short y ; /* MIX */
|
||||
short sr; /* ADDB */
|
||||
short dq;
|
||||
short dqsez;
|
||||
|
||||
i &= 0x1f; /* mask to get proper bits */
|
||||
sezi = predictor_zero(state_ptr);
|
||||
sez = sezi >> 1;
|
||||
sei = sezi + predictor_pole(state_ptr);
|
||||
se = sei >> 1; /* se = estimated signal */
|
||||
|
||||
y = step_size(state_ptr); /* adaptive quantizer step size */
|
||||
dq = reconstruct(i & 0x10, _dqlntab[i], y); /* estimation diff. */
|
||||
|
||||
sr = (dq < 0) ? (se - (dq & 0x7FFF)) : (se + dq); /* reconst. signal */
|
||||
|
||||
dqsez = sr - se + sez; /* pole prediction diff. */
|
||||
|
||||
update(5, y, _witab[i], _fitab[i], dq, sr, dqsez, state_ptr);
|
||||
|
||||
return (sr << 2); /* sr was of 14-bit dynamic range */
|
||||
}
|
||||
|
||||
644
project/jni/sndfile/src/G72x/g72x.c
Normal file
644
project/jni/sndfile/src/G72x/g72x.c
Normal file
@@ -0,0 +1,644 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
/*
|
||||
* g72x.c
|
||||
*
|
||||
* Common routines for G.721 and G.723 conversions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "g72x.h"
|
||||
#include "g72x_priv.h"
|
||||
|
||||
static G72x_STATE * g72x_state_new (void) ;
|
||||
static int unpack_bytes (int bits, int blocksize, const unsigned char * block, short * samples) ;
|
||||
static int pack_bytes (int bits, const short * samples, unsigned char * block) ;
|
||||
|
||||
static
|
||||
short power2 [15] =
|
||||
{ 1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
|
||||
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000
|
||||
} ;
|
||||
|
||||
/*
|
||||
* quan()
|
||||
*
|
||||
* quantizes the input val against the table of size short integers.
|
||||
* It returns i if table[i - 1] <= val < table[i].
|
||||
*
|
||||
* Using linear search for simple coding.
|
||||
*/
|
||||
static
|
||||
int quan (int val, short *table, int size)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < size; i++)
|
||||
if (val < *table++)
|
||||
break;
|
||||
return (i);
|
||||
}
|
||||
|
||||
/*
|
||||
* fmult()
|
||||
*
|
||||
* returns the integer product of the 14-bit integer "an" and
|
||||
* "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
|
||||
*/
|
||||
static
|
||||
int fmult (int an, int srn)
|
||||
{
|
||||
short anmag, anexp, anmant;
|
||||
short wanexp, wanmant;
|
||||
short retval;
|
||||
|
||||
anmag = (an > 0) ? an : ((-an) & 0x1FFF);
|
||||
anexp = quan(anmag, power2, 15) - 6;
|
||||
anmant = (anmag == 0) ? 32 :
|
||||
(anexp >= 0) ? anmag >> anexp : anmag << -anexp;
|
||||
wanexp = anexp + ((srn >> 6) & 0xF) - 13;
|
||||
|
||||
/*
|
||||
** The original was :
|
||||
** wanmant = (anmant * (srn & 0x3F) + 0x30) >> 4 ;
|
||||
** but could see no valid reason for the + 0x30.
|
||||
** Removed it and it improved the SNR of the codec.
|
||||
*/
|
||||
|
||||
wanmant = (anmant * (srn & 0x3F)) >> 4 ;
|
||||
|
||||
retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
|
||||
(wanmant >> -wanexp);
|
||||
|
||||
return (((an ^ srn) < 0) ? -retval : retval);
|
||||
}
|
||||
|
||||
static G72x_STATE * g72x_state_new (void)
|
||||
{ return calloc (1, sizeof (G72x_STATE)) ;
|
||||
}
|
||||
|
||||
/*
|
||||
* private_init_state()
|
||||
*
|
||||
* This routine initializes and/or resets the G72x_PRIVATE structure
|
||||
* pointed to by 'state_ptr'.
|
||||
* All the initial state values are specified in the CCITT G.721 document.
|
||||
*/
|
||||
void private_init_state (G72x_STATE *state_ptr)
|
||||
{
|
||||
int cnta;
|
||||
|
||||
state_ptr->yl = 34816;
|
||||
state_ptr->yu = 544;
|
||||
state_ptr->dms = 0;
|
||||
state_ptr->dml = 0;
|
||||
state_ptr->ap = 0;
|
||||
for (cnta = 0; cnta < 2; cnta++) {
|
||||
state_ptr->a[cnta] = 0;
|
||||
state_ptr->pk[cnta] = 0;
|
||||
state_ptr->sr[cnta] = 32;
|
||||
}
|
||||
for (cnta = 0; cnta < 6; cnta++) {
|
||||
state_ptr->b[cnta] = 0;
|
||||
state_ptr->dq[cnta] = 32;
|
||||
}
|
||||
state_ptr->td = 0;
|
||||
} /* private_init_state */
|
||||
|
||||
struct g72x_state * g72x_reader_init (int codec, int *blocksize, int *samplesperblock)
|
||||
{ G72x_STATE *pstate ;
|
||||
|
||||
if ((pstate = g72x_state_new ()) == NULL)
|
||||
return NULL ;
|
||||
|
||||
private_init_state (pstate) ;
|
||||
|
||||
pstate->encoder = NULL ;
|
||||
|
||||
switch (codec)
|
||||
{ case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */
|
||||
pstate->decoder = g723_16_decoder ;
|
||||
*blocksize = G723_16_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 2 ;
|
||||
pstate->blocksize = G723_16_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */
|
||||
pstate->decoder = g723_24_decoder ;
|
||||
*blocksize = G723_24_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 3 ;
|
||||
pstate->blocksize = G723_24_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */
|
||||
pstate->decoder = g721_decoder ;
|
||||
*blocksize = G721_32_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 4 ;
|
||||
pstate->blocksize = G721_32_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */
|
||||
pstate->decoder = g723_40_decoder ;
|
||||
*blocksize = G721_40_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 5 ;
|
||||
pstate->blocksize = G721_40_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
free (pstate) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
return pstate ;
|
||||
} /* g72x_reader_init */
|
||||
|
||||
struct g72x_state * g72x_writer_init (int codec, int *blocksize, int *samplesperblock)
|
||||
{ G72x_STATE *pstate ;
|
||||
|
||||
if ((pstate = g72x_state_new ()) == NULL)
|
||||
return NULL ;
|
||||
|
||||
private_init_state (pstate) ;
|
||||
pstate->decoder = NULL ;
|
||||
|
||||
switch (codec)
|
||||
{ case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */
|
||||
pstate->encoder = g723_16_encoder ;
|
||||
*blocksize = G723_16_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 2 ;
|
||||
pstate->blocksize = G723_16_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */
|
||||
pstate->encoder = g723_24_encoder ;
|
||||
*blocksize = G723_24_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 3 ;
|
||||
pstate->blocksize = G723_24_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */
|
||||
pstate->encoder = g721_encoder ;
|
||||
*blocksize = G721_32_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 4 ;
|
||||
pstate->blocksize = G721_32_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */
|
||||
pstate->encoder = g723_40_encoder ;
|
||||
*blocksize = G721_40_BYTES_PER_BLOCK ;
|
||||
*samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
|
||||
pstate->codec_bits = 5 ;
|
||||
pstate->blocksize = G721_40_BYTES_PER_BLOCK ;
|
||||
pstate->samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
free (pstate) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
return pstate ;
|
||||
} /* g72x_writer_init */
|
||||
|
||||
int g72x_decode_block (G72x_STATE *pstate, const unsigned char *block, short *samples)
|
||||
{ int k, count ;
|
||||
|
||||
count = unpack_bytes (pstate->codec_bits, pstate->blocksize, block, samples) ;
|
||||
|
||||
for (k = 0 ; k < count ; k++)
|
||||
samples [k] = pstate->decoder (samples [k], pstate) ;
|
||||
|
||||
return 0 ;
|
||||
} /* g72x_decode_block */
|
||||
|
||||
int g72x_encode_block (G72x_STATE *pstate, short *samples, unsigned char *block)
|
||||
{ int k, count ;
|
||||
|
||||
for (k = 0 ; k < pstate->samplesperblock ; k++)
|
||||
samples [k] = pstate->encoder (samples [k], pstate) ;
|
||||
|
||||
count = pack_bytes (pstate->codec_bits, samples, block) ;
|
||||
|
||||
return count ;
|
||||
} /* g72x_encode_block */
|
||||
|
||||
/*
|
||||
* predictor_zero()
|
||||
*
|
||||
* computes the estimated signal from 6-zero predictor.
|
||||
*
|
||||
*/
|
||||
int predictor_zero (G72x_STATE *state_ptr)
|
||||
{
|
||||
int i;
|
||||
int sezi;
|
||||
|
||||
sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
|
||||
for (i = 1; i < 6; i++) /* ACCUM */
|
||||
sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
|
||||
return (sezi);
|
||||
}
|
||||
/*
|
||||
* predictor_pole()
|
||||
*
|
||||
* computes the estimated signal from 2-pole predictor.
|
||||
*
|
||||
*/
|
||||
int predictor_pole(G72x_STATE *state_ptr)
|
||||
{
|
||||
return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
|
||||
fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
|
||||
}
|
||||
/*
|
||||
* step_size()
|
||||
*
|
||||
* computes the quantization step size of the adaptive quantizer.
|
||||
*
|
||||
*/
|
||||
int step_size (G72x_STATE *state_ptr)
|
||||
{
|
||||
int y;
|
||||
int dif;
|
||||
int al;
|
||||
|
||||
if (state_ptr->ap >= 256)
|
||||
return (state_ptr->yu);
|
||||
else {
|
||||
y = state_ptr->yl >> 6;
|
||||
dif = state_ptr->yu - y;
|
||||
al = state_ptr->ap >> 2;
|
||||
if (dif > 0)
|
||||
y += (dif * al) >> 6;
|
||||
else if (dif < 0)
|
||||
y += (dif * al + 0x3F) >> 6;
|
||||
return (y);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* quantize()
|
||||
*
|
||||
* Given a raw sample, 'd', of the difference signal and a
|
||||
* quantization step size scale factor, 'y', this routine returns the
|
||||
* ADPCM codeword to which that sample gets quantized. The step
|
||||
* size scale factor division operation is done in the log base 2 domain
|
||||
* as a subtraction.
|
||||
*/
|
||||
int quantize(
|
||||
int d, /* Raw difference signal sample */
|
||||
int y, /* Step size multiplier */
|
||||
short *table, /* quantization table */
|
||||
int size) /* table size of short integers */
|
||||
{
|
||||
short dqm; /* Magnitude of 'd' */
|
||||
short expon; /* Integer part of base 2 log of 'd' */
|
||||
short mant; /* Fractional part of base 2 log */
|
||||
short dl; /* Log of magnitude of 'd' */
|
||||
short dln; /* Step size scale factor normalized log */
|
||||
int i;
|
||||
|
||||
/*
|
||||
* LOG
|
||||
*
|
||||
* Compute base 2 log of 'd', and store in 'dl'.
|
||||
*/
|
||||
dqm = abs(d);
|
||||
expon = quan(dqm >> 1, power2, 15);
|
||||
mant = ((dqm << 7) >> expon) & 0x7F; /* Fractional portion. */
|
||||
dl = (expon << 7) + mant;
|
||||
|
||||
/*
|
||||
* SUBTB
|
||||
*
|
||||
* "Divide" by step size multiplier.
|
||||
*/
|
||||
dln = dl - (y >> 2);
|
||||
|
||||
/*
|
||||
* QUAN
|
||||
*
|
||||
* Obtain codword i for 'd'.
|
||||
*/
|
||||
i = quan(dln, table, size);
|
||||
if (d < 0) /* take 1's complement of i */
|
||||
return ((size << 1) + 1 - i);
|
||||
else if (i == 0) /* take 1's complement of 0 */
|
||||
return ((size << 1) + 1); /* new in 1988 */
|
||||
else
|
||||
return (i);
|
||||
}
|
||||
/*
|
||||
* reconstruct()
|
||||
*
|
||||
* Returns reconstructed difference signal 'dq' obtained from
|
||||
* codeword 'i' and quantization step size scale factor 'y'.
|
||||
* Multiplication is performed in log base 2 domain as addition.
|
||||
*/
|
||||
int
|
||||
reconstruct(
|
||||
int sign, /* 0 for non-negative value */
|
||||
int dqln, /* G.72x codeword */
|
||||
int y) /* Step size multiplier */
|
||||
{
|
||||
short dql; /* Log of 'dq' magnitude */
|
||||
short dex; /* Integer part of log */
|
||||
short dqt;
|
||||
short dq; /* Reconstructed difference signal sample */
|
||||
|
||||
dql = dqln + (y >> 2); /* ADDA */
|
||||
|
||||
if (dql < 0) {
|
||||
return ((sign) ? -0x8000 : 0);
|
||||
} else { /* ANTILOG */
|
||||
dex = (dql >> 7) & 15;
|
||||
dqt = 128 + (dql & 127);
|
||||
dq = (dqt << 7) >> (14 - dex);
|
||||
return ((sign) ? (dq - 0x8000) : dq);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* update()
|
||||
*
|
||||
* updates the state variables for each output code
|
||||
*/
|
||||
void
|
||||
update(
|
||||
int code_size, /* distinguish 723_40 with others */
|
||||
int y, /* quantizer step size */
|
||||
int wi, /* scale factor multiplier */
|
||||
int fi, /* for long/short term energies */
|
||||
int dq, /* quantized prediction difference */
|
||||
int sr, /* reconstructed signal */
|
||||
int dqsez, /* difference from 2-pole predictor */
|
||||
G72x_STATE *state_ptr) /* coder state pointer */
|
||||
{
|
||||
int cnt;
|
||||
short mag, expon; /* Adaptive predictor, FLOAT A */
|
||||
short a2p = 0; /* LIMC */
|
||||
short a1ul; /* UPA1 */
|
||||
short pks1; /* UPA2 */
|
||||
short fa1;
|
||||
char tr; /* tone/transition detector */
|
||||
short ylint, thr2, dqthr;
|
||||
short ylfrac, thr1;
|
||||
short pk0;
|
||||
|
||||
pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
|
||||
|
||||
mag = dq & 0x7FFF; /* prediction difference magnitude */
|
||||
/* TRANS */
|
||||
ylint = state_ptr->yl >> 15; /* exponent part of yl */
|
||||
ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
|
||||
thr1 = (32 + ylfrac) << ylint; /* threshold */
|
||||
thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */
|
||||
dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */
|
||||
if (state_ptr->td == 0) /* signal supposed voice */
|
||||
tr = 0;
|
||||
else if (mag <= dqthr) /* supposed data, but small mag */
|
||||
tr = 0; /* treated as voice */
|
||||
else /* signal is data (modem) */
|
||||
tr = 1;
|
||||
|
||||
/*
|
||||
* Quantizer scale factor adaptation.
|
||||
*/
|
||||
|
||||
/* FUNCTW & FILTD & DELAY */
|
||||
/* update non-steady state step size multiplier */
|
||||
state_ptr->yu = y + ((wi - y) >> 5);
|
||||
|
||||
/* LIMB */
|
||||
if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */
|
||||
state_ptr->yu = 544;
|
||||
else if (state_ptr->yu > 5120)
|
||||
state_ptr->yu = 5120;
|
||||
|
||||
/* FILTE & DELAY */
|
||||
/* update steady state step size multiplier */
|
||||
state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
|
||||
|
||||
/*
|
||||
* Adaptive predictor coefficients.
|
||||
*/
|
||||
if (tr == 1) { /* reset a's and b's for modem signal */
|
||||
state_ptr->a[0] = 0;
|
||||
state_ptr->a[1] = 0;
|
||||
state_ptr->b[0] = 0;
|
||||
state_ptr->b[1] = 0;
|
||||
state_ptr->b[2] = 0;
|
||||
state_ptr->b[3] = 0;
|
||||
state_ptr->b[4] = 0;
|
||||
state_ptr->b[5] = 0;
|
||||
} else { /* update a's and b's */
|
||||
pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
|
||||
|
||||
/* update predictor pole a[1] */
|
||||
a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
|
||||
if (dqsez != 0) {
|
||||
fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
|
||||
if (fa1 < -8191) /* a2p = function of fa1 */
|
||||
a2p -= 0x100;
|
||||
else if (fa1 > 8191)
|
||||
a2p += 0xFF;
|
||||
else
|
||||
a2p += fa1 >> 5;
|
||||
|
||||
if (pk0 ^ state_ptr->pk[1])
|
||||
{ /* LIMC */
|
||||
if (a2p <= -12160)
|
||||
a2p = -12288;
|
||||
else if (a2p >= 12416)
|
||||
a2p = 12288;
|
||||
else
|
||||
a2p -= 0x80;
|
||||
}
|
||||
else if (a2p <= -12416)
|
||||
a2p = -12288;
|
||||
else if (a2p >= 12160)
|
||||
a2p = 12288;
|
||||
else
|
||||
a2p += 0x80;
|
||||
}
|
||||
|
||||
/* TRIGB & DELAY */
|
||||
state_ptr->a[1] = a2p;
|
||||
|
||||
/* UPA1 */
|
||||
/* update predictor pole a[0] */
|
||||
state_ptr->a[0] -= state_ptr->a[0] >> 8;
|
||||
if (dqsez != 0)
|
||||
{ if (pks1 == 0)
|
||||
state_ptr->a[0] += 192;
|
||||
else
|
||||
state_ptr->a[0] -= 192;
|
||||
} ;
|
||||
|
||||
/* LIMD */
|
||||
a1ul = 15360 - a2p;
|
||||
if (state_ptr->a[0] < -a1ul)
|
||||
state_ptr->a[0] = -a1ul;
|
||||
else if (state_ptr->a[0] > a1ul)
|
||||
state_ptr->a[0] = a1ul;
|
||||
|
||||
/* UPB : update predictor zeros b[6] */
|
||||
for (cnt = 0; cnt < 6; cnt++) {
|
||||
if (code_size == 5) /* for 40Kbps G.723 */
|
||||
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;
|
||||
else /* for G.721 and 24Kbps G.723 */
|
||||
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
|
||||
if (dq & 0x7FFF) { /* XOR */
|
||||
if ((dq ^ state_ptr->dq[cnt]) >= 0)
|
||||
state_ptr->b[cnt] += 128;
|
||||
else
|
||||
state_ptr->b[cnt] -= 128;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (cnt = 5; cnt > 0; cnt--)
|
||||
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
|
||||
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
|
||||
if (mag == 0) {
|
||||
state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
|
||||
} else {
|
||||
expon = quan(mag, power2, 15);
|
||||
state_ptr->dq[0] = (dq >= 0) ?
|
||||
(expon << 6) + ((mag << 6) >> expon) :
|
||||
(expon << 6) + ((mag << 6) >> expon) - 0x400;
|
||||
}
|
||||
|
||||
state_ptr->sr[1] = state_ptr->sr[0];
|
||||
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
|
||||
if (sr == 0) {
|
||||
state_ptr->sr[0] = 0x20;
|
||||
} else if (sr > 0) {
|
||||
expon = quan(sr, power2, 15);
|
||||
state_ptr->sr[0] = (expon << 6) + ((sr << 6) >> expon);
|
||||
} else if (sr > -32768) {
|
||||
mag = -sr;
|
||||
expon = quan(mag, power2, 15);
|
||||
state_ptr->sr[0] = (expon << 6) + ((mag << 6) >> expon) - 0x400;
|
||||
} else
|
||||
state_ptr->sr[0] = (short) 0xFC20;
|
||||
|
||||
/* DELAY A */
|
||||
state_ptr->pk[1] = state_ptr->pk[0];
|
||||
state_ptr->pk[0] = pk0;
|
||||
|
||||
/* TONE */
|
||||
if (tr == 1) /* this sample has been treated as data */
|
||||
state_ptr->td = 0; /* next one will be treated as voice */
|
||||
else if (a2p < -11776) /* small sample-to-sample correlation */
|
||||
state_ptr->td = 1; /* signal may be data */
|
||||
else /* signal is voice */
|
||||
state_ptr->td = 0;
|
||||
|
||||
/*
|
||||
* Adaptation speed control.
|
||||
*/
|
||||
state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
|
||||
state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
|
||||
|
||||
if (tr == 1)
|
||||
state_ptr->ap = 256;
|
||||
else if (y < 1536) /* SUBTC */
|
||||
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
|
||||
else if (state_ptr->td == 1)
|
||||
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
|
||||
else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
|
||||
(state_ptr->dml >> 3))
|
||||
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
|
||||
else
|
||||
state_ptr->ap += (-state_ptr->ap) >> 4;
|
||||
|
||||
return ;
|
||||
} /* update */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
unpack_bytes (int bits, int blocksize, const unsigned char * block, short * samples)
|
||||
{ unsigned int in_buffer = 0 ;
|
||||
unsigned char in_byte ;
|
||||
int k, in_bits = 0, bindex = 0 ;
|
||||
|
||||
for (k = 0 ; bindex <= blocksize && k < G72x_BLOCK_SIZE ; k++)
|
||||
{ if (in_bits < bits)
|
||||
{ in_byte = block [bindex++] ;
|
||||
|
||||
in_buffer |= (in_byte << in_bits);
|
||||
in_bits += 8;
|
||||
}
|
||||
samples [k] = in_buffer & ((1 << bits) - 1);
|
||||
in_buffer >>= bits;
|
||||
in_bits -= bits;
|
||||
} ;
|
||||
|
||||
return k ;
|
||||
} /* unpack_bytes */
|
||||
|
||||
static int
|
||||
pack_bytes (int bits, const short * samples, unsigned char * block)
|
||||
{
|
||||
unsigned int out_buffer = 0 ;
|
||||
int k, bindex = 0, out_bits = 0 ;
|
||||
unsigned char out_byte ;
|
||||
|
||||
for (k = 0 ; k < G72x_BLOCK_SIZE ; k++)
|
||||
{ out_buffer |= (samples [k] << out_bits) ;
|
||||
out_bits += bits ;
|
||||
if (out_bits >= 8)
|
||||
{ out_byte = out_buffer & 0xFF ;
|
||||
out_bits -= 8 ;
|
||||
out_buffer >>= 8 ;
|
||||
block [bindex++] = out_byte ;
|
||||
}
|
||||
} ;
|
||||
|
||||
return bindex ;
|
||||
} /* pack_bytes */
|
||||
|
||||
91
project/jni/sndfile/src/G72x/g72x.h
Normal file
91
project/jni/sndfile/src/G72x/g72x.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** This file is not the same as the original file from Sun Microsystems. Nearly
|
||||
** all the original definitions and function prototypes that were in the file
|
||||
** of this name have been moved to g72x_priv.h.
|
||||
*/
|
||||
|
||||
#ifndef G72X_HEADER_FILE
|
||||
#define G72X_HEADER_FILE
|
||||
|
||||
/*
|
||||
** Number of samples per block to process.
|
||||
** Must be a common multiple of possible bits per sample : 2, 3, 4, 5 and 8.
|
||||
*/
|
||||
#define G72x_BLOCK_SIZE (3 * 5 * 8)
|
||||
|
||||
/*
|
||||
** Identifiers for the differing kinds of G72x ADPCM codecs.
|
||||
** The identifiers also define the number of encoded bits per sample.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ G723_16_BITS_PER_SAMPLE = 2,
|
||||
G723_24_BITS_PER_SAMPLE = 3,
|
||||
G723_40_BITS_PER_SAMPLE = 5,
|
||||
|
||||
G721_32_BITS_PER_SAMPLE = 4,
|
||||
G721_40_BITS_PER_SAMPLE = 5,
|
||||
|
||||
G723_16_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE,
|
||||
G723_24_SAMPLES_PER_BLOCK = G723_24_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_24_BITS_PER_SAMPLE),
|
||||
G723_40_SAMPLES_PER_BLOCK = G723_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G723_40_BITS_PER_SAMPLE),
|
||||
|
||||
G721_32_SAMPLES_PER_BLOCK = G72x_BLOCK_SIZE,
|
||||
G721_40_SAMPLES_PER_BLOCK = G721_40_BITS_PER_SAMPLE * (G72x_BLOCK_SIZE / G721_40_BITS_PER_SAMPLE),
|
||||
|
||||
G723_16_BYTES_PER_BLOCK = (G723_16_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
|
||||
G723_24_BYTES_PER_BLOCK = (G723_24_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
|
||||
G723_40_BYTES_PER_BLOCK = (G723_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
|
||||
|
||||
G721_32_BYTES_PER_BLOCK = (G721_32_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8,
|
||||
G721_40_BYTES_PER_BLOCK = (G721_40_BITS_PER_SAMPLE * G72x_BLOCK_SIZE) / 8
|
||||
} ;
|
||||
|
||||
/* Forward declaration of of g72x_state. */
|
||||
|
||||
struct g72x_state ;
|
||||
|
||||
/* External function definitions. */
|
||||
|
||||
struct g72x_state * g72x_reader_init (int codec, int *blocksize, int *samplesperblock) ;
|
||||
struct g72x_state * g72x_writer_init (int codec, int *blocksize, int *samplesperblock) ;
|
||||
/*
|
||||
** Initialize the ADPCM state table for the given codec.
|
||||
** Return 0 on success, 1 on fail.
|
||||
*/
|
||||
|
||||
int g72x_decode_block (struct g72x_state *pstate, const unsigned char *block, short *samples) ;
|
||||
/*
|
||||
** The caller fills data->block with data->bytes bytes before calling the
|
||||
** function. The value data->bytes must be an integer multiple of
|
||||
** data->blocksize and be <= data->max_bytes.
|
||||
** When it returns, the caller can read out data->samples samples.
|
||||
*/
|
||||
|
||||
int g72x_encode_block (struct g72x_state *pstate, short *samples, unsigned char *block) ;
|
||||
/*
|
||||
** The caller fills state->samples some integer multiple data->samples_per_block
|
||||
** (up to G72x_BLOCK_SIZE) samples before calling the function.
|
||||
** When it returns, the caller can read out bytes encoded bytes.
|
||||
*/
|
||||
|
||||
#endif /* !G72X_HEADER_FILE */
|
||||
|
||||
109
project/jni/sndfile/src/G72x/g72x_priv.h
Normal file
109
project/jni/sndfile/src/G72x/g72x_priv.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This source code is a product of Sun Microsystems, Inc. and is provided
|
||||
* for unrestricted use. Users may copy or modify this source code without
|
||||
* charge.
|
||||
*
|
||||
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
|
||||
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
|
||||
*
|
||||
* Sun source code is provided with no support and without any obligation on
|
||||
* the part of Sun Microsystems, Inc. to assist in its use, correction,
|
||||
* modification or enhancement.
|
||||
*
|
||||
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
|
||||
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
|
||||
* OR ANY PART THEREOF.
|
||||
*
|
||||
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
|
||||
* or profits or other special, indirect and consequential damages, even if
|
||||
* Sun has been advised of the possibility of such damages.
|
||||
*
|
||||
* Sun Microsystems, Inc.
|
||||
* 2550 Garcia Avenue
|
||||
* Mountain View, California 94043
|
||||
*/
|
||||
|
||||
#ifndef G72X_PRIVATE_H
|
||||
#define G72X_PRIVATE_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
#error "This code is not designed to be compiled with a C++ compiler."
|
||||
#endif
|
||||
|
||||
/*
|
||||
** The following is the definition of the state structure used by the
|
||||
** G.721/G.723 encoder and decoder to preserve their internal state
|
||||
** between successive calls. The meanings of the majority of the state
|
||||
** structure fields are explained in detail in the CCITT Recommendation
|
||||
** G.721. The field names are essentially identical to variable names
|
||||
** in the bit level description of the coding algorithm included in this
|
||||
** Recommendation.
|
||||
*/
|
||||
|
||||
struct g72x_state
|
||||
{ long yl; /* Locked or steady state step size multiplier. */
|
||||
short yu; /* Unlocked or non-steady state step size multiplier. */
|
||||
short dms; /* Short term energy estimate. */
|
||||
short dml; /* Long term energy estimate. */
|
||||
short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */
|
||||
|
||||
short a[2]; /* Coefficients of pole portion of prediction filter. */
|
||||
short b[6]; /* Coefficients of zero portion of prediction filter. */
|
||||
short pk[2]; /*
|
||||
** Signs of previous two samples of a partially
|
||||
** reconstructed signal.
|
||||
**/
|
||||
short dq[6]; /*
|
||||
** Previous 6 samples of the quantized difference
|
||||
** signal represented in an internal floating point
|
||||
** format.
|
||||
**/
|
||||
short sr[2]; /*
|
||||
** Previous 2 samples of the quantized difference
|
||||
** signal represented in an internal floating point
|
||||
** format.
|
||||
*/
|
||||
char td; /* delayed tone detect, new in 1988 version */
|
||||
|
||||
/* The following struct members were added for libsndfile. The original
|
||||
** code worked by calling a set of functions on a sample by sample basis
|
||||
** which is slow on architectures like Intel x86. For libsndfile, this
|
||||
** was changed so that the encoding and decoding routines could work on
|
||||
** a block of samples at a time to reduce the function call overhead.
|
||||
*/
|
||||
int (*encoder) (int, struct g72x_state* state) ;
|
||||
int (*decoder) (int, struct g72x_state* state) ;
|
||||
|
||||
int codec_bits, blocksize, samplesperblock ;
|
||||
} ;
|
||||
|
||||
typedef struct g72x_state G72x_STATE ;
|
||||
|
||||
int predictor_zero (G72x_STATE *state_ptr);
|
||||
|
||||
int predictor_pole (G72x_STATE *state_ptr);
|
||||
|
||||
int step_size (G72x_STATE *state_ptr);
|
||||
|
||||
int quantize (int d, int y, short *table, int size);
|
||||
|
||||
int reconstruct (int sign, int dqln, int y);
|
||||
|
||||
void update (int code_size, int y, int wi, int fi, int dq, int sr, int dqsez, G72x_STATE *state_ptr);
|
||||
|
||||
int g721_encoder (int sample, G72x_STATE *state_ptr);
|
||||
int g721_decoder (int code, G72x_STATE *state_ptr);
|
||||
|
||||
int g723_16_encoder (int sample, G72x_STATE *state_ptr);
|
||||
int g723_16_decoder (int code, G72x_STATE *state_ptr);
|
||||
|
||||
int g723_24_encoder (int sample, G72x_STATE *state_ptr);
|
||||
int g723_24_decoder (int code, G72x_STATE *state_ptr);
|
||||
|
||||
int g723_40_encoder (int sample, G72x_STATE *state_ptr);
|
||||
int g723_40_decoder (int code, G72x_STATE *state_ptr);
|
||||
|
||||
void private_init_state (G72x_STATE *state_ptr) ;
|
||||
|
||||
#endif /* G72X_PRIVATE_H */
|
||||
16
project/jni/sndfile/src/GSM610/COPYRIGHT
Normal file
16
project/jni/sndfile/src/GSM610/COPYRIGHT
Normal file
@@ -0,0 +1,16 @@
|
||||
Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universitaet Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
are deemed to have made any representations as to the suitability of this
|
||||
software for any purpose nor are held responsible for any defects of
|
||||
this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener
|
||||
Carsten Bormann
|
||||
56
project/jni/sndfile/src/GSM610/ChangeLog
Normal file
56
project/jni/sndfile/src/GSM610/ChangeLog
Normal file
@@ -0,0 +1,56 @@
|
||||
2004-05-12 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* gsm610_priv.h
|
||||
Replace ugly macros with inline functions.
|
||||
|
||||
* *.c
|
||||
Remove temporary variables used by macros and other minor fixes required by
|
||||
above change.
|
||||
|
||||
2003-06-02 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* rpe.c
|
||||
Renamed variables "exp" to "expon" to avoid shadowed parameter warnigns.
|
||||
|
||||
2002-06-08 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* long_term.c
|
||||
Changes tp removed compiler warnings about shadowed parameters.
|
||||
|
||||
2002-06-08 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* private.h
|
||||
Made declarations of gsm_A, gsm_B, gsm_MIC etc extern. This fixed a compile
|
||||
problem on MacOSX.
|
||||
|
||||
2002-05-10 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* *.[ch]
|
||||
Removed all pre-ANSI prototype kludges. Removed proto.h and unproto.h.
|
||||
Started work on making GSM 6.10 files seekable. Currently they are not.
|
||||
|
||||
* code.c private.h
|
||||
Function Gsm_Coder () used a statically defined array. This was obviously
|
||||
not re-entrant so moved it to struct gsm_state.
|
||||
|
||||
2001-09-16 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* code.c
|
||||
Added #includes for string.h and stdlib.h.
|
||||
|
||||
2000-10-27 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* config.h
|
||||
Removed some commented out #defines (ie //*efine) which were causing problems on
|
||||
the Sun cc compiler.
|
||||
|
||||
2000-02-29 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* private.h
|
||||
Added #defines to emulate normal compile time options.
|
||||
|
||||
2000-02-28 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
|
||||
|
||||
* everthing
|
||||
Created this directory and copied files from libgsm.
|
||||
http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||
36
project/jni/sndfile/src/GSM610/README
Normal file
36
project/jni/sndfile/src/GSM610/README
Normal file
@@ -0,0 +1,36 @@
|
||||
GSM 06.10 13 kbit/s RPE/LTP speech codec
|
||||
----------------------------------------
|
||||
|
||||
All the file in this directory were written by Jutta Degener
|
||||
and Carsten Borman for The Communications and Operating Systems
|
||||
Research Group (KBS) at the Technische Universitaet Berlin.
|
||||
|
||||
Their work was released under the following license which is
|
||||
assumed to be compatible with The GNU Lesser General Public License.
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Copyright 1992, 1993, 1994 by Jutta Degener and Carsten Bormann,
|
||||
Technische Universitaet Berlin
|
||||
|
||||
Any use of this software is permitted provided that this notice is not
|
||||
removed and that neither the authors nor the Technische Universitaet Berlin
|
||||
are deemed to have made any representations as to the suitability of this
|
||||
software for any purpose nor are held responsible for any defects of
|
||||
this software. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
|
||||
As a matter of courtesy, the authors request to be informed about uses
|
||||
this software has found, about bugs in this software, and about any
|
||||
improvements that may be of general interest.
|
||||
|
||||
Berlin, 28.11.1994
|
||||
Jutta Degener (jutta@cs.tu-berlin.de)
|
||||
Carsten Bormann (cabo@cs.tu-berlin.de)
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Jutta Degener and Carsten Bormann's work can be found on their homepage
|
||||
at:
|
||||
|
||||
http://kbs.cs.tu-berlin.de/~jutta/toast.html
|
||||
|
||||
240
project/jni/sndfile/src/GSM610/add.c
Normal file
240
project/jni/sndfile/src/GSM610/add.c
Normal file
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* See private.h for the more commonly used macro versions.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
#define saturate(x) \
|
||||
((x) < MIN_WORD ? MIN_WORD : (x) > MAX_WORD ? MAX_WORD: (x))
|
||||
|
||||
word gsm_add ( word a, word b)
|
||||
{
|
||||
longword sum = (longword)a + (longword)b;
|
||||
return saturate(sum);
|
||||
}
|
||||
|
||||
word gsm_sub ( word a, word b)
|
||||
{
|
||||
longword diff = (longword)a - (longword)b;
|
||||
return saturate(diff);
|
||||
}
|
||||
|
||||
word gsm_mult ( word a, word b)
|
||||
{
|
||||
if (a == MIN_WORD && b == MIN_WORD)
|
||||
return MAX_WORD;
|
||||
|
||||
return SASR_L( (longword)a * (longword)b, 15 );
|
||||
}
|
||||
|
||||
word gsm_mult_r ( word a, word b)
|
||||
{
|
||||
if (b == MIN_WORD && a == MIN_WORD) return MAX_WORD;
|
||||
else {
|
||||
longword prod = (longword)a * (longword)b + 16384;
|
||||
prod >>= 15;
|
||||
return prod & 0xFFFF;
|
||||
}
|
||||
}
|
||||
|
||||
word gsm_abs (word a)
|
||||
{
|
||||
return a < 0 ? (a == MIN_WORD ? MAX_WORD : -a) : a;
|
||||
}
|
||||
|
||||
longword gsm_L_mult (word a, word b)
|
||||
{
|
||||
assert( a != MIN_WORD || b != MIN_WORD );
|
||||
return ((longword)a * (longword)b) << 1;
|
||||
}
|
||||
|
||||
longword gsm_L_add ( longword a, longword b)
|
||||
{
|
||||
if (a < 0) {
|
||||
if (b >= 0) return a + b;
|
||||
else {
|
||||
ulongword A = (ulongword)-(a + 1) + (ulongword)-(b + 1);
|
||||
return A >= MAX_LONGWORD ? MIN_LONGWORD :-(longword)A-2;
|
||||
}
|
||||
}
|
||||
else if (b <= 0) return a + b;
|
||||
else {
|
||||
ulongword A = (ulongword)a + (ulongword)b;
|
||||
return A > MAX_LONGWORD ? MAX_LONGWORD : A;
|
||||
}
|
||||
}
|
||||
|
||||
longword gsm_L_sub ( longword a, longword b)
|
||||
{
|
||||
if (a >= 0) {
|
||||
if (b >= 0) return a - b;
|
||||
else {
|
||||
/* a>=0, b<0 */
|
||||
|
||||
ulongword A = (ulongword)a + -(b + 1);
|
||||
return A >= MAX_LONGWORD ? MAX_LONGWORD : (A + 1);
|
||||
}
|
||||
}
|
||||
else if (b <= 0) return a - b;
|
||||
else {
|
||||
/* a<0, b>0 */
|
||||
|
||||
ulongword A = (ulongword)-(a + 1) + b;
|
||||
return A >= MAX_LONGWORD ? MIN_LONGWORD : -(longword)A - 1;
|
||||
}
|
||||
}
|
||||
|
||||
static unsigned char const bitoff[ 256 ] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
word gsm_norm (longword a )
|
||||
/*
|
||||
* the number of left shifts needed to normalize the 32 bit
|
||||
* variable L_var1 for positive values on the interval
|
||||
*
|
||||
* with minimum of
|
||||
* minimum of 1073741824 (01000000000000000000000000000000) and
|
||||
* maximum of 2147483647 (01111111111111111111111111111111)
|
||||
*
|
||||
*
|
||||
* and for negative values on the interval with
|
||||
* minimum of -2147483648 (-10000000000000000000000000000000) and
|
||||
* maximum of -1073741824 ( -1000000000000000000000000000000).
|
||||
*
|
||||
* in order to normalize the result, the following
|
||||
* operation must be done: L_norm_var1 = L_var1 << norm( L_var1 );
|
||||
*
|
||||
* (That's 'ffs', only from the left, not the right..)
|
||||
*/
|
||||
{
|
||||
assert(a != 0);
|
||||
|
||||
if (a < 0) {
|
||||
if (a <= -1073741824) return 0;
|
||||
a = ~a;
|
||||
}
|
||||
|
||||
return a & 0xffff0000
|
||||
? ( a & 0xff000000
|
||||
? -1 + bitoff[ 0xFF & (a >> 24) ]
|
||||
: 7 + bitoff[ 0xFF & (a >> 16) ] )
|
||||
: ( a & 0xff00
|
||||
? 15 + bitoff[ 0xFF & (a >> 8) ]
|
||||
: 23 + bitoff[ 0xFF & a ] );
|
||||
}
|
||||
|
||||
longword gsm_L_asl (longword a, int n)
|
||||
{
|
||||
if (n >= 32) return 0;
|
||||
if (n <= -32) return -(a < 0);
|
||||
if (n < 0) return gsm_L_asr(a, -n);
|
||||
return a << n;
|
||||
}
|
||||
|
||||
word gsm_asr (word a, int n)
|
||||
{
|
||||
if (n >= 16) return -(a < 0);
|
||||
if (n <= -16) return 0;
|
||||
if (n < 0) return a << -n;
|
||||
|
||||
return SASR_W (a, (word) n);
|
||||
}
|
||||
|
||||
word gsm_asl (word a, int n)
|
||||
{
|
||||
if (n >= 16) return 0;
|
||||
if (n <= -16) return -(a < 0);
|
||||
if (n < 0) return gsm_asr(a, -n);
|
||||
return a << n;
|
||||
}
|
||||
|
||||
longword gsm_L_asr (longword a, int n)
|
||||
{
|
||||
if (n >= 32) return -(a < 0);
|
||||
if (n <= -32) return 0;
|
||||
if (n < 0) return a << -n;
|
||||
|
||||
return SASR_L (a, (word) n);
|
||||
}
|
||||
|
||||
/*
|
||||
** word gsm_asr (word a, int n)
|
||||
** {
|
||||
** if (n >= 16) return -(a < 0);
|
||||
** if (n <= -16) return 0;
|
||||
** if (n < 0) return a << -n;
|
||||
**
|
||||
** # ifdef SASR_W
|
||||
** return a >> n;
|
||||
** # else
|
||||
** if (a >= 0) return a >> n;
|
||||
** else return -(word)( -(uword)a >> n );
|
||||
** # endif
|
||||
** }
|
||||
**
|
||||
*/
|
||||
/*
|
||||
* (From p. 46, end of section 4.2.5)
|
||||
*
|
||||
* NOTE: The following lines gives [sic] one correct implementation
|
||||
* of the div(num, denum) arithmetic operation. Compute div
|
||||
* which is the integer division of num by denum: with denum
|
||||
* >= num > 0
|
||||
*/
|
||||
|
||||
word gsm_div (word num, word denum)
|
||||
{
|
||||
longword L_num = num;
|
||||
longword L_denum = denum;
|
||||
word div = 0;
|
||||
int k = 15;
|
||||
|
||||
/* The parameter num sometimes becomes zero.
|
||||
* Although this is explicitly guarded against in 4.2.5,
|
||||
* we assume that the result should then be zero as well.
|
||||
*/
|
||||
|
||||
/* assert(num != 0); */
|
||||
|
||||
assert(num >= 0 && denum >= num);
|
||||
if (num == 0)
|
||||
return 0;
|
||||
|
||||
while (k--) {
|
||||
div <<= 1;
|
||||
L_num <<= 1;
|
||||
|
||||
if (L_num >= L_denum) {
|
||||
L_num -= L_denum;
|
||||
div++;
|
||||
}
|
||||
}
|
||||
|
||||
return div;
|
||||
}
|
||||
|
||||
87
project/jni/sndfile/src/GSM610/code.c
Normal file
87
project/jni/sndfile/src/GSM610/code.c
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/*
|
||||
* 4.2 FIXED POINT IMPLEMENTATION OF THE RPE-LTP CODER
|
||||
*/
|
||||
|
||||
void Gsm_Coder (
|
||||
|
||||
struct gsm_state * State,
|
||||
|
||||
word * s, /* [0..159] samples IN */
|
||||
|
||||
/*
|
||||
* The RPE-LTD coder works on a frame by frame basis. The length of
|
||||
* the frame is equal to 160 samples. Some computations are done
|
||||
* once per frame to produce at the output of the coder the
|
||||
* LARc[1..8] parameters which are the coded LAR coefficients and
|
||||
* also to realize the inverse filtering operation for the entire
|
||||
* frame (160 samples of signal d[0..159]). These parts produce at
|
||||
* the output of the coder:
|
||||
*/
|
||||
|
||||
word * LARc, /* [0..7] LAR coefficients OUT */
|
||||
|
||||
/*
|
||||
* Procedure 4.2.11 to 4.2.18 are to be executed four times per
|
||||
* frame. That means once for each sub-segment RPE-LTP analysis of
|
||||
* 40 samples. These parts produce at the output of the coder:
|
||||
*/
|
||||
|
||||
word * Nc, /* [0..3] LTP lag OUT */
|
||||
word * bc, /* [0..3] coded LTP gain OUT */
|
||||
word * Mc, /* [0..3] RPE grid selection OUT */
|
||||
word * xmaxc,/* [0..3] Coded maximum amplitude OUT */
|
||||
word * xMc /* [13*4] normalized RPE samples OUT */
|
||||
)
|
||||
{
|
||||
int k;
|
||||
word * dp = State->dp0 + 120; /* [ -120...-1 ] */
|
||||
word * dpp = dp; /* [ 0...39 ] */
|
||||
|
||||
word so[160];
|
||||
|
||||
Gsm_Preprocess (State, s, so);
|
||||
Gsm_LPC_Analysis (State, so, LARc);
|
||||
Gsm_Short_Term_Analysis_Filter (State, LARc, so);
|
||||
|
||||
for (k = 0; k <= 3; k++, xMc += 13) {
|
||||
|
||||
Gsm_Long_Term_Predictor ( State,
|
||||
so+k*40, /* d [0..39] IN */
|
||||
dp, /* dp [-120..-1] IN */
|
||||
State->e + 5, /* e [0..39] OUT */
|
||||
dpp, /* dpp [0..39] OUT */
|
||||
Nc++,
|
||||
bc++);
|
||||
|
||||
Gsm_RPE_Encoding ( /*-S,-*/
|
||||
State->e + 5, /* e ][0..39][ IN/OUT */
|
||||
xmaxc++, Mc++, xMc );
|
||||
/*
|
||||
* Gsm_Update_of_reconstructed_short_time_residual_signal
|
||||
* ( dpp, State->e + 5, dp );
|
||||
*/
|
||||
|
||||
{ register int i;
|
||||
for (i = 0; i <= 39; i++)
|
||||
dp[ i ] = GSM_ADD( State->e[5 + i], dpp[i] );
|
||||
}
|
||||
dp += 40;
|
||||
dpp += 40;
|
||||
|
||||
}
|
||||
(void)memcpy( (char *)State->dp0, (char *)(State->dp0 + 160),
|
||||
120 * sizeof(*State->dp0) );
|
||||
}
|
||||
|
||||
26
project/jni/sndfile/src/GSM610/config.h
Normal file
26
project/jni/sndfile/src/GSM610/config.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef CONFIG_H
|
||||
#define CONFIG_H
|
||||
|
||||
#define HAS_STDLIB_H 1 /* /usr/include/stdlib.h */
|
||||
#define HAS_FCNTL_H 1 /* /usr/include/fcntl.h */
|
||||
|
||||
#define HAS_FSTAT 1 /* fstat syscall */
|
||||
#define HAS_FCHMOD 1 /* fchmod syscall */
|
||||
#define HAS_CHMOD 1 /* chmod syscall */
|
||||
#define HAS_FCHOWN 1 /* fchown syscall */
|
||||
#define HAS_CHOWN 1 /* chown syscall */
|
||||
|
||||
#define HAS_STRING_H 1 /* /usr/include/string.h */
|
||||
|
||||
#define HAS_UNISTD_H 1 /* /usr/include/unistd.h */
|
||||
#define HAS_UTIME 1 /* POSIX utime(path, times) */
|
||||
#define HAS_UTIME_H 1 /* UTIME header file */
|
||||
|
||||
#endif /* CONFIG_H */
|
||||
|
||||
59
project/jni/sndfile/src/GSM610/decode.c
Normal file
59
project/jni/sndfile/src/GSM610/decode.c
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/*
|
||||
* 4.3 FIXED POINT IMPLEMENTATION OF THE RPE-LTP DECODER
|
||||
*/
|
||||
|
||||
static void Postprocessing (
|
||||
struct gsm_state * S,
|
||||
register word * s)
|
||||
{
|
||||
register int k;
|
||||
register word msr = S->msr;
|
||||
register word tmp;
|
||||
|
||||
for (k = 160; k--; s++) {
|
||||
tmp = GSM_MULT_R( msr, 28180 );
|
||||
msr = GSM_ADD(*s, tmp); /* Deemphasis */
|
||||
*s = GSM_ADD(msr, msr) & 0xFFF8; /* Truncation & Upscaling */
|
||||
}
|
||||
S->msr = msr;
|
||||
}
|
||||
|
||||
void Gsm_Decoder (
|
||||
struct gsm_state * S,
|
||||
|
||||
word * LARcr, /* [0..7] IN */
|
||||
|
||||
word * Ncr, /* [0..3] IN */
|
||||
word * bcr, /* [0..3] IN */
|
||||
word * Mcr, /* [0..3] IN */
|
||||
word * xmaxcr, /* [0..3] IN */
|
||||
word * xMcr, /* [0..13*4] IN */
|
||||
|
||||
word * s) /* [0..159] OUT */
|
||||
{
|
||||
int j, k;
|
||||
word erp[40], wt[160];
|
||||
word * drp = S->dp0 + 120;
|
||||
|
||||
for (j=0; j <= 3; j++, xmaxcr++, bcr++, Ncr++, Mcr++, xMcr += 13) {
|
||||
|
||||
Gsm_RPE_Decoding( /*-S,-*/ *xmaxcr, *Mcr, xMcr, erp );
|
||||
Gsm_Long_Term_Synthesis_Filtering( S, *Ncr, *bcr, erp, drp );
|
||||
|
||||
for (k = 0; k <= 39; k++) wt[ j * 40 + k ] = drp[ k ];
|
||||
}
|
||||
|
||||
Gsm_Short_Term_Synthesis_Filter( S, LARcr, wt, s );
|
||||
Postprocessing(S, s);
|
||||
}
|
||||
|
||||
52
project/jni/sndfile/src/GSM610/gsm.h
Normal file
52
project/jni/sndfile/src/GSM610/gsm.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef GSM_H
|
||||
#define GSM_H
|
||||
|
||||
#include <stdio.h> /* for FILE * */
|
||||
|
||||
/*
|
||||
* Interface
|
||||
*/
|
||||
|
||||
typedef struct gsm_state * gsm;
|
||||
typedef short gsm_signal; /* signed 16 bit */
|
||||
typedef unsigned char gsm_byte;
|
||||
typedef gsm_byte gsm_frame[33]; /* 33 * 8 bits */
|
||||
|
||||
#define GSM_MAGIC 0xD /* 13 kbit/s RPE-LTP */
|
||||
|
||||
#define GSM_PATCHLEVEL 10
|
||||
#define GSM_MINOR 0
|
||||
#define GSM_MAJOR 1
|
||||
|
||||
#define GSM_OPT_VERBOSE 1
|
||||
#define GSM_OPT_FAST 2
|
||||
#define GSM_OPT_LTP_CUT 3
|
||||
#define GSM_OPT_WAV49 4
|
||||
#define GSM_OPT_FRAME_INDEX 5
|
||||
#define GSM_OPT_FRAME_CHAIN 6
|
||||
|
||||
gsm gsm_create (void);
|
||||
|
||||
/* Added for libsndfile : May 6, 2002 */
|
||||
void gsm_init (gsm);
|
||||
|
||||
void gsm_destroy (gsm);
|
||||
|
||||
int gsm_print (FILE *, gsm, gsm_byte *);
|
||||
int gsm_option (gsm, int, int *);
|
||||
|
||||
void gsm_encode (gsm, gsm_signal *, gsm_byte *);
|
||||
int gsm_decode (gsm, gsm_byte *, gsm_signal *);
|
||||
|
||||
int gsm_explode (gsm, gsm_byte *, gsm_signal *);
|
||||
void gsm_implode (gsm, gsm_signal *, gsm_byte *);
|
||||
|
||||
#endif /* GSM_H */
|
||||
|
||||
|
||||
301
project/jni/sndfile/src/GSM610/gsm610_priv.h
Normal file
301
project/jni/sndfile/src/GSM610/gsm610_priv.h
Normal file
@@ -0,0 +1,301 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef PRIVATE_H
|
||||
#define PRIVATE_H
|
||||
|
||||
/* Added by Erik de Castro Lopo */
|
||||
#define USE_FLOAT_MUL
|
||||
#define FAST
|
||||
#define WAV49
|
||||
|
||||
#ifdef __cplusplus
|
||||
#error "This code is not designed to be compiled with a C++ compiler."
|
||||
#endif
|
||||
/* Added by Erik de Castro Lopo */
|
||||
|
||||
|
||||
|
||||
typedef short word; /* 16 bit signed int */
|
||||
typedef int longword; /* 32 bit signed int */
|
||||
|
||||
typedef unsigned short uword; /* unsigned word */
|
||||
typedef unsigned int ulongword; /* unsigned longword */
|
||||
|
||||
struct gsm_state
|
||||
{ word dp0[ 280 ] ;
|
||||
|
||||
word z1; /* preprocessing.c, Offset_com. */
|
||||
longword L_z2; /* Offset_com. */
|
||||
int mp; /* Preemphasis */
|
||||
|
||||
word u[8] ; /* short_term_aly_filter.c */
|
||||
word LARpp[2][8] ; /* */
|
||||
word j; /* */
|
||||
|
||||
word ltp_cut; /* long_term.c, LTP crosscorr. */
|
||||
word nrp; /* 40 */ /* long_term.c, synthesis */
|
||||
word v[9] ; /* short_term.c, synthesis */
|
||||
word msr; /* decoder.c, Postprocessing */
|
||||
|
||||
char verbose; /* only used if !NDEBUG */
|
||||
char fast; /* only used if FAST */
|
||||
|
||||
char wav_fmt; /* only used if WAV49 defined */
|
||||
unsigned char frame_index; /* odd/even chaining */
|
||||
unsigned char frame_chain; /* half-byte to carry forward */
|
||||
|
||||
/* Moved here from code.c where it was defined as static */
|
||||
word e[50] ;
|
||||
} ;
|
||||
|
||||
typedef struct gsm_state GSM_STATE ;
|
||||
|
||||
#define MIN_WORD (-32767 - 1)
|
||||
#define MAX_WORD 32767
|
||||
|
||||
#define MIN_LONGWORD (-2147483647 - 1)
|
||||
#define MAX_LONGWORD 2147483647
|
||||
|
||||
/* Signed arithmetic shift right. */
|
||||
static inline word
|
||||
SASR_W (word x, word by)
|
||||
{ return (x >> by) ;
|
||||
} /* SASR */
|
||||
|
||||
static inline longword
|
||||
SASR_L (longword x, word by)
|
||||
{ return (x >> by) ;
|
||||
} /* SASR */
|
||||
|
||||
/*
|
||||
* Prototypes from add.c
|
||||
*/
|
||||
word gsm_mult (word a, word b) ;
|
||||
longword gsm_L_mult (word a, word b) ;
|
||||
word gsm_mult_r (word a, word b) ;
|
||||
|
||||
word gsm_div (word num, word denum) ;
|
||||
|
||||
word gsm_add (word a, word b ) ;
|
||||
longword gsm_L_add (longword a, longword b ) ;
|
||||
|
||||
word gsm_sub (word a, word b) ;
|
||||
longword gsm_L_sub (longword a, longword b) ;
|
||||
|
||||
word gsm_abs (word a) ;
|
||||
|
||||
word gsm_norm (longword a ) ;
|
||||
|
||||
longword gsm_L_asl (longword a, int n) ;
|
||||
word gsm_asl (word a, int n) ;
|
||||
|
||||
longword gsm_L_asr (longword a, int n) ;
|
||||
word gsm_asr (word a, int n) ;
|
||||
|
||||
/*
|
||||
* Inlined functions from add.h
|
||||
*/
|
||||
|
||||
static inline longword
|
||||
GSM_MULT_R (word a, word b)
|
||||
{ return (((longword) (a)) * ((longword) (b)) + 16384) >> 15 ;
|
||||
} /* GSM_MULT_R */
|
||||
|
||||
static inline longword
|
||||
GSM_MULT (word a, word b)
|
||||
{ return (((longword) (a)) * ((longword) (b))) >> 15 ;
|
||||
} /* GSM_MULT */
|
||||
|
||||
static inline longword
|
||||
GSM_L_MULT (word a, word b)
|
||||
{ return ((longword) (a)) * ((longword) (b)) << 1 ;
|
||||
} /* GSM_L_MULT */
|
||||
|
||||
static inline longword
|
||||
GSM_L_ADD (longword a, longword b)
|
||||
{ ulongword utmp ;
|
||||
|
||||
if (a < 0 && b < 0)
|
||||
{ utmp = (ulongword)-((a) + 1) + (ulongword)-((b) + 1) ;
|
||||
return (utmp >= (ulongword) MAX_LONGWORD) ? MIN_LONGWORD : -(longword)utmp-2 ;
|
||||
} ;
|
||||
|
||||
if (a > 0 && b > 0)
|
||||
{ utmp = (ulongword) a + (ulongword) b ;
|
||||
return (utmp >= (ulongword) MAX_LONGWORD) ? MAX_LONGWORD : utmp ;
|
||||
} ;
|
||||
|
||||
return a + b ;
|
||||
} /* GSM_L_ADD */
|
||||
|
||||
static inline longword
|
||||
GSM_ADD (word a, word b)
|
||||
{ longword ltmp ;
|
||||
|
||||
ltmp = ((longword) a) + ((longword) b) ;
|
||||
|
||||
if (ltmp >= MAX_WORD)
|
||||
return MAX_WORD ;
|
||||
if (ltmp <= MIN_WORD)
|
||||
return MIN_WORD ;
|
||||
|
||||
return ltmp ;
|
||||
} /* GSM_ADD */
|
||||
|
||||
static inline longword
|
||||
GSM_SUB (word a, word b)
|
||||
{ longword ltmp ;
|
||||
|
||||
ltmp = ((longword) a) - ((longword) b) ;
|
||||
|
||||
if (ltmp >= MAX_WORD)
|
||||
ltmp = MAX_WORD ;
|
||||
else if (ltmp <= MIN_WORD)
|
||||
ltmp = MIN_WORD ;
|
||||
|
||||
return ltmp ;
|
||||
} /* GSM_SUB */
|
||||
|
||||
static inline word
|
||||
GSM_ABS (word a)
|
||||
{
|
||||
if (a > 0)
|
||||
return a ;
|
||||
if (a == MIN_WORD)
|
||||
return MAX_WORD ;
|
||||
return -a ;
|
||||
} /* GSM_ADD */
|
||||
|
||||
|
||||
/*
|
||||
* More prototypes from implementations..
|
||||
*/
|
||||
void Gsm_Coder (
|
||||
struct gsm_state * S,
|
||||
word * s, /* [0..159] samples IN */
|
||||
word * LARc, /* [0..7] LAR coefficients OUT */
|
||||
word * Nc, /* [0..3] LTP lag OUT */
|
||||
word * bc, /* [0..3] coded LTP gain OUT */
|
||||
word * Mc, /* [0..3] RPE grid selection OUT */
|
||||
word * xmaxc,/* [0..3] Coded maximum amplitude OUT */
|
||||
word * xMc) ;/* [13*4] normalized RPE samples OUT */
|
||||
|
||||
void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */
|
||||
struct gsm_state * S,
|
||||
word * d, /* [0..39] residual signal IN */
|
||||
word * dp, /* [-120..-1] d' IN */
|
||||
word * e, /* [0..40] OUT */
|
||||
word * dpp, /* [0..40] OUT */
|
||||
word * Nc, /* correlation lag OUT */
|
||||
word * bc) ; /* gain factor OUT */
|
||||
|
||||
void Gsm_LPC_Analysis (
|
||||
struct gsm_state * S,
|
||||
word * s, /* 0..159 signals IN/OUT */
|
||||
word * LARc) ; /* 0..7 LARc's OUT */
|
||||
|
||||
void Gsm_Preprocess (
|
||||
struct gsm_state * S,
|
||||
word * s, word * so) ;
|
||||
|
||||
void Gsm_Encoding (
|
||||
struct gsm_state * S,
|
||||
word * e,
|
||||
word * ep,
|
||||
word * xmaxc,
|
||||
word * Mc,
|
||||
word * xMc) ;
|
||||
|
||||
void Gsm_Short_Term_Analysis_Filter (
|
||||
struct gsm_state * S,
|
||||
word * LARc, /* coded log area ratio [0..7] IN */
|
||||
word * d) ; /* st res. signal [0..159] IN/OUT */
|
||||
|
||||
void Gsm_Decoder (
|
||||
struct gsm_state * S,
|
||||
word * LARcr, /* [0..7] IN */
|
||||
word * Ncr, /* [0..3] IN */
|
||||
word * bcr, /* [0..3] IN */
|
||||
word * Mcr, /* [0..3] IN */
|
||||
word * xmaxcr, /* [0..3] IN */
|
||||
word * xMcr, /* [0..13*4] IN */
|
||||
word * s) ; /* [0..159] OUT */
|
||||
|
||||
void Gsm_Decoding (
|
||||
struct gsm_state * S,
|
||||
word xmaxcr,
|
||||
word Mcr,
|
||||
word * xMcr, /* [0..12] IN */
|
||||
word * erp) ; /* [0..39] OUT */
|
||||
|
||||
void Gsm_Long_Term_Synthesis_Filtering (
|
||||
struct gsm_state* S,
|
||||
word Ncr,
|
||||
word bcr,
|
||||
word * erp, /* [0..39] IN */
|
||||
word * drp) ; /* [-120..-1] IN, [0..40] OUT */
|
||||
|
||||
void Gsm_RPE_Decoding (
|
||||
/*-struct gsm_state *S,-*/
|
||||
word xmaxcr,
|
||||
word Mcr,
|
||||
word * xMcr, /* [0..12], 3 bits IN */
|
||||
word * erp) ; /* [0..39] OUT */
|
||||
|
||||
void Gsm_RPE_Encoding (
|
||||
/*-struct gsm_state * S,-*/
|
||||
word * e, /* -5..-1][0..39][40..44 IN/OUT */
|
||||
word * xmaxc, /* OUT */
|
||||
word * Mc, /* OUT */
|
||||
word * xMc) ; /* [0..12] OUT */
|
||||
|
||||
void Gsm_Short_Term_Synthesis_Filter (
|
||||
struct gsm_state * S,
|
||||
word * LARcr, /* log area ratios [0..7] IN */
|
||||
word * drp, /* received d [0...39] IN */
|
||||
word * s) ; /* signal s [0..159] OUT */
|
||||
|
||||
void Gsm_Update_of_reconstructed_short_time_residual_signal (
|
||||
word * dpp, /* [0...39] IN */
|
||||
word * ep, /* [0...39] IN */
|
||||
word * dp) ; /* [-120...-1] IN/OUT */
|
||||
|
||||
/*
|
||||
* Tables from table.c
|
||||
*/
|
||||
#ifndef GSM_TABLE_C
|
||||
|
||||
extern word gsm_A [8], gsm_B [8], gsm_MIC [8], gsm_MAC [8] ;
|
||||
extern word gsm_INVA [8] ;
|
||||
extern word gsm_DLB [4], gsm_QLB [4] ;
|
||||
extern word gsm_H [11] ;
|
||||
extern word gsm_NRFAC [8] ;
|
||||
extern word gsm_FAC [8] ;
|
||||
|
||||
#endif /* GSM_TABLE_C */
|
||||
|
||||
/*
|
||||
* Debugging
|
||||
*/
|
||||
#ifdef NDEBUG
|
||||
|
||||
# define gsm_debug_words(a, b, c, d) /* nil */
|
||||
# define gsm_debug_longwords(a, b, c, d) /* nil */
|
||||
# define gsm_debug_word(a, b) /* nil */
|
||||
# define gsm_debug_longword(a, b) /* nil */
|
||||
|
||||
#else /* !NDEBUG => DEBUG */
|
||||
|
||||
void gsm_debug_words (char * name, int, int, word *) ;
|
||||
void gsm_debug_longwords (char * name, int, int, longword *) ;
|
||||
void gsm_debug_longword (char * name, longword) ;
|
||||
void gsm_debug_word (char * name, word) ;
|
||||
|
||||
#endif /* !NDEBUG */
|
||||
|
||||
#endif /* PRIVATE_H */
|
||||
|
||||
37
project/jni/sndfile/src/GSM610/gsm_create.c
Normal file
37
project/jni/sndfile/src/GSM610/gsm_create.c
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
|
||||
#include "gsm.h"
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
gsm gsm_create (void)
|
||||
{
|
||||
gsm r;
|
||||
|
||||
r = malloc (sizeof(struct gsm_state));
|
||||
if (!r) return r;
|
||||
|
||||
memset((char *)r, 0, sizeof (struct gsm_state));
|
||||
r->nrp = 40;
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Added for libsndfile : May 6, 2002. Not sure if it works. */
|
||||
void gsm_init (gsm state)
|
||||
{
|
||||
memset (state, 0, sizeof (struct gsm_state)) ;
|
||||
state->nrp = 40 ;
|
||||
}
|
||||
|
||||
359
project/jni/sndfile/src/GSM610/gsm_decode.c
Normal file
359
project/jni/sndfile/src/GSM610/gsm_decode.c
Normal file
@@ -0,0 +1,359 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
#include "gsm.h"
|
||||
|
||||
int gsm_decode (gsm s, gsm_byte * c, gsm_signal * target)
|
||||
{
|
||||
word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
|
||||
|
||||
#ifdef WAV49
|
||||
if (s->wav_fmt) {
|
||||
|
||||
uword sr = 0;
|
||||
|
||||
s->frame_index = !s->frame_index;
|
||||
if (s->frame_index) {
|
||||
|
||||
sr = *c++;
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr |= (uword)*c++ << 4;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2; /* 5 */
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 10 */
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 15 */
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4; /* 20 */
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 25 */
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 4;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 30 */
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
|
||||
s->frame_chain = sr & 0xf;
|
||||
}
|
||||
else {
|
||||
sr = s->frame_chain;
|
||||
sr |= (uword)*c++ << 4; /* 1 */
|
||||
LARc[0] = sr & 0x3f; sr >>= 6;
|
||||
LARc[1] = sr & 0x3f; sr >>= 6;
|
||||
sr = *c++;
|
||||
LARc[2] = sr & 0x1f; sr >>= 5;
|
||||
sr |= (uword)*c++ << 3;
|
||||
LARc[3] = sr & 0x1f; sr >>= 5;
|
||||
LARc[4] = sr & 0xf; sr >>= 4;
|
||||
sr |= (uword)*c++ << 2;
|
||||
LARc[5] = sr & 0xf; sr >>= 4;
|
||||
LARc[6] = sr & 0x7; sr >>= 3;
|
||||
LARc[7] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 5 */
|
||||
Nc[0] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[0] = sr & 0x3; sr >>= 2;
|
||||
Mc[0] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[0] = sr & 0x3f; sr >>= 6;
|
||||
xmc[0] = sr & 0x7; sr >>= 3;
|
||||
xmc[1] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[2] = sr & 0x7; sr >>= 3;
|
||||
xmc[3] = sr & 0x7; sr >>= 3;
|
||||
xmc[4] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[5] = sr & 0x7; sr >>= 3;
|
||||
xmc[6] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2; /* 10 */
|
||||
xmc[7] = sr & 0x7; sr >>= 3;
|
||||
xmc[8] = sr & 0x7; sr >>= 3;
|
||||
xmc[9] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[10] = sr & 0x7; sr >>= 3;
|
||||
xmc[11] = sr & 0x7; sr >>= 3;
|
||||
xmc[12] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[1] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[1] = sr & 0x3; sr >>= 2;
|
||||
Mc[1] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[1] = sr & 0x3f; sr >>= 6;
|
||||
xmc[13] = sr & 0x7; sr >>= 3;
|
||||
xmc[14] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 15 */
|
||||
xmc[15] = sr & 0x7; sr >>= 3;
|
||||
xmc[16] = sr & 0x7; sr >>= 3;
|
||||
xmc[17] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[18] = sr & 0x7; sr >>= 3;
|
||||
xmc[19] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[20] = sr & 0x7; sr >>= 3;
|
||||
xmc[21] = sr & 0x7; sr >>= 3;
|
||||
xmc[22] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[23] = sr & 0x7; sr >>= 3;
|
||||
xmc[24] = sr & 0x7; sr >>= 3;
|
||||
xmc[25] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[2] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1; /* 20 */
|
||||
bc[2] = sr & 0x3; sr >>= 2;
|
||||
Mc[2] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[2] = sr & 0x3f; sr >>= 6;
|
||||
xmc[26] = sr & 0x7; sr >>= 3;
|
||||
xmc[27] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[28] = sr & 0x7; sr >>= 3;
|
||||
xmc[29] = sr & 0x7; sr >>= 3;
|
||||
xmc[30] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
xmc[31] = sr & 0x7; sr >>= 3;
|
||||
xmc[32] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[33] = sr & 0x7; sr >>= 3;
|
||||
xmc[34] = sr & 0x7; sr >>= 3;
|
||||
xmc[35] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1; /* 25 */
|
||||
xmc[36] = sr & 0x7; sr >>= 3;
|
||||
xmc[37] = sr & 0x7; sr >>= 3;
|
||||
xmc[38] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++;
|
||||
Nc[3] = sr & 0x7f; sr >>= 7;
|
||||
sr |= (uword)*c++ << 1;
|
||||
bc[3] = sr & 0x3; sr >>= 2;
|
||||
Mc[3] = sr & 0x3; sr >>= 2;
|
||||
sr |= (uword)*c++ << 5;
|
||||
xmaxc[3] = sr & 0x3f; sr >>= 6;
|
||||
xmc[39] = sr & 0x7; sr >>= 3;
|
||||
xmc[40] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[41] = sr & 0x7; sr >>= 3;
|
||||
xmc[42] = sr & 0x7; sr >>= 3;
|
||||
xmc[43] = sr & 0x7; sr >>= 3;
|
||||
sr = *c++; /* 30 */
|
||||
xmc[44] = sr & 0x7; sr >>= 3;
|
||||
xmc[45] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 2;
|
||||
xmc[46] = sr & 0x7; sr >>= 3;
|
||||
xmc[47] = sr & 0x7; sr >>= 3;
|
||||
xmc[48] = sr & 0x7; sr >>= 3;
|
||||
sr |= (uword)*c++ << 1;
|
||||
xmc[49] = sr & 0x7; sr >>= 3;
|
||||
xmc[50] = sr & 0x7; sr >>= 3;
|
||||
xmc[51] = sr & 0x7; sr >>= 3;
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
/* GSM_MAGIC = (*c >> 4) & 0xF; */
|
||||
|
||||
if (((*c >> 4) & 0x0F) != GSM_MAGIC) return -1;
|
||||
|
||||
LARc[0] = (*c++ & 0xF) << 2; /* 1 */
|
||||
LARc[0] |= (*c >> 6) & 0x3;
|
||||
LARc[1] = *c++ & 0x3F;
|
||||
LARc[2] = (*c >> 3) & 0x1F;
|
||||
LARc[3] = (*c++ & 0x7) << 2;
|
||||
LARc[3] |= (*c >> 6) & 0x3;
|
||||
LARc[4] = (*c >> 2) & 0xF;
|
||||
LARc[5] = (*c++ & 0x3) << 2;
|
||||
LARc[5] |= (*c >> 6) & 0x3;
|
||||
LARc[6] = (*c >> 3) & 0x7;
|
||||
LARc[7] = *c++ & 0x7;
|
||||
Nc[0] = (*c >> 1) & 0x7F;
|
||||
bc[0] = (*c++ & 0x1) << 1;
|
||||
bc[0] |= (*c >> 7) & 0x1;
|
||||
Mc[0] = (*c >> 5) & 0x3;
|
||||
xmaxc[0] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[0] |= (*c >> 7) & 0x1;
|
||||
xmc[0] = (*c >> 4) & 0x7;
|
||||
xmc[1] = (*c >> 1) & 0x7;
|
||||
xmc[2] = (*c++ & 0x1) << 2;
|
||||
xmc[2] |= (*c >> 6) & 0x3;
|
||||
xmc[3] = (*c >> 3) & 0x7;
|
||||
xmc[4] = *c++ & 0x7;
|
||||
xmc[5] = (*c >> 5) & 0x7;
|
||||
xmc[6] = (*c >> 2) & 0x7;
|
||||
xmc[7] = (*c++ & 0x3) << 1; /* 10 */
|
||||
xmc[7] |= (*c >> 7) & 0x1;
|
||||
xmc[8] = (*c >> 4) & 0x7;
|
||||
xmc[9] = (*c >> 1) & 0x7;
|
||||
xmc[10] = (*c++ & 0x1) << 2;
|
||||
xmc[10] |= (*c >> 6) & 0x3;
|
||||
xmc[11] = (*c >> 3) & 0x7;
|
||||
xmc[12] = *c++ & 0x7;
|
||||
Nc[1] = (*c >> 1) & 0x7F;
|
||||
bc[1] = (*c++ & 0x1) << 1;
|
||||
bc[1] |= (*c >> 7) & 0x1;
|
||||
Mc[1] = (*c >> 5) & 0x3;
|
||||
xmaxc[1] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[1] |= (*c >> 7) & 0x1;
|
||||
xmc[13] = (*c >> 4) & 0x7;
|
||||
xmc[14] = (*c >> 1) & 0x7;
|
||||
xmc[15] = (*c++ & 0x1) << 2;
|
||||
xmc[15] |= (*c >> 6) & 0x3;
|
||||
xmc[16] = (*c >> 3) & 0x7;
|
||||
xmc[17] = *c++ & 0x7;
|
||||
xmc[18] = (*c >> 5) & 0x7;
|
||||
xmc[19] = (*c >> 2) & 0x7;
|
||||
xmc[20] = (*c++ & 0x3) << 1;
|
||||
xmc[20] |= (*c >> 7) & 0x1;
|
||||
xmc[21] = (*c >> 4) & 0x7;
|
||||
xmc[22] = (*c >> 1) & 0x7;
|
||||
xmc[23] = (*c++ & 0x1) << 2;
|
||||
xmc[23] |= (*c >> 6) & 0x3;
|
||||
xmc[24] = (*c >> 3) & 0x7;
|
||||
xmc[25] = *c++ & 0x7;
|
||||
Nc[2] = (*c >> 1) & 0x7F;
|
||||
bc[2] = (*c++ & 0x1) << 1; /* 20 */
|
||||
bc[2] |= (*c >> 7) & 0x1;
|
||||
Mc[2] = (*c >> 5) & 0x3;
|
||||
xmaxc[2] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[2] |= (*c >> 7) & 0x1;
|
||||
xmc[26] = (*c >> 4) & 0x7;
|
||||
xmc[27] = (*c >> 1) & 0x7;
|
||||
xmc[28] = (*c++ & 0x1) << 2;
|
||||
xmc[28] |= (*c >> 6) & 0x3;
|
||||
xmc[29] = (*c >> 3) & 0x7;
|
||||
xmc[30] = *c++ & 0x7;
|
||||
xmc[31] = (*c >> 5) & 0x7;
|
||||
xmc[32] = (*c >> 2) & 0x7;
|
||||
xmc[33] = (*c++ & 0x3) << 1;
|
||||
xmc[33] |= (*c >> 7) & 0x1;
|
||||
xmc[34] = (*c >> 4) & 0x7;
|
||||
xmc[35] = (*c >> 1) & 0x7;
|
||||
xmc[36] = (*c++ & 0x1) << 2;
|
||||
xmc[36] |= (*c >> 6) & 0x3;
|
||||
xmc[37] = (*c >> 3) & 0x7;
|
||||
xmc[38] = *c++ & 0x7;
|
||||
Nc[3] = (*c >> 1) & 0x7F;
|
||||
bc[3] = (*c++ & 0x1) << 1;
|
||||
bc[3] |= (*c >> 7) & 0x1;
|
||||
Mc[3] = (*c >> 5) & 0x3;
|
||||
xmaxc[3] = (*c++ & 0x1F) << 1;
|
||||
xmaxc[3] |= (*c >> 7) & 0x1;
|
||||
xmc[39] = (*c >> 4) & 0x7;
|
||||
xmc[40] = (*c >> 1) & 0x7;
|
||||
xmc[41] = (*c++ & 0x1) << 2;
|
||||
xmc[41] |= (*c >> 6) & 0x3;
|
||||
xmc[42] = (*c >> 3) & 0x7;
|
||||
xmc[43] = *c++ & 0x7; /* 30 */
|
||||
xmc[44] = (*c >> 5) & 0x7;
|
||||
xmc[45] = (*c >> 2) & 0x7;
|
||||
xmc[46] = (*c++ & 0x3) << 1;
|
||||
xmc[46] |= (*c >> 7) & 0x1;
|
||||
xmc[47] = (*c >> 4) & 0x7;
|
||||
xmc[48] = (*c >> 1) & 0x7;
|
||||
xmc[49] = (*c++ & 0x1) << 2;
|
||||
xmc[49] |= (*c >> 6) & 0x3;
|
||||
xmc[50] = (*c >> 3) & 0x7;
|
||||
xmc[51] = *c & 0x7; /* 33 */
|
||||
}
|
||||
|
||||
Gsm_Decoder(s, LARc, Nc, bc, Mc, xmaxc, xmc, target);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
24
project/jni/sndfile/src/GSM610/gsm_destroy.c
Normal file
24
project/jni/sndfile/src/GSM610/gsm_destroy.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "gsm.h"
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAS_STDLIB_H
|
||||
# include <stdlib.h>
|
||||
#else
|
||||
# ifdef HAS_MALLOC_H
|
||||
# include <malloc.h>
|
||||
# else
|
||||
extern void free();
|
||||
# endif
|
||||
#endif
|
||||
|
||||
void gsm_destroy (gsm S)
|
||||
{
|
||||
if (S) free((char *)S);
|
||||
}
|
||||
|
||||
449
project/jni/sndfile/src/GSM610/gsm_encode.c
Normal file
449
project/jni/sndfile/src/GSM610/gsm_encode.c
Normal file
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
#include "gsm.h"
|
||||
|
||||
void gsm_encode (gsm s, gsm_signal * source, gsm_byte * c)
|
||||
{
|
||||
word LARc[8], Nc[4], Mc[4], bc[4], xmaxc[4], xmc[13*4];
|
||||
|
||||
Gsm_Coder(s, source, LARc, Nc, bc, Mc, xmaxc, xmc);
|
||||
|
||||
|
||||
/* variable size
|
||||
|
||||
GSM_MAGIC 4
|
||||
|
||||
LARc[0] 6
|
||||
LARc[1] 6
|
||||
LARc[2] 5
|
||||
LARc[3] 5
|
||||
LARc[4] 4
|
||||
LARc[5] 4
|
||||
LARc[6] 3
|
||||
LARc[7] 3
|
||||
|
||||
Nc[0] 7
|
||||
bc[0] 2
|
||||
Mc[0] 2
|
||||
xmaxc[0] 6
|
||||
xmc[0] 3
|
||||
xmc[1] 3
|
||||
xmc[2] 3
|
||||
xmc[3] 3
|
||||
xmc[4] 3
|
||||
xmc[5] 3
|
||||
xmc[6] 3
|
||||
xmc[7] 3
|
||||
xmc[8] 3
|
||||
xmc[9] 3
|
||||
xmc[10] 3
|
||||
xmc[11] 3
|
||||
xmc[12] 3
|
||||
|
||||
Nc[1] 7
|
||||
bc[1] 2
|
||||
Mc[1] 2
|
||||
xmaxc[1] 6
|
||||
xmc[13] 3
|
||||
xmc[14] 3
|
||||
xmc[15] 3
|
||||
xmc[16] 3
|
||||
xmc[17] 3
|
||||
xmc[18] 3
|
||||
xmc[19] 3
|
||||
xmc[20] 3
|
||||
xmc[21] 3
|
||||
xmc[22] 3
|
||||
xmc[23] 3
|
||||
xmc[24] 3
|
||||
xmc[25] 3
|
||||
|
||||
Nc[2] 7
|
||||
bc[2] 2
|
||||
Mc[2] 2
|
||||
xmaxc[2] 6
|
||||
xmc[26] 3
|
||||
xmc[27] 3
|
||||
xmc[28] 3
|
||||
xmc[29] 3
|
||||
xmc[30] 3
|
||||
xmc[31] 3
|
||||
xmc[32] 3
|
||||
xmc[33] 3
|
||||
xmc[34] 3
|
||||
xmc[35] 3
|
||||
xmc[36] 3
|
||||
xmc[37] 3
|
||||
xmc[38] 3
|
||||
|
||||
Nc[3] 7
|
||||
bc[3] 2
|
||||
Mc[3] 2
|
||||
xmaxc[3] 6
|
||||
xmc[39] 3
|
||||
xmc[40] 3
|
||||
xmc[41] 3
|
||||
xmc[42] 3
|
||||
xmc[43] 3
|
||||
xmc[44] 3
|
||||
xmc[45] 3
|
||||
xmc[46] 3
|
||||
xmc[47] 3
|
||||
xmc[48] 3
|
||||
xmc[49] 3
|
||||
xmc[50] 3
|
||||
xmc[51] 3
|
||||
*/
|
||||
|
||||
#ifdef WAV49
|
||||
|
||||
if (s->wav_fmt) {
|
||||
s->frame_index = !s->frame_index;
|
||||
if (s->frame_index) {
|
||||
|
||||
uword sr;
|
||||
|
||||
sr = 0;
|
||||
sr = sr >> 6 | LARc[0] << 10;
|
||||
sr = sr >> 6 | LARc[1] << 10;
|
||||
*c++ = sr >> 4;
|
||||
sr = sr >> 5 | LARc[2] << 11;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 5 | LARc[3] << 11;
|
||||
sr = sr >> 4 | LARc[4] << 12;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 4 | LARc[5] << 12;
|
||||
sr = sr >> 3 | LARc[6] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | LARc[7] << 13;
|
||||
sr = sr >> 7 | Nc[0] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[0] << 14;
|
||||
sr = sr >> 2 | Mc[0] << 14;
|
||||
sr = sr >> 6 | xmaxc[0] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[0] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[1] << 13;
|
||||
sr = sr >> 3 | xmc[2] << 13;
|
||||
sr = sr >> 3 | xmc[3] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[4] << 13;
|
||||
sr = sr >> 3 | xmc[5] << 13;
|
||||
sr = sr >> 3 | xmc[6] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[7] << 13;
|
||||
sr = sr >> 3 | xmc[8] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[9] << 13;
|
||||
sr = sr >> 3 | xmc[10] << 13;
|
||||
sr = sr >> 3 | xmc[11] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[12] << 13;
|
||||
sr = sr >> 7 | Nc[1] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[1] << 14;
|
||||
sr = sr >> 2 | Mc[1] << 14;
|
||||
sr = sr >> 6 | xmaxc[1] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[13] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[14] << 13;
|
||||
sr = sr >> 3 | xmc[15] << 13;
|
||||
sr = sr >> 3 | xmc[16] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[17] << 13;
|
||||
sr = sr >> 3 | xmc[18] << 13;
|
||||
sr = sr >> 3 | xmc[19] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[20] << 13;
|
||||
sr = sr >> 3 | xmc[21] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[22] << 13;
|
||||
sr = sr >> 3 | xmc[23] << 13;
|
||||
sr = sr >> 3 | xmc[24] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[25] << 13;
|
||||
sr = sr >> 7 | Nc[2] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[2] << 14;
|
||||
sr = sr >> 2 | Mc[2] << 14;
|
||||
sr = sr >> 6 | xmaxc[2] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[26] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[27] << 13;
|
||||
sr = sr >> 3 | xmc[28] << 13;
|
||||
sr = sr >> 3 | xmc[29] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[30] << 13;
|
||||
sr = sr >> 3 | xmc[31] << 13;
|
||||
sr = sr >> 3 | xmc[32] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[33] << 13;
|
||||
sr = sr >> 3 | xmc[34] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[35] << 13;
|
||||
sr = sr >> 3 | xmc[36] << 13;
|
||||
sr = sr >> 3 | xmc[37] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[38] << 13;
|
||||
sr = sr >> 7 | Nc[3] << 9;
|
||||
*c++ = sr >> 5;
|
||||
sr = sr >> 2 | bc[3] << 14;
|
||||
sr = sr >> 2 | Mc[3] << 14;
|
||||
sr = sr >> 6 | xmaxc[3] << 10;
|
||||
*c++ = sr >> 3;
|
||||
sr = sr >> 3 | xmc[39] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[40] << 13;
|
||||
sr = sr >> 3 | xmc[41] << 13;
|
||||
sr = sr >> 3 | xmc[42] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[43] << 13;
|
||||
sr = sr >> 3 | xmc[44] << 13;
|
||||
sr = sr >> 3 | xmc[45] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[46] << 13;
|
||||
sr = sr >> 3 | xmc[47] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[48] << 13;
|
||||
sr = sr >> 3 | xmc[49] << 13;
|
||||
sr = sr >> 3 | xmc[50] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[51] << 13;
|
||||
sr = sr >> 4;
|
||||
*c = sr >> 8;
|
||||
s->frame_chain = *c;
|
||||
}
|
||||
else {
|
||||
uword sr;
|
||||
|
||||
sr = 0;
|
||||
sr = sr >> 4 | s->frame_chain << 12;
|
||||
sr = sr >> 6 | LARc[0] << 10;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 6 | LARc[1] << 10;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 5 | LARc[2] << 11;
|
||||
sr = sr >> 5 | LARc[3] << 11;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 4 | LARc[4] << 12;
|
||||
sr = sr >> 4 | LARc[5] << 12;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | LARc[6] << 13;
|
||||
sr = sr >> 3 | LARc[7] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[0] << 9;
|
||||
sr = sr >> 2 | bc[0] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[0] << 14;
|
||||
sr = sr >> 6 | xmaxc[0] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[0] << 13;
|
||||
sr = sr >> 3 | xmc[1] << 13;
|
||||
sr = sr >> 3 | xmc[2] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[3] << 13;
|
||||
sr = sr >> 3 | xmc[4] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[5] << 13;
|
||||
sr = sr >> 3 | xmc[6] << 13;
|
||||
sr = sr >> 3 | xmc[7] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[8] << 13;
|
||||
sr = sr >> 3 | xmc[9] << 13;
|
||||
sr = sr >> 3 | xmc[10] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[11] << 13;
|
||||
sr = sr >> 3 | xmc[12] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[1] << 9;
|
||||
sr = sr >> 2 | bc[1] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[1] << 14;
|
||||
sr = sr >> 6 | xmaxc[1] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[13] << 13;
|
||||
sr = sr >> 3 | xmc[14] << 13;
|
||||
sr = sr >> 3 | xmc[15] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[16] << 13;
|
||||
sr = sr >> 3 | xmc[17] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[18] << 13;
|
||||
sr = sr >> 3 | xmc[19] << 13;
|
||||
sr = sr >> 3 | xmc[20] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[21] << 13;
|
||||
sr = sr >> 3 | xmc[22] << 13;
|
||||
sr = sr >> 3 | xmc[23] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[24] << 13;
|
||||
sr = sr >> 3 | xmc[25] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[2] << 9;
|
||||
sr = sr >> 2 | bc[2] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[2] << 14;
|
||||
sr = sr >> 6 | xmaxc[2] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[26] << 13;
|
||||
sr = sr >> 3 | xmc[27] << 13;
|
||||
sr = sr >> 3 | xmc[28] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[29] << 13;
|
||||
sr = sr >> 3 | xmc[30] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[31] << 13;
|
||||
sr = sr >> 3 | xmc[32] << 13;
|
||||
sr = sr >> 3 | xmc[33] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[34] << 13;
|
||||
sr = sr >> 3 | xmc[35] << 13;
|
||||
sr = sr >> 3 | xmc[36] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[37] << 13;
|
||||
sr = sr >> 3 | xmc[38] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 7 | Nc[3] << 9;
|
||||
sr = sr >> 2 | bc[3] << 14;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 2 | Mc[3] << 14;
|
||||
sr = sr >> 6 | xmaxc[3] << 10;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[39] << 13;
|
||||
sr = sr >> 3 | xmc[40] << 13;
|
||||
sr = sr >> 3 | xmc[41] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[42] << 13;
|
||||
sr = sr >> 3 | xmc[43] << 13;
|
||||
*c++ = sr >> 8;
|
||||
sr = sr >> 3 | xmc[44] << 13;
|
||||
sr = sr >> 3 | xmc[45] << 13;
|
||||
sr = sr >> 3 | xmc[46] << 13;
|
||||
*c++ = sr >> 7;
|
||||
sr = sr >> 3 | xmc[47] << 13;
|
||||
sr = sr >> 3 | xmc[48] << 13;
|
||||
sr = sr >> 3 | xmc[49] << 13;
|
||||
*c++ = sr >> 6;
|
||||
sr = sr >> 3 | xmc[50] << 13;
|
||||
sr = sr >> 3 | xmc[51] << 13;
|
||||
*c++ = sr >> 8;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
|
||||
#endif /* WAV49 */
|
||||
{
|
||||
|
||||
*c++ = ((GSM_MAGIC & 0xF) << 4) /* 1 */
|
||||
| ((LARc[0] >> 2) & 0xF);
|
||||
*c++ = ((LARc[0] & 0x3) << 6)
|
||||
| (LARc[1] & 0x3F);
|
||||
*c++ = ((LARc[2] & 0x1F) << 3)
|
||||
| ((LARc[3] >> 2) & 0x7);
|
||||
*c++ = ((LARc[3] & 0x3) << 6)
|
||||
| ((LARc[4] & 0xF) << 2)
|
||||
| ((LARc[5] >> 2) & 0x3);
|
||||
*c++ = ((LARc[5] & 0x3) << 6)
|
||||
| ((LARc[6] & 0x7) << 3)
|
||||
| (LARc[7] & 0x7);
|
||||
*c++ = ((Nc[0] & 0x7F) << 1)
|
||||
| ((bc[0] >> 1) & 0x1);
|
||||
*c++ = ((bc[0] & 0x1) << 7)
|
||||
| ((Mc[0] & 0x3) << 5)
|
||||
| ((xmaxc[0] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[0] & 0x1) << 7)
|
||||
| ((xmc[0] & 0x7) << 4)
|
||||
| ((xmc[1] & 0x7) << 1)
|
||||
| ((xmc[2] >> 2) & 0x1);
|
||||
*c++ = ((xmc[2] & 0x3) << 6)
|
||||
| ((xmc[3] & 0x7) << 3)
|
||||
| (xmc[4] & 0x7);
|
||||
*c++ = ((xmc[5] & 0x7) << 5) /* 10 */
|
||||
| ((xmc[6] & 0x7) << 2)
|
||||
| ((xmc[7] >> 1) & 0x3);
|
||||
*c++ = ((xmc[7] & 0x1) << 7)
|
||||
| ((xmc[8] & 0x7) << 4)
|
||||
| ((xmc[9] & 0x7) << 1)
|
||||
| ((xmc[10] >> 2) & 0x1);
|
||||
*c++ = ((xmc[10] & 0x3) << 6)
|
||||
| ((xmc[11] & 0x7) << 3)
|
||||
| (xmc[12] & 0x7);
|
||||
*c++ = ((Nc[1] & 0x7F) << 1)
|
||||
| ((bc[1] >> 1) & 0x1);
|
||||
*c++ = ((bc[1] & 0x1) << 7)
|
||||
| ((Mc[1] & 0x3) << 5)
|
||||
| ((xmaxc[1] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[1] & 0x1) << 7)
|
||||
| ((xmc[13] & 0x7) << 4)
|
||||
| ((xmc[14] & 0x7) << 1)
|
||||
| ((xmc[15] >> 2) & 0x1);
|
||||
*c++ = ((xmc[15] & 0x3) << 6)
|
||||
| ((xmc[16] & 0x7) << 3)
|
||||
| (xmc[17] & 0x7);
|
||||
*c++ = ((xmc[18] & 0x7) << 5)
|
||||
| ((xmc[19] & 0x7) << 2)
|
||||
| ((xmc[20] >> 1) & 0x3);
|
||||
*c++ = ((xmc[20] & 0x1) << 7)
|
||||
| ((xmc[21] & 0x7) << 4)
|
||||
| ((xmc[22] & 0x7) << 1)
|
||||
| ((xmc[23] >> 2) & 0x1);
|
||||
*c++ = ((xmc[23] & 0x3) << 6)
|
||||
| ((xmc[24] & 0x7) << 3)
|
||||
| (xmc[25] & 0x7);
|
||||
*c++ = ((Nc[2] & 0x7F) << 1) /* 20 */
|
||||
| ((bc[2] >> 1) & 0x1);
|
||||
*c++ = ((bc[2] & 0x1) << 7)
|
||||
| ((Mc[2] & 0x3) << 5)
|
||||
| ((xmaxc[2] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[2] & 0x1) << 7)
|
||||
| ((xmc[26] & 0x7) << 4)
|
||||
| ((xmc[27] & 0x7) << 1)
|
||||
| ((xmc[28] >> 2) & 0x1);
|
||||
*c++ = ((xmc[28] & 0x3) << 6)
|
||||
| ((xmc[29] & 0x7) << 3)
|
||||
| (xmc[30] & 0x7);
|
||||
*c++ = ((xmc[31] & 0x7) << 5)
|
||||
| ((xmc[32] & 0x7) << 2)
|
||||
| ((xmc[33] >> 1) & 0x3);
|
||||
*c++ = ((xmc[33] & 0x1) << 7)
|
||||
| ((xmc[34] & 0x7) << 4)
|
||||
| ((xmc[35] & 0x7) << 1)
|
||||
| ((xmc[36] >> 2) & 0x1);
|
||||
*c++ = ((xmc[36] & 0x3) << 6)
|
||||
| ((xmc[37] & 0x7) << 3)
|
||||
| (xmc[38] & 0x7);
|
||||
*c++ = ((Nc[3] & 0x7F) << 1)
|
||||
| ((bc[3] >> 1) & 0x1);
|
||||
*c++ = ((bc[3] & 0x1) << 7)
|
||||
| ((Mc[3] & 0x3) << 5)
|
||||
| ((xmaxc[3] >> 1) & 0x1F);
|
||||
*c++ = ((xmaxc[3] & 0x1) << 7)
|
||||
| ((xmc[39] & 0x7) << 4)
|
||||
| ((xmc[40] & 0x7) << 1)
|
||||
| ((xmc[41] >> 2) & 0x1);
|
||||
*c++ = ((xmc[41] & 0x3) << 6) /* 30 */
|
||||
| ((xmc[42] & 0x7) << 3)
|
||||
| (xmc[43] & 0x7);
|
||||
*c++ = ((xmc[44] & 0x7) << 5)
|
||||
| ((xmc[45] & 0x7) << 2)
|
||||
| ((xmc[46] >> 1) & 0x3);
|
||||
*c++ = ((xmc[46] & 0x1) << 7)
|
||||
| ((xmc[47] & 0x7) << 4)
|
||||
| ((xmc[48] & 0x7) << 1)
|
||||
| ((xmc[49] >> 2) & 0x1);
|
||||
*c++ = ((xmc[49] & 0x3) << 6)
|
||||
| ((xmc[50] & 0x7) << 3)
|
||||
| (xmc[51] & 0x7);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
66
project/jni/sndfile/src/GSM610/gsm_option.c
Normal file
66
project/jni/sndfile/src/GSM610/gsm_option.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
#include "gsm.h"
|
||||
|
||||
int gsm_option (gsm r, int opt, int * val)
|
||||
{
|
||||
int result = -1;
|
||||
|
||||
switch (opt) {
|
||||
case GSM_OPT_LTP_CUT:
|
||||
#ifdef LTP_CUT
|
||||
result = r->ltp_cut;
|
||||
if (val) r->ltp_cut = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_VERBOSE:
|
||||
#ifndef NDEBUG
|
||||
result = r->verbose;
|
||||
if (val) r->verbose = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_FAST:
|
||||
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
result = r->fast;
|
||||
if (val) r->fast = !!*val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_FRAME_CHAIN:
|
||||
|
||||
#ifdef WAV49
|
||||
result = r->frame_chain;
|
||||
if (val) r->frame_chain = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_FRAME_INDEX:
|
||||
|
||||
#ifdef WAV49
|
||||
result = r->frame_index;
|
||||
if (val) r->frame_index = *val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
case GSM_OPT_WAV49:
|
||||
|
||||
#ifdef WAV49
|
||||
result = r->wav_fmt;
|
||||
if (val) r->wav_fmt = !!*val;
|
||||
#endif
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
959
project/jni/sndfile/src/GSM610/long_term.c
Normal file
959
project/jni/sndfile/src/GSM610/long_term.c
Normal file
@@ -0,0 +1,959 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/*
|
||||
* 4.2.11 .. 4.2.12 LONG TERM PREDICTOR (LTP) SECTION
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* This module computes the LTP gain (bc) and the LTP lag (Nc)
|
||||
* for the long term analysis filter. This is done by calculating a
|
||||
* maximum of the cross-correlation function between the current
|
||||
* sub-segment short term residual signal d[0..39] (output of
|
||||
* the short term analysis filter; for simplification the index
|
||||
* of this array begins at 0 and ends at 39 for each sub-segment of the
|
||||
* RPE-LTP analysis) and the previous reconstructed short term
|
||||
* residual signal dp[ -120 .. -1 ]. A dynamic scaling must be
|
||||
* performed to avoid overflow.
|
||||
*/
|
||||
|
||||
/* The next procedure exists in six versions. First two integer
|
||||
* version (if USE_FLOAT_MUL is not defined); then four floating
|
||||
* point versions, twice with proper scaling (USE_FLOAT_MUL defined),
|
||||
* once without (USE_FLOAT_MUL and FAST defined, and fast run-time
|
||||
* option used). Every pair has first a Cut version (see the -C
|
||||
* option to toast or the LTP_CUT option to gsm_option()), then the
|
||||
* uncut one. (For a detailed explanation of why this is altogether
|
||||
* a bad idea, see Henry Spencer and Geoff Collyer, ``#ifdef Considered
|
||||
* Harmful''.)
|
||||
*/
|
||||
|
||||
#ifndef USE_FLOAT_MUL
|
||||
|
||||
#ifdef LTP_CUT
|
||||
|
||||
static void Cut_Calculation_of_the_LTP_parameters (
|
||||
|
||||
struct gsm_state * st,
|
||||
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
word wt[40];
|
||||
|
||||
longword L_result;
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal, best_k;
|
||||
word ltp_cut;
|
||||
|
||||
register word temp, wt_k;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) {
|
||||
dmax = temp;
|
||||
best_k = k;
|
||||
}
|
||||
}
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
assert(scal >= 0);
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
wt_k = SASR_W(d[best_k], scal);
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++) {
|
||||
L_result = (longword)wt_k * dp[best_k - lambda];
|
||||
if (L_result > L_max) {
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR_W( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR( L_max << temp, 16 );
|
||||
S = SASR( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* LTP_CUT */
|
||||
|
||||
static void Calculation_of_the_LTP_parameters (
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
word wt[40];
|
||||
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal;
|
||||
register word temp;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) dmax = temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
|
||||
assert(scal >= 0);
|
||||
|
||||
/* Initialization of a working array wt
|
||||
*/
|
||||
|
||||
for (k = 0; k <= 39; k++) wt[k] = SASR_W( d[k], scal );
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++) {
|
||||
|
||||
# undef STEP
|
||||
# define STEP(k) (longword)wt[k] * dp[k - lambda]
|
||||
|
||||
register longword L_result;
|
||||
|
||||
L_result = STEP(0) ; L_result += STEP(1) ;
|
||||
L_result += STEP(2) ; L_result += STEP(3) ;
|
||||
L_result += STEP(4) ; L_result += STEP(5) ;
|
||||
L_result += STEP(6) ; L_result += STEP(7) ;
|
||||
L_result += STEP(8) ; L_result += STEP(9) ;
|
||||
L_result += STEP(10) ; L_result += STEP(11) ;
|
||||
L_result += STEP(12) ; L_result += STEP(13) ;
|
||||
L_result += STEP(14) ; L_result += STEP(15) ;
|
||||
L_result += STEP(16) ; L_result += STEP(17) ;
|
||||
L_result += STEP(18) ; L_result += STEP(19) ;
|
||||
L_result += STEP(20) ; L_result += STEP(21) ;
|
||||
L_result += STEP(22) ; L_result += STEP(23) ;
|
||||
L_result += STEP(24) ; L_result += STEP(25) ;
|
||||
L_result += STEP(26) ; L_result += STEP(27) ;
|
||||
L_result += STEP(28) ; L_result += STEP(29) ;
|
||||
L_result += STEP(30) ; L_result += STEP(31) ;
|
||||
L_result += STEP(32) ; L_result += STEP(33) ;
|
||||
L_result += STEP(34) ; L_result += STEP(35) ;
|
||||
L_result += STEP(36) ; L_result += STEP(37) ;
|
||||
L_result += STEP(38) ; L_result += STEP(39) ;
|
||||
|
||||
if (L_result > L_max) {
|
||||
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR_W( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR_L( L_max << temp, 16 );
|
||||
S = SASR_L( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#else /* USE_FLOAT_MUL */
|
||||
|
||||
#ifdef LTP_CUT
|
||||
|
||||
static void Cut_Calculation_of_the_LTP_parameters (
|
||||
struct gsm_state * st, /* IN */
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
word ltp_cut;
|
||||
|
||||
float wt_float[40];
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal;
|
||||
register word temp;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = d[k];
|
||||
temp = GSM_ABS( temp );
|
||||
if (temp > dmax) dmax = temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
|
||||
assert(scal >= 0);
|
||||
ltp_cut = (longword)SASR_W(dmax, scal) * st->ltp_cut / 100;
|
||||
|
||||
|
||||
/* Initialization of a working array wt
|
||||
*/
|
||||
|
||||
for (k = 0; k < 40; k++) {
|
||||
register word w = SASR_W( d[k], scal );
|
||||
if (w < 0 ? w > -ltp_cut : w < ltp_cut) {
|
||||
wt_float[k] = 0.0;
|
||||
}
|
||||
else {
|
||||
wt_float[k] = w;
|
||||
}
|
||||
}
|
||||
for (k = -120; k < 0; k++) dp_float[k] = dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda += 9) {
|
||||
|
||||
/* Calculate L_result for l = lambda .. lambda + 9.
|
||||
*/
|
||||
register float *lp = dp_float - lambda;
|
||||
|
||||
register float W;
|
||||
register float a = lp[-8], b = lp[-7], c = lp[-6],
|
||||
d = lp[-5], e = lp[-4], f = lp[-3],
|
||||
g = lp[-2], h = lp[-1];
|
||||
register float E;
|
||||
register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
|
||||
S5 = 0, S6 = 0, S7 = 0, S8 = 0;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(K, a, b, c, d, e, f, g, h) \
|
||||
if ((W = wt_float[K]) != 0.0) { \
|
||||
E = W * a; S8 += E; \
|
||||
E = W * b; S7 += E; \
|
||||
E = W * c; S6 += E; \
|
||||
E = W * d; S5 += E; \
|
||||
E = W * e; S4 += E; \
|
||||
E = W * f; S3 += E; \
|
||||
E = W * g; S2 += E; \
|
||||
E = W * h; S1 += E; \
|
||||
a = lp[K]; \
|
||||
E = W * a; S0 += E; } else (a = lp[K])
|
||||
|
||||
# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h)
|
||||
# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a)
|
||||
# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b)
|
||||
# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c)
|
||||
# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d)
|
||||
# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e)
|
||||
# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f)
|
||||
# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g)
|
||||
|
||||
STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3);
|
||||
STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7);
|
||||
|
||||
STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11);
|
||||
STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15);
|
||||
|
||||
STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19);
|
||||
STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23);
|
||||
|
||||
STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27);
|
||||
STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31);
|
||||
|
||||
STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35);
|
||||
STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39);
|
||||
|
||||
# undef STEP_A
|
||||
# undef STEP_B
|
||||
# undef STEP_C
|
||||
# undef STEP_D
|
||||
# undef STEP_E
|
||||
# undef STEP_F
|
||||
# undef STEP_G
|
||||
# undef STEP_H
|
||||
|
||||
if (S0 > L_max) { L_max = S0; Nc = lambda; }
|
||||
if (S1 > L_max) { L_max = S1; Nc = lambda + 1; }
|
||||
if (S2 > L_max) { L_max = S2; Nc = lambda + 2; }
|
||||
if (S3 > L_max) { L_max = S3; Nc = lambda + 3; }
|
||||
if (S4 > L_max) { L_max = S4; Nc = lambda + 4; }
|
||||
if (S5 > L_max) { L_max = S5; Nc = lambda + 5; }
|
||||
if (S6 > L_max) { L_max = S6; Nc = lambda + 6; }
|
||||
if (S7 > L_max) { L_max = S7; Nc = lambda + 7; }
|
||||
if (S8 > L_max) { L_max = S8; Nc = lambda + 8; }
|
||||
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR_W( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR( L_max << temp, 16 );
|
||||
S = SASR( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* LTP_CUT */
|
||||
|
||||
static void Calculation_of_the_LTP_parameters (
|
||||
register word * din, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
|
||||
float wt_float[40];
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
longword L_max, L_power;
|
||||
word R, S, dmax, scal;
|
||||
register word temp;
|
||||
|
||||
/* Search of the optimum scaling of d[0..39].
|
||||
*/
|
||||
dmax = 0;
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
temp = din [k] ;
|
||||
temp = GSM_ABS (temp) ;
|
||||
if (temp > dmax) dmax = temp;
|
||||
}
|
||||
|
||||
temp = 0;
|
||||
if (dmax == 0) scal = 0;
|
||||
else {
|
||||
assert(dmax > 0);
|
||||
temp = gsm_norm( (longword)dmax << 16 );
|
||||
}
|
||||
|
||||
if (temp > 6) scal = 0;
|
||||
else scal = 6 - temp;
|
||||
|
||||
assert(scal >= 0);
|
||||
|
||||
/* Initialization of a working array wt
|
||||
*/
|
||||
|
||||
for (k = 0; k < 40; k++) wt_float[k] = SASR_W (din [k], scal) ;
|
||||
for (k = -120; k < 0; k++) dp_float[k] = dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda += 9) {
|
||||
|
||||
/* Calculate L_result for l = lambda .. lambda + 9.
|
||||
*/
|
||||
register float *lp = dp_float - lambda;
|
||||
|
||||
register float W;
|
||||
register float a = lp[-8], b = lp[-7], c = lp[-6],
|
||||
d = lp[-5], e = lp[-4], f = lp[-3],
|
||||
g = lp[-2], h = lp[-1];
|
||||
register float E;
|
||||
register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
|
||||
S5 = 0, S6 = 0, S7 = 0, S8 = 0;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(K, a, b, c, d, e, f, g, h) \
|
||||
W = wt_float[K]; \
|
||||
E = W * a; S8 += E; \
|
||||
E = W * b; S7 += E; \
|
||||
E = W * c; S6 += E; \
|
||||
E = W * d; S5 += E; \
|
||||
E = W * e; S4 += E; \
|
||||
E = W * f; S3 += E; \
|
||||
E = W * g; S2 += E; \
|
||||
E = W * h; S1 += E; \
|
||||
a = lp[K]; \
|
||||
E = W * a; S0 += E
|
||||
|
||||
# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h)
|
||||
# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a)
|
||||
# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b)
|
||||
# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c)
|
||||
# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d)
|
||||
# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e)
|
||||
# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f)
|
||||
# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g)
|
||||
|
||||
STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3);
|
||||
STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7);
|
||||
|
||||
STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11);
|
||||
STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15);
|
||||
|
||||
STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19);
|
||||
STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23);
|
||||
|
||||
STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27);
|
||||
STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31);
|
||||
|
||||
STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35);
|
||||
STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39);
|
||||
|
||||
# undef STEP_A
|
||||
# undef STEP_B
|
||||
# undef STEP_C
|
||||
# undef STEP_D
|
||||
# undef STEP_E
|
||||
# undef STEP_F
|
||||
# undef STEP_G
|
||||
# undef STEP_H
|
||||
|
||||
if (S0 > L_max) { L_max = S0; Nc = lambda; }
|
||||
if (S1 > L_max) { L_max = S1; Nc = lambda + 1; }
|
||||
if (S2 > L_max) { L_max = S2; Nc = lambda + 2; }
|
||||
if (S3 > L_max) { L_max = S3; Nc = lambda + 3; }
|
||||
if (S4 > L_max) { L_max = S4; Nc = lambda + 4; }
|
||||
if (S5 > L_max) { L_max = S5; Nc = lambda + 5; }
|
||||
if (S6 > L_max) { L_max = S6; Nc = lambda + 6; }
|
||||
if (S7 > L_max) { L_max = S7; Nc = lambda + 7; }
|
||||
if (S8 > L_max) { L_max = S8; Nc = lambda + 8; }
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
|
||||
L_max <<= 1;
|
||||
|
||||
/* Rescaling of L_max
|
||||
*/
|
||||
assert(scal <= 100 && scal >= -100);
|
||||
L_max = L_max >> (6 - scal); /* sub(6, scal) */
|
||||
|
||||
assert( Nc <= 120 && Nc >= 40);
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
L_power = 0;
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
register longword L_temp;
|
||||
|
||||
L_temp = SASR_W( dp[k - Nc], 3 );
|
||||
L_power += L_temp * L_temp;
|
||||
}
|
||||
L_power <<= 1; /* from L_MULT */
|
||||
|
||||
/* Normalization of L_max and L_power
|
||||
*/
|
||||
|
||||
if (L_max <= 0) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
temp = gsm_norm( L_power );
|
||||
|
||||
R = SASR_L ( L_max << temp, 16 );
|
||||
S = SASR_L ( L_power << temp, 16 );
|
||||
|
||||
/* Coding of the LTP gain
|
||||
*/
|
||||
|
||||
/* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
for (bc = 0; bc <= 2; bc++) if (R <= gsm_mult(S, gsm_DLB[bc])) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#ifdef FAST
|
||||
#ifdef LTP_CUT
|
||||
|
||||
static void Cut_Fast_Calculation_of_the_LTP_parameters (
|
||||
struct gsm_state * st, /* IN */
|
||||
register word * d, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
register float wt_float;
|
||||
word Nc, bc;
|
||||
word wt_max, best_k, ltp_cut;
|
||||
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
register float L_result, L_max, L_power;
|
||||
|
||||
wt_max = 0;
|
||||
|
||||
for (k = 0; k < 40; ++k) {
|
||||
if ( d[k] > wt_max) wt_max = d[best_k = k];
|
||||
else if (-d[k] > wt_max) wt_max = -d[best_k = k];
|
||||
}
|
||||
|
||||
assert(wt_max >= 0);
|
||||
wt_float = (float)wt_max;
|
||||
|
||||
for (k = -120; k < 0; ++k) dp_float[k] = (float)dp[k];
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda++) {
|
||||
L_result = wt_float * dp_float[best_k - lambda];
|
||||
if (L_result > L_max) {
|
||||
Nc = lambda;
|
||||
L_max = L_result;
|
||||
}
|
||||
}
|
||||
|
||||
*Nc_out = Nc;
|
||||
if (L_max <= 0.) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
dp_float -= Nc;
|
||||
L_power = 0;
|
||||
for (k = 0; k < 40; ++k) {
|
||||
register float f = dp_float[k];
|
||||
L_power += f * f;
|
||||
}
|
||||
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Coding of the LTP gain
|
||||
* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
lambda = L_max / L_power * 32768.;
|
||||
for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* LTP_CUT */
|
||||
|
||||
static void Fast_Calculation_of_the_LTP_parameters (
|
||||
register word * din, /* [0..39] IN */
|
||||
register word * dp, /* [-120..-1] IN */
|
||||
word * bc_out, /* OUT */
|
||||
word * Nc_out /* OUT */
|
||||
)
|
||||
{
|
||||
register int k, lambda;
|
||||
word Nc, bc;
|
||||
|
||||
float wt_float[40];
|
||||
float dp_float_base[120], * dp_float = dp_float_base + 120;
|
||||
|
||||
register float L_max, L_power;
|
||||
|
||||
for (k = 0; k < 40; ++k) wt_float[k] = (float) din [k] ;
|
||||
for (k = -120; k < 0; ++k) dp_float[k] = (float) dp [k] ;
|
||||
|
||||
/* Search for the maximum cross-correlation and coding of the LTP lag
|
||||
*/
|
||||
L_max = 0;
|
||||
Nc = 40; /* index for the maximum cross-correlation */
|
||||
|
||||
for (lambda = 40; lambda <= 120; lambda += 9) {
|
||||
|
||||
/* Calculate L_result for l = lambda .. lambda + 9.
|
||||
*/
|
||||
register float *lp = dp_float - lambda;
|
||||
|
||||
register float W;
|
||||
register float a = lp[-8], b = lp[-7], c = lp[-6],
|
||||
d = lp[-5], e = lp[-4], f = lp[-3],
|
||||
g = lp[-2], h = lp[-1];
|
||||
register float E;
|
||||
register float S0 = 0, S1 = 0, S2 = 0, S3 = 0, S4 = 0,
|
||||
S5 = 0, S6 = 0, S7 = 0, S8 = 0;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(K, a, b, c, d, e, f, g, h) \
|
||||
W = wt_float[K]; \
|
||||
E = W * a; S8 += E; \
|
||||
E = W * b; S7 += E; \
|
||||
E = W * c; S6 += E; \
|
||||
E = W * d; S5 += E; \
|
||||
E = W * e; S4 += E; \
|
||||
E = W * f; S3 += E; \
|
||||
E = W * g; S2 += E; \
|
||||
E = W * h; S1 += E; \
|
||||
a = lp[K]; \
|
||||
E = W * a; S0 += E
|
||||
|
||||
# define STEP_A(K) STEP(K, a, b, c, d, e, f, g, h)
|
||||
# define STEP_B(K) STEP(K, b, c, d, e, f, g, h, a)
|
||||
# define STEP_C(K) STEP(K, c, d, e, f, g, h, a, b)
|
||||
# define STEP_D(K) STEP(K, d, e, f, g, h, a, b, c)
|
||||
# define STEP_E(K) STEP(K, e, f, g, h, a, b, c, d)
|
||||
# define STEP_F(K) STEP(K, f, g, h, a, b, c, d, e)
|
||||
# define STEP_G(K) STEP(K, g, h, a, b, c, d, e, f)
|
||||
# define STEP_H(K) STEP(K, h, a, b, c, d, e, f, g)
|
||||
|
||||
STEP_A( 0); STEP_B( 1); STEP_C( 2); STEP_D( 3);
|
||||
STEP_E( 4); STEP_F( 5); STEP_G( 6); STEP_H( 7);
|
||||
|
||||
STEP_A( 8); STEP_B( 9); STEP_C(10); STEP_D(11);
|
||||
STEP_E(12); STEP_F(13); STEP_G(14); STEP_H(15);
|
||||
|
||||
STEP_A(16); STEP_B(17); STEP_C(18); STEP_D(19);
|
||||
STEP_E(20); STEP_F(21); STEP_G(22); STEP_H(23);
|
||||
|
||||
STEP_A(24); STEP_B(25); STEP_C(26); STEP_D(27);
|
||||
STEP_E(28); STEP_F(29); STEP_G(30); STEP_H(31);
|
||||
|
||||
STEP_A(32); STEP_B(33); STEP_C(34); STEP_D(35);
|
||||
STEP_E(36); STEP_F(37); STEP_G(38); STEP_H(39);
|
||||
|
||||
if (S0 > L_max) { L_max = S0; Nc = lambda; }
|
||||
if (S1 > L_max) { L_max = S1; Nc = lambda + 1; }
|
||||
if (S2 > L_max) { L_max = S2; Nc = lambda + 2; }
|
||||
if (S3 > L_max) { L_max = S3; Nc = lambda + 3; }
|
||||
if (S4 > L_max) { L_max = S4; Nc = lambda + 4; }
|
||||
if (S5 > L_max) { L_max = S5; Nc = lambda + 5; }
|
||||
if (S6 > L_max) { L_max = S6; Nc = lambda + 6; }
|
||||
if (S7 > L_max) { L_max = S7; Nc = lambda + 7; }
|
||||
if (S8 > L_max) { L_max = S8; Nc = lambda + 8; }
|
||||
}
|
||||
*Nc_out = Nc;
|
||||
|
||||
if (L_max <= 0.) {
|
||||
*bc_out = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Compute the power of the reconstructed short term residual
|
||||
* signal dp[..]
|
||||
*/
|
||||
dp_float -= Nc;
|
||||
L_power = 0;
|
||||
for (k = 0; k < 40; ++k) {
|
||||
register float f = dp_float[k];
|
||||
L_power += f * f;
|
||||
}
|
||||
|
||||
if (L_max >= L_power) {
|
||||
*bc_out = 3;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Coding of the LTP gain
|
||||
* Table 4.3a must be used to obtain the level DLB[i] for the
|
||||
* quantization of the LTP gain b to get the coded version bc.
|
||||
*/
|
||||
lambda = L_max / L_power * 32768.;
|
||||
for (bc = 0; bc <= 2; ++bc) if (lambda <= gsm_DLB[bc]) break;
|
||||
*bc_out = bc;
|
||||
}
|
||||
|
||||
#endif /* FAST */
|
||||
#endif /* USE_FLOAT_MUL */
|
||||
|
||||
|
||||
/* 4.2.12 */
|
||||
|
||||
static void Long_term_analysis_filtering (
|
||||
word bc, /* IN */
|
||||
word Nc, /* IN */
|
||||
register word * dp, /* previous d [-120..-1] IN */
|
||||
register word * d, /* d [0..39] IN */
|
||||
register word * dpp, /* estimate [0..39] OUT */
|
||||
register word * e /* long term res. signal [0..39] OUT */
|
||||
)
|
||||
/*
|
||||
* In this part, we have to decode the bc parameter to compute
|
||||
* the samples of the estimate dpp[0..39]. The decoding of bc needs the
|
||||
* use of table 4.3b. The long term residual signal e[0..39]
|
||||
* is then calculated to be fed to the RPE encoding section.
|
||||
*/
|
||||
{
|
||||
register int k;
|
||||
|
||||
# undef STEP
|
||||
# define STEP(BP) \
|
||||
for (k = 0; k <= 39; k++) { \
|
||||
dpp[k] = GSM_MULT_R( BP, dp[k - Nc]); \
|
||||
e[k] = GSM_SUB( d[k], dpp[k] ); \
|
||||
}
|
||||
|
||||
switch (bc) {
|
||||
case 0: STEP( 3277 ); break;
|
||||
case 1: STEP( 11469 ); break;
|
||||
case 2: STEP( 21299 ); break;
|
||||
case 3: STEP( 32767 ); break;
|
||||
}
|
||||
}
|
||||
|
||||
void Gsm_Long_Term_Predictor ( /* 4x for 160 samples */
|
||||
|
||||
struct gsm_state * S,
|
||||
|
||||
word * d, /* [0..39] residual signal IN */
|
||||
word * dp, /* [-120..-1] d' IN */
|
||||
|
||||
word * e, /* [0..39] OUT */
|
||||
word * dpp, /* [0..39] OUT */
|
||||
word * Nc, /* correlation lag OUT */
|
||||
word * bc /* gain factor OUT */
|
||||
)
|
||||
{
|
||||
assert( d ); assert( dp ); assert( e );
|
||||
assert( dpp); assert( Nc ); assert( bc );
|
||||
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
if (S->fast)
|
||||
#if defined (LTP_CUT)
|
||||
if (S->ltp_cut)
|
||||
Cut_Fast_Calculation_of_the_LTP_parameters(S,
|
||||
d, dp, bc, Nc);
|
||||
else
|
||||
#endif /* LTP_CUT */
|
||||
Fast_Calculation_of_the_LTP_parameters(d, dp, bc, Nc );
|
||||
else
|
||||
#endif /* FAST & USE_FLOAT_MUL */
|
||||
#ifdef LTP_CUT
|
||||
if (S->ltp_cut)
|
||||
Cut_Calculation_of_the_LTP_parameters(S, d, dp, bc, Nc);
|
||||
else
|
||||
#endif
|
||||
Calculation_of_the_LTP_parameters(d, dp, bc, Nc);
|
||||
|
||||
Long_term_analysis_filtering( *bc, *Nc, dp, d, dpp, e );
|
||||
}
|
||||
|
||||
/* 4.3.2 */
|
||||
void Gsm_Long_Term_Synthesis_Filtering (
|
||||
struct gsm_state * S,
|
||||
|
||||
word Ncr,
|
||||
word bcr,
|
||||
register word * erp, /* [0..39] IN */
|
||||
register word * drp /* [-120..-1] IN, [-120..40] OUT */
|
||||
)
|
||||
/*
|
||||
* This procedure uses the bcr and Ncr parameter to realize the
|
||||
* long term synthesis filtering. The decoding of bcr needs
|
||||
* table 4.3b.
|
||||
*/
|
||||
{
|
||||
register int k;
|
||||
word brp, drpp, Nr;
|
||||
|
||||
/* Check the limits of Nr.
|
||||
*/
|
||||
Nr = Ncr < 40 || Ncr > 120 ? S->nrp : Ncr;
|
||||
S->nrp = Nr;
|
||||
assert(Nr >= 40 && Nr <= 120);
|
||||
|
||||
/* Decoding of the LTP gain bcr
|
||||
*/
|
||||
brp = gsm_QLB[ bcr ];
|
||||
|
||||
/* Computation of the reconstructed short term residual
|
||||
* signal drp[0..39]
|
||||
*/
|
||||
assert(brp != MIN_WORD);
|
||||
|
||||
for (k = 0; k <= 39; k++) {
|
||||
drpp = GSM_MULT_R( brp, drp[ k - Nr ] );
|
||||
drp[k] = GSM_ADD( erp[k], drpp );
|
||||
}
|
||||
|
||||
/*
|
||||
* Update of the reconstructed short term residual signal
|
||||
* drp[ -1..-120 ]
|
||||
*/
|
||||
|
||||
for (k = 0; k <= 119; k++) drp[ -120 + k ] = drp[ -80 + k ];
|
||||
}
|
||||
331
project/jni/sndfile/src/GSM610/lpc.c
Normal file
331
project/jni/sndfile/src/GSM610/lpc.c
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/*
|
||||
* 4.2.4 .. 4.2.7 LPC ANALYSIS SECTION
|
||||
*/
|
||||
|
||||
/* 4.2.4 */
|
||||
|
||||
|
||||
static void Autocorrelation (
|
||||
word * s, /* [0..159] IN/OUT */
|
||||
longword * L_ACF) /* [0..8] OUT */
|
||||
/*
|
||||
* The goal is to compute the array L_ACF[k]. The signal s[i] must
|
||||
* be scaled in order to avoid an overflow situation.
|
||||
*/
|
||||
{
|
||||
register int k, i;
|
||||
|
||||
word temp, smax, scalauto;
|
||||
|
||||
#ifdef USE_FLOAT_MUL
|
||||
float float_s[160];
|
||||
#endif
|
||||
|
||||
/* Dynamic scaling of the array s[0..159]
|
||||
*/
|
||||
|
||||
/* Search for the maximum.
|
||||
*/
|
||||
smax = 0;
|
||||
for (k = 0; k <= 159; k++) {
|
||||
temp = GSM_ABS( s[k] );
|
||||
if (temp > smax) smax = temp;
|
||||
}
|
||||
|
||||
/* Computation of the scaling factor.
|
||||
*/
|
||||
if (smax == 0) scalauto = 0;
|
||||
else {
|
||||
assert(smax > 0);
|
||||
scalauto = 4 - gsm_norm( (longword)smax << 16 );/* sub(4,..) */
|
||||
}
|
||||
|
||||
/* Scaling of the array s[0...159]
|
||||
*/
|
||||
|
||||
if (scalauto > 0) {
|
||||
|
||||
# ifdef USE_FLOAT_MUL
|
||||
# define SCALE(n) \
|
||||
case n: for (k = 0; k <= 159; k++) \
|
||||
float_s[k] = (float) \
|
||||
(s[k] = GSM_MULT_R(s[k], 16384 >> (n-1)));\
|
||||
break;
|
||||
# else
|
||||
# define SCALE(n) \
|
||||
case n: for (k = 0; k <= 159; k++) \
|
||||
s[k] = GSM_MULT_R( s[k], 16384 >> (n-1) );\
|
||||
break;
|
||||
# endif /* USE_FLOAT_MUL */
|
||||
|
||||
switch (scalauto) {
|
||||
SCALE(1)
|
||||
SCALE(2)
|
||||
SCALE(3)
|
||||
SCALE(4)
|
||||
}
|
||||
# undef SCALE
|
||||
}
|
||||
# ifdef USE_FLOAT_MUL
|
||||
else for (k = 0; k <= 159; k++) float_s[k] = (float) s[k];
|
||||
# endif
|
||||
|
||||
/* Compute the L_ACF[..].
|
||||
*/
|
||||
{
|
||||
# ifdef USE_FLOAT_MUL
|
||||
register float * sp = float_s;
|
||||
register float sl = *sp;
|
||||
|
||||
# define STEP(k) L_ACF[k] += (longword)(sl * sp[ -(k) ]);
|
||||
# else
|
||||
word * sp = s;
|
||||
word sl = *sp;
|
||||
|
||||
# define STEP(k) L_ACF[k] += ((longword)sl * sp[ -(k) ]);
|
||||
# endif
|
||||
|
||||
# define NEXTI sl = *++sp
|
||||
|
||||
|
||||
for (k = 9; k--; L_ACF[k] = 0) ;
|
||||
|
||||
STEP (0);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6);
|
||||
NEXTI;
|
||||
STEP(0); STEP(1); STEP(2); STEP(3); STEP(4); STEP(5); STEP(6); STEP(7);
|
||||
|
||||
for (i = 8; i <= 159; i++) {
|
||||
|
||||
NEXTI;
|
||||
|
||||
STEP(0);
|
||||
STEP(1); STEP(2); STEP(3); STEP(4);
|
||||
STEP(5); STEP(6); STEP(7); STEP(8);
|
||||
}
|
||||
|
||||
for (k = 9; k--; L_ACF[k] <<= 1) ;
|
||||
|
||||
}
|
||||
/* Rescaling of the array s[0..159]
|
||||
*/
|
||||
if (scalauto > 0) {
|
||||
assert(scalauto <= 4);
|
||||
for (k = 160; k--; *s++ <<= scalauto) ;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
|
||||
static void Fast_Autocorrelation (
|
||||
word * s, /* [0..159] IN/OUT */
|
||||
longword * L_ACF) /* [0..8] OUT */
|
||||
{
|
||||
register int k, i;
|
||||
float f_L_ACF[9];
|
||||
float scale;
|
||||
|
||||
float s_f[160];
|
||||
register float *sf = s_f;
|
||||
|
||||
for (i = 0; i < 160; ++i) sf[i] = s[i];
|
||||
for (k = 0; k <= 8; k++) {
|
||||
register float L_temp2 = 0;
|
||||
register float *sfl = sf - k;
|
||||
for (i = k; i < 160; ++i) L_temp2 += sf[i] * sfl[i];
|
||||
f_L_ACF[k] = L_temp2;
|
||||
}
|
||||
scale = MAX_LONGWORD / f_L_ACF[0];
|
||||
|
||||
for (k = 0; k <= 8; k++) {
|
||||
L_ACF[k] = f_L_ACF[k] * scale;
|
||||
}
|
||||
}
|
||||
#endif /* defined (USE_FLOAT_MUL) && defined (FAST) */
|
||||
|
||||
/* 4.2.5 */
|
||||
|
||||
static void Reflection_coefficients (
|
||||
longword * L_ACF, /* 0...8 IN */
|
||||
register word * r /* 0...7 OUT */
|
||||
)
|
||||
{
|
||||
register int i, m, n;
|
||||
register word temp;
|
||||
word ACF[9]; /* 0..8 */
|
||||
word P[ 9]; /* 0..8 */
|
||||
word K[ 9]; /* 2..8 */
|
||||
|
||||
/* Schur recursion with 16 bits arithmetic.
|
||||
*/
|
||||
|
||||
if (L_ACF[0] == 0) {
|
||||
for (i = 8; i--; *r++ = 0) ;
|
||||
return;
|
||||
}
|
||||
|
||||
assert( L_ACF[0] != 0 );
|
||||
temp = gsm_norm( L_ACF[0] );
|
||||
|
||||
assert(temp >= 0 && temp < 32);
|
||||
|
||||
/* ? overflow ? */
|
||||
for (i = 0; i <= 8; i++) ACF[i] = SASR_L( L_ACF[i] << temp, 16 );
|
||||
|
||||
/* Initialize array P[..] and K[..] for the recursion.
|
||||
*/
|
||||
|
||||
for (i = 1; i <= 7; i++) K[ i ] = ACF[ i ];
|
||||
for (i = 0; i <= 8; i++) P[ i ] = ACF[ i ];
|
||||
|
||||
/* Compute reflection coefficients
|
||||
*/
|
||||
for (n = 1; n <= 8; n++, r++) {
|
||||
|
||||
temp = P[1];
|
||||
temp = GSM_ABS(temp);
|
||||
if (P[0] < temp) {
|
||||
for (i = n; i <= 8; i++) *r++ = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
*r = gsm_div( temp, P[0] );
|
||||
|
||||
assert(*r >= 0);
|
||||
if (P[1] > 0) *r = -*r; /* r[n] = sub(0, r[n]) */
|
||||
assert (*r != MIN_WORD);
|
||||
if (n == 8) return;
|
||||
|
||||
/* Schur recursion
|
||||
*/
|
||||
temp = GSM_MULT_R( P[1], *r );
|
||||
P[0] = GSM_ADD( P[0], temp );
|
||||
|
||||
for (m = 1; m <= 8 - n; m++) {
|
||||
temp = GSM_MULT_R( K[ m ], *r );
|
||||
P[m] = GSM_ADD( P[ m+1 ], temp );
|
||||
|
||||
temp = GSM_MULT_R( P[ m+1 ], *r );
|
||||
K[m] = GSM_ADD( K[ m ], temp );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.6 */
|
||||
|
||||
static void Transformation_to_Log_Area_Ratios (
|
||||
register word * r /* 0..7 IN/OUT */
|
||||
)
|
||||
/*
|
||||
* The following scaling for r[..] and LAR[..] has been used:
|
||||
*
|
||||
* r[..] = integer( real_r[..]*32768. ); -1 <= real_r < 1.
|
||||
* LAR[..] = integer( real_LAR[..] * 16384 );
|
||||
* with -1.625 <= real_LAR <= 1.625
|
||||
*/
|
||||
{
|
||||
register word temp;
|
||||
register int i;
|
||||
|
||||
|
||||
/* Computation of the LAR[0..7] from the r[0..7]
|
||||
*/
|
||||
for (i = 1; i <= 8; i++, r++) {
|
||||
|
||||
temp = *r;
|
||||
temp = GSM_ABS(temp);
|
||||
assert(temp >= 0);
|
||||
|
||||
if (temp < 22118) {
|
||||
temp >>= 1;
|
||||
} else if (temp < 31130) {
|
||||
assert( temp >= 11059 );
|
||||
temp -= 11059;
|
||||
} else {
|
||||
assert( temp >= 26112 );
|
||||
temp -= 26112;
|
||||
temp <<= 2;
|
||||
}
|
||||
|
||||
*r = *r < 0 ? -temp : temp;
|
||||
assert( *r != MIN_WORD );
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.7 */
|
||||
|
||||
static void Quantization_and_coding (
|
||||
register word * LAR /* [0..7] IN/OUT */
|
||||
)
|
||||
{
|
||||
register word temp;
|
||||
|
||||
/* This procedure needs four tables; the following equations
|
||||
* give the optimum scaling for the constants:
|
||||
*
|
||||
* A[0..7] = integer( real_A[0..7] * 1024 )
|
||||
* B[0..7] = integer( real_B[0..7] * 512 )
|
||||
* MAC[0..7] = maximum of the LARc[0..7]
|
||||
* MIC[0..7] = minimum of the LARc[0..7]
|
||||
*/
|
||||
|
||||
# undef STEP
|
||||
# define STEP( A, B, MAC, MIC ) \
|
||||
temp = GSM_MULT( A, *LAR ); \
|
||||
temp = GSM_ADD( temp, B ); \
|
||||
temp = GSM_ADD( temp, 256 ); \
|
||||
temp = SASR_W( temp, 9 ); \
|
||||
*LAR = temp>MAC ? MAC - MIC : (temp<MIC ? 0 : temp - MIC); \
|
||||
LAR++;
|
||||
|
||||
STEP( 20480, 0, 31, -32 );
|
||||
STEP( 20480, 0, 31, -32 );
|
||||
STEP( 20480, 2048, 15, -16 );
|
||||
STEP( 20480, -2560, 15, -16 );
|
||||
|
||||
STEP( 13964, 94, 7, -8 );
|
||||
STEP( 15360, -1792, 7, -8 );
|
||||
STEP( 8534, -341, 3, -4 );
|
||||
STEP( 9036, -1144, 3, -4 );
|
||||
|
||||
# undef STEP
|
||||
}
|
||||
|
||||
void Gsm_LPC_Analysis (
|
||||
struct gsm_state *S,
|
||||
word * s, /* 0..159 signals IN/OUT */
|
||||
word * LARc) /* 0..7 LARc's OUT */
|
||||
{
|
||||
longword L_ACF[9];
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
if (S->fast) Fast_Autocorrelation (s, L_ACF );
|
||||
else
|
||||
#endif
|
||||
Autocorrelation (s, L_ACF );
|
||||
Reflection_coefficients (L_ACF, LARc );
|
||||
Transformation_to_Log_Area_Ratios (LARc);
|
||||
Quantization_and_coding (LARc);
|
||||
}
|
||||
105
project/jni/sndfile/src/GSM610/preprocess.c
Normal file
105
project/jni/sndfile/src/GSM610/preprocess.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/* 4.2.0 .. 4.2.3 PREPROCESSING SECTION
|
||||
*
|
||||
* After A-law to linear conversion (or directly from the
|
||||
* Ato D converter) the following scaling is assumed for
|
||||
* input to the RPE-LTP algorithm:
|
||||
*
|
||||
* in: 0.1.....................12
|
||||
* S.v.v.v.v.v.v.v.v.v.v.v.v.*.*.*
|
||||
*
|
||||
* Where S is the sign bit, v a valid bit, and * a "don't care" bit.
|
||||
* The original signal is called sop[..]
|
||||
*
|
||||
* out: 0.1................... 12
|
||||
* S.S.v.v.v.v.v.v.v.v.v.v.v.v.0.0
|
||||
*/
|
||||
|
||||
|
||||
void Gsm_Preprocess (
|
||||
struct gsm_state * S,
|
||||
word * s,
|
||||
word * so ) /* [0..159] IN/OUT */
|
||||
{
|
||||
|
||||
word z1 = S->z1;
|
||||
longword L_z2 = S->L_z2;
|
||||
word mp = S->mp;
|
||||
|
||||
word s1;
|
||||
longword L_s2;
|
||||
|
||||
longword L_temp;
|
||||
|
||||
word msp, lsp;
|
||||
word SO;
|
||||
|
||||
register int k = 160;
|
||||
|
||||
while (k--) {
|
||||
|
||||
/* 4.2.1 Downscaling of the input signal
|
||||
*/
|
||||
SO = SASR_W( *s, 3 ) << 2;
|
||||
s++;
|
||||
|
||||
assert (SO >= -0x4000); /* downscaled by */
|
||||
assert (SO <= 0x3FFC); /* previous routine. */
|
||||
|
||||
|
||||
/* 4.2.2 Offset compensation
|
||||
*
|
||||
* This part implements a high-pass filter and requires extended
|
||||
* arithmetic precision for the recursive part of this filter.
|
||||
* The input of this procedure is the array so[0...159] and the
|
||||
* output the array sof[ 0...159 ].
|
||||
*/
|
||||
/* Compute the non-recursive part
|
||||
*/
|
||||
|
||||
s1 = SO - z1; /* s1 = gsm_sub( *so, z1 ); */
|
||||
z1 = SO;
|
||||
|
||||
assert(s1 != MIN_WORD);
|
||||
|
||||
/* Compute the recursive part
|
||||
*/
|
||||
L_s2 = s1;
|
||||
L_s2 <<= 15;
|
||||
|
||||
/* Execution of a 31 bv 16 bits multiplication
|
||||
*/
|
||||
|
||||
msp = SASR_L( L_z2, 15 );
|
||||
lsp = L_z2-((longword)msp<<15); /* gsm_L_sub(L_z2,(msp<<15)); */
|
||||
|
||||
L_s2 += GSM_MULT_R( lsp, 32735 );
|
||||
L_temp = (longword)msp * 32735; /* GSM_L_MULT(msp,32735) >> 1;*/
|
||||
L_z2 = GSM_L_ADD( L_temp, L_s2 );
|
||||
|
||||
/* Compute sof[k] with rounding
|
||||
*/
|
||||
L_temp = GSM_L_ADD( L_z2, 16384 );
|
||||
|
||||
/* 4.2.3 Preemphasis
|
||||
*/
|
||||
|
||||
msp = GSM_MULT_R( mp, -28180 );
|
||||
mp = SASR_L( L_temp, 15 );
|
||||
*so++ = GSM_ADD( mp, msp );
|
||||
}
|
||||
|
||||
S->z1 = z1;
|
||||
S->L_z2 = L_z2;
|
||||
S->mp = mp;
|
||||
}
|
||||
480
project/jni/sndfile/src/GSM610/rpe.c
Normal file
480
project/jni/sndfile/src/GSM610/rpe.c
Normal file
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/* 4.2.13 .. 4.2.17 RPE ENCODING SECTION
|
||||
*/
|
||||
|
||||
/* 4.2.13 */
|
||||
|
||||
static void Weighting_filter (
|
||||
register word * e, /* signal [-5..0.39.44] IN */
|
||||
word * x /* signal [0..39] OUT */
|
||||
)
|
||||
/*
|
||||
* The coefficients of the weighting filter are stored in a table
|
||||
* (see table 4.4). The following scaling is used:
|
||||
*
|
||||
* H[0..10] = integer( real_H[ 0..10] * 8192 );
|
||||
*/
|
||||
{
|
||||
/* word wt[ 50 ]; */
|
||||
|
||||
register longword L_result;
|
||||
register int k /* , i */ ;
|
||||
|
||||
/* Initialization of a temporary working array wt[0...49]
|
||||
*/
|
||||
|
||||
/* for (k = 0; k <= 4; k++) wt[k] = 0;
|
||||
* for (k = 5; k <= 44; k++) wt[k] = *e++;
|
||||
* for (k = 45; k <= 49; k++) wt[k] = 0;
|
||||
*
|
||||
* (e[-5..-1] and e[40..44] are allocated by the caller,
|
||||
* are initially zero and are not written anywhere.)
|
||||
*/
|
||||
e -= 5;
|
||||
|
||||
/* Compute the signal x[0..39]
|
||||
*/
|
||||
for (k = 0; k <= 39; k++) {
|
||||
|
||||
L_result = 8192 >> 1;
|
||||
|
||||
/* for (i = 0; i <= 10; i++) {
|
||||
* L_temp = GSM_L_MULT( wt[k+i], gsm_H[i] );
|
||||
* L_result = GSM_L_ADD( L_result, L_temp );
|
||||
* }
|
||||
*/
|
||||
|
||||
#undef STEP
|
||||
#define STEP( i, H ) (e[ k + i ] * (longword)H)
|
||||
|
||||
/* Every one of these multiplications is done twice --
|
||||
* but I don't see an elegant way to optimize this.
|
||||
* Do you?
|
||||
*/
|
||||
|
||||
#ifdef STUPID_COMPILER
|
||||
L_result += STEP( 0, -134 ) ;
|
||||
L_result += STEP( 1, -374 ) ;
|
||||
/* + STEP( 2, 0 ) */
|
||||
L_result += STEP( 3, 2054 ) ;
|
||||
L_result += STEP( 4, 5741 ) ;
|
||||
L_result += STEP( 5, 8192 ) ;
|
||||
L_result += STEP( 6, 5741 ) ;
|
||||
L_result += STEP( 7, 2054 ) ;
|
||||
/* + STEP( 8, 0 ) */
|
||||
L_result += STEP( 9, -374 ) ;
|
||||
L_result += STEP( 10, -134 ) ;
|
||||
#else
|
||||
L_result +=
|
||||
STEP( 0, -134 )
|
||||
+ STEP( 1, -374 )
|
||||
/* + STEP( 2, 0 ) */
|
||||
+ STEP( 3, 2054 )
|
||||
+ STEP( 4, 5741 )
|
||||
+ STEP( 5, 8192 )
|
||||
+ STEP( 6, 5741 )
|
||||
+ STEP( 7, 2054 )
|
||||
/* + STEP( 8, 0 ) */
|
||||
+ STEP( 9, -374 )
|
||||
+ STEP(10, -134 )
|
||||
;
|
||||
#endif
|
||||
|
||||
/* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x2) *)
|
||||
* L_result = GSM_L_ADD( L_result, L_result ); (* scaling(x4) *)
|
||||
*
|
||||
* x[k] = SASR( L_result, 16 );
|
||||
*/
|
||||
|
||||
/* 2 adds vs. >>16 => 14, minus one shift to compensate for
|
||||
* those we lost when replacing L_MULT by '*'.
|
||||
*/
|
||||
|
||||
L_result = SASR_L( L_result, 13 );
|
||||
x[k] = ( L_result < MIN_WORD ? MIN_WORD
|
||||
: (L_result > MAX_WORD ? MAX_WORD : L_result ));
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.14 */
|
||||
|
||||
static void RPE_grid_selection (
|
||||
word * x, /* [0..39] IN */
|
||||
word * xM, /* [0..12] OUT */
|
||||
word * Mc_out /* OUT */
|
||||
)
|
||||
/*
|
||||
* The signal x[0..39] is used to select the RPE grid which is
|
||||
* represented by Mc.
|
||||
*/
|
||||
{
|
||||
/* register word temp1; */
|
||||
register int /* m, */ i;
|
||||
register longword L_result, L_temp;
|
||||
longword EM; /* xxx should be L_EM? */
|
||||
word Mc;
|
||||
|
||||
longword L_common_0_3;
|
||||
|
||||
EM = 0;
|
||||
Mc = 0;
|
||||
|
||||
/* for (m = 0; m <= 3; m++) {
|
||||
* L_result = 0;
|
||||
*
|
||||
*
|
||||
* for (i = 0; i <= 12; i++) {
|
||||
*
|
||||
* temp1 = SASR_W( x[m + 3*i], 2 );
|
||||
*
|
||||
* assert(temp1 != MIN_WORD);
|
||||
*
|
||||
* L_temp = GSM_L_MULT( temp1, temp1 );
|
||||
* L_result = GSM_L_ADD( L_temp, L_result );
|
||||
* }
|
||||
*
|
||||
* if (L_result > EM) {
|
||||
* Mc = m;
|
||||
* EM = L_result;
|
||||
* }
|
||||
* }
|
||||
*/
|
||||
|
||||
#undef STEP
|
||||
#define STEP( m, i ) L_temp = SASR_W( x[m + 3 * i], 2 ); \
|
||||
L_result += L_temp * L_temp;
|
||||
|
||||
/* common part of 0 and 3 */
|
||||
|
||||
L_result = 0;
|
||||
STEP( 0, 1 ); STEP( 0, 2 ); STEP( 0, 3 ); STEP( 0, 4 );
|
||||
STEP( 0, 5 ); STEP( 0, 6 ); STEP( 0, 7 ); STEP( 0, 8 );
|
||||
STEP( 0, 9 ); STEP( 0, 10); STEP( 0, 11); STEP( 0, 12);
|
||||
L_common_0_3 = L_result;
|
||||
|
||||
/* i = 0 */
|
||||
|
||||
STEP( 0, 0 );
|
||||
L_result <<= 1; /* implicit in L_MULT */
|
||||
EM = L_result;
|
||||
|
||||
/* i = 1 */
|
||||
|
||||
L_result = 0;
|
||||
STEP( 1, 0 );
|
||||
STEP( 1, 1 ); STEP( 1, 2 ); STEP( 1, 3 ); STEP( 1, 4 );
|
||||
STEP( 1, 5 ); STEP( 1, 6 ); STEP( 1, 7 ); STEP( 1, 8 );
|
||||
STEP( 1, 9 ); STEP( 1, 10); STEP( 1, 11); STEP( 1, 12);
|
||||
L_result <<= 1;
|
||||
if (L_result > EM) {
|
||||
Mc = 1;
|
||||
EM = L_result;
|
||||
}
|
||||
|
||||
/* i = 2 */
|
||||
|
||||
L_result = 0;
|
||||
STEP( 2, 0 );
|
||||
STEP( 2, 1 ); STEP( 2, 2 ); STEP( 2, 3 ); STEP( 2, 4 );
|
||||
STEP( 2, 5 ); STEP( 2, 6 ); STEP( 2, 7 ); STEP( 2, 8 );
|
||||
STEP( 2, 9 ); STEP( 2, 10); STEP( 2, 11); STEP( 2, 12);
|
||||
L_result <<= 1;
|
||||
if (L_result > EM) {
|
||||
Mc = 2;
|
||||
EM = L_result;
|
||||
}
|
||||
|
||||
/* i = 3 */
|
||||
|
||||
L_result = L_common_0_3;
|
||||
STEP( 3, 12 );
|
||||
L_result <<= 1;
|
||||
if (L_result > EM) {
|
||||
Mc = 3;
|
||||
EM = L_result;
|
||||
}
|
||||
|
||||
/**/
|
||||
|
||||
/* Down-sampling by a factor 3 to get the selected xM[0..12]
|
||||
* RPE sequence.
|
||||
*/
|
||||
for (i = 0; i <= 12; i ++) xM[i] = x[Mc + 3*i];
|
||||
*Mc_out = Mc;
|
||||
}
|
||||
|
||||
/* 4.12.15 */
|
||||
|
||||
static void APCM_quantization_xmaxc_to_exp_mant (
|
||||
word xmaxc, /* IN */
|
||||
word * expon_out, /* OUT */
|
||||
word * mant_out ) /* OUT */
|
||||
{
|
||||
word expon, mant;
|
||||
|
||||
/* Compute expononent and mantissa of the decoded version of xmaxc
|
||||
*/
|
||||
|
||||
expon = 0;
|
||||
if (xmaxc > 15) expon = SASR_W(xmaxc, 3) - 1;
|
||||
mant = xmaxc - (expon << 3);
|
||||
|
||||
if (mant == 0) {
|
||||
expon = -4;
|
||||
mant = 7;
|
||||
}
|
||||
else {
|
||||
while (mant <= 7) {
|
||||
mant = mant << 1 | 1;
|
||||
expon--;
|
||||
}
|
||||
mant -= 8;
|
||||
}
|
||||
|
||||
assert( expon >= -4 && expon <= 6 );
|
||||
assert( mant >= 0 && mant <= 7 );
|
||||
|
||||
*expon_out = expon;
|
||||
*mant_out = mant;
|
||||
}
|
||||
|
||||
static void APCM_quantization (
|
||||
word * xM, /* [0..12] IN */
|
||||
word * xMc, /* [0..12] OUT */
|
||||
word * mant_out, /* OUT */
|
||||
word * expon_out, /* OUT */
|
||||
word * xmaxc_out /* OUT */
|
||||
)
|
||||
{
|
||||
int i, itest;
|
||||
|
||||
word xmax, xmaxc, temp, temp1, temp2;
|
||||
word expon, mant;
|
||||
|
||||
|
||||
/* Find the maximum absolute value xmax of xM[0..12].
|
||||
*/
|
||||
|
||||
xmax = 0;
|
||||
for (i = 0; i <= 12; i++) {
|
||||
temp = xM[i];
|
||||
temp = GSM_ABS(temp);
|
||||
if (temp > xmax) xmax = temp;
|
||||
}
|
||||
|
||||
/* Qantizing and coding of xmax to get xmaxc.
|
||||
*/
|
||||
|
||||
expon = 0;
|
||||
temp = SASR_W( xmax, 9 );
|
||||
itest = 0;
|
||||
|
||||
for (i = 0; i <= 5; i++) {
|
||||
|
||||
itest |= (temp <= 0);
|
||||
temp = SASR_W( temp, 1 );
|
||||
|
||||
assert(expon <= 5);
|
||||
if (itest == 0) expon++; /* expon = add (expon, 1) */
|
||||
}
|
||||
|
||||
assert(expon <= 6 && expon >= 0);
|
||||
temp = expon + 5;
|
||||
|
||||
assert(temp <= 11 && temp >= 0);
|
||||
xmaxc = gsm_add( SASR_W(xmax, temp), (word) (expon << 3) );
|
||||
|
||||
/* Quantizing and coding of the xM[0..12] RPE sequence
|
||||
* to get the xMc[0..12]
|
||||
*/
|
||||
|
||||
APCM_quantization_xmaxc_to_exp_mant( xmaxc, &expon, &mant );
|
||||
|
||||
/* This computation uses the fact that the decoded version of xmaxc
|
||||
* can be calculated by using the expononent and the mantissa part of
|
||||
* xmaxc (logarithmic table).
|
||||
* So, this method avoids any division and uses only a scaling
|
||||
* of the RPE samples by a function of the expononent. A direct
|
||||
* multiplication by the inverse of the mantissa (NRFAC[0..7]
|
||||
* found in table 4.5) gives the 3 bit coded version xMc[0..12]
|
||||
* of the RPE samples.
|
||||
*/
|
||||
|
||||
|
||||
/* Direct computation of xMc[0..12] using table 4.5
|
||||
*/
|
||||
|
||||
assert( expon <= 4096 && expon >= -4096);
|
||||
assert( mant >= 0 && mant <= 7 );
|
||||
|
||||
temp1 = 6 - expon; /* normalization by the expononent */
|
||||
temp2 = gsm_NRFAC[ mant ]; /* inverse mantissa */
|
||||
|
||||
for (i = 0; i <= 12; i++) {
|
||||
|
||||
assert(temp1 >= 0 && temp1 < 16);
|
||||
|
||||
temp = xM[i] << temp1;
|
||||
temp = GSM_MULT( temp, temp2 );
|
||||
temp = SASR_W(temp, 12);
|
||||
xMc[i] = temp + 4; /* see note below */
|
||||
}
|
||||
|
||||
/* NOTE: This equation is used to make all the xMc[i] positive.
|
||||
*/
|
||||
|
||||
*mant_out = mant;
|
||||
*expon_out = expon;
|
||||
*xmaxc_out = xmaxc;
|
||||
}
|
||||
|
||||
/* 4.2.16 */
|
||||
|
||||
static void APCM_inverse_quantization (
|
||||
register word * xMc, /* [0..12] IN */
|
||||
word mant,
|
||||
word expon,
|
||||
register word * xMp) /* [0..12] OUT */
|
||||
/*
|
||||
* This part is for decoding the RPE sequence of coded xMc[0..12]
|
||||
* samples to obtain the xMp[0..12] array. Table 4.6 is used to get
|
||||
* the mantissa of xmaxc (FAC[0..7]).
|
||||
*/
|
||||
{
|
||||
int i;
|
||||
word temp, temp1, temp2, temp3;
|
||||
|
||||
assert( mant >= 0 && mant <= 7 );
|
||||
|
||||
temp1 = gsm_FAC[ mant ]; /* see 4.2-15 for mant */
|
||||
temp2 = gsm_sub( 6, expon ); /* see 4.2-15 for exp */
|
||||
temp3 = gsm_asl( 1, gsm_sub( temp2, 1 ));
|
||||
|
||||
for (i = 13; i--;) {
|
||||
|
||||
assert( *xMc <= 7 && *xMc >= 0 ); /* 3 bit unsigned */
|
||||
|
||||
/* temp = gsm_sub( *xMc++ << 1, 7 ); */
|
||||
temp = (*xMc++ << 1) - 7; /* restore sign */
|
||||
assert( temp <= 7 && temp >= -7 ); /* 4 bit signed */
|
||||
|
||||
temp <<= 12; /* 16 bit signed */
|
||||
temp = GSM_MULT_R( temp1, temp );
|
||||
temp = GSM_ADD( temp, temp3 );
|
||||
*xMp++ = gsm_asr( temp, temp2 );
|
||||
}
|
||||
}
|
||||
|
||||
/* 4.2.17 */
|
||||
|
||||
static void RPE_grid_positioning (
|
||||
word Mc, /* grid position IN */
|
||||
register word * xMp, /* [0..12] IN */
|
||||
register word * ep /* [0..39] OUT */
|
||||
)
|
||||
/*
|
||||
* This procedure computes the reconstructed long term residual signal
|
||||
* ep[0..39] for the LTP analysis filter. The inputs are the Mc
|
||||
* which is the grid position selection and the xMp[0..12] decoded
|
||||
* RPE samples which are upsampled by a factor of 3 by inserting zero
|
||||
* values.
|
||||
*/
|
||||
{
|
||||
int i = 13;
|
||||
|
||||
assert(0 <= Mc && Mc <= 3);
|
||||
|
||||
switch (Mc) {
|
||||
case 3: *ep++ = 0;
|
||||
case 2: do {
|
||||
*ep++ = 0;
|
||||
case 1: *ep++ = 0;
|
||||
case 0: *ep++ = *xMp++;
|
||||
} while (--i);
|
||||
}
|
||||
while (++Mc < 4) *ep++ = 0;
|
||||
|
||||
/*
|
||||
|
||||
int i, k;
|
||||
for (k = 0; k <= 39; k++) ep[k] = 0;
|
||||
for (i = 0; i <= 12; i++) {
|
||||
ep[ Mc + (3*i) ] = xMp[i];
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
||||
/* 4.2.18 */
|
||||
|
||||
/* This procedure adds the reconstructed long term residual signal
|
||||
* ep[0..39] to the estimated signal dpp[0..39] from the long term
|
||||
* analysis filter to compute the reconstructed short term residual
|
||||
* signal dp[-40..-1]; also the reconstructed short term residual
|
||||
* array dp[-120..-41] is updated.
|
||||
*/
|
||||
|
||||
#if 0 /* Has been inlined in code.c */
|
||||
void Gsm_Update_of_reconstructed_short_time_residual_signal (
|
||||
word * dpp, /* [0...39] IN */
|
||||
word * ep, /* [0...39] IN */
|
||||
word * dp) /* [-120...-1] IN/OUT */
|
||||
{
|
||||
int k;
|
||||
|
||||
for (k = 0; k <= 79; k++)
|
||||
dp[ -120 + k ] = dp[ -80 + k ];
|
||||
|
||||
for (k = 0; k <= 39; k++)
|
||||
dp[ -40 + k ] = gsm_add( ep[k], dpp[k] );
|
||||
}
|
||||
#endif /* Has been inlined in code.c */
|
||||
|
||||
void Gsm_RPE_Encoding (
|
||||
/*-struct gsm_state * S,-*/
|
||||
|
||||
word * e, /* -5..-1][0..39][40..44 IN/OUT */
|
||||
word * xmaxc, /* OUT */
|
||||
word * Mc, /* OUT */
|
||||
word * xMc) /* [0..12] OUT */
|
||||
{
|
||||
word x[40];
|
||||
word xM[13], xMp[13];
|
||||
word mant, expon;
|
||||
|
||||
Weighting_filter(e, x);
|
||||
RPE_grid_selection(x, xM, Mc);
|
||||
|
||||
APCM_quantization( xM, xMc, &mant, &expon, xmaxc);
|
||||
APCM_inverse_quantization( xMc, mant, expon, xMp);
|
||||
|
||||
RPE_grid_positioning( *Mc, xMp, e );
|
||||
|
||||
}
|
||||
|
||||
void Gsm_RPE_Decoding (
|
||||
/*-struct gsm_state * S,-*/
|
||||
|
||||
word xmaxcr,
|
||||
word Mcr,
|
||||
word * xMcr, /* [0..12], 3 bits IN */
|
||||
word * erp /* [0..39] OUT */
|
||||
)
|
||||
{
|
||||
word expon, mant;
|
||||
word xMp[ 13 ];
|
||||
|
||||
APCM_quantization_xmaxc_to_exp_mant( xmaxcr, &expon, &mant );
|
||||
APCM_inverse_quantization( xMcr, mant, expon, xMp );
|
||||
RPE_grid_positioning( Mcr, xMp, erp );
|
||||
|
||||
}
|
||||
417
project/jni/sndfile/src/GSM610/short_term.c
Normal file
417
project/jni/sndfile/src/GSM610/short_term.c
Normal file
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/*
|
||||
* SHORT TERM ANALYSIS FILTERING SECTION
|
||||
*/
|
||||
|
||||
/* 4.2.8 */
|
||||
|
||||
static void Decoding_of_the_coded_Log_Area_Ratios (
|
||||
word * LARc, /* coded log area ratio [0..7] IN */
|
||||
word * LARpp) /* out: decoded .. */
|
||||
{
|
||||
register word temp1 /* , temp2 */;
|
||||
|
||||
/* This procedure requires for efficient implementation
|
||||
* two tables.
|
||||
*
|
||||
* INVA[1..8] = integer( (32768 * 8) / real_A[1..8])
|
||||
* MIC[1..8] = minimum value of the LARc[1..8]
|
||||
*/
|
||||
|
||||
/* Compute the LARpp[1..8]
|
||||
*/
|
||||
|
||||
/* for (i = 1; i <= 8; i++, B++, MIC++, INVA++, LARc++, LARpp++) {
|
||||
*
|
||||
* temp1 = GSM_ADD( *LARc, *MIC ) << 10;
|
||||
* temp2 = *B << 1;
|
||||
* temp1 = GSM_SUB( temp1, temp2 );
|
||||
*
|
||||
* assert(*INVA != MIN_WORD);
|
||||
*
|
||||
* temp1 = GSM_MULT_R( *INVA, temp1 );
|
||||
* *LARpp = GSM_ADD( temp1, temp1 );
|
||||
* }
|
||||
*/
|
||||
|
||||
#undef STEP
|
||||
#define STEP( B, MIC, INVA ) \
|
||||
temp1 = GSM_ADD( *LARc++, MIC ) << 10; \
|
||||
temp1 = GSM_SUB( temp1, B << 1 ); \
|
||||
temp1 = GSM_MULT_R( INVA, temp1 ); \
|
||||
*LARpp++ = GSM_ADD( temp1, temp1 );
|
||||
|
||||
STEP( 0, -32, 13107 );
|
||||
STEP( 0, -32, 13107 );
|
||||
STEP( 2048, -16, 13107 );
|
||||
STEP( -2560, -16, 13107 );
|
||||
|
||||
STEP( 94, -8, 19223 );
|
||||
STEP( -1792, -8, 17476 );
|
||||
STEP( -341, -4, 31454 );
|
||||
STEP( -1144, -4, 29708 );
|
||||
|
||||
/* NOTE: the addition of *MIC is used to restore
|
||||
* the sign of *LARc.
|
||||
*/
|
||||
}
|
||||
|
||||
/* 4.2.9 */
|
||||
/* Computation of the quantized reflection coefficients
|
||||
*/
|
||||
|
||||
/* 4.2.9.1 Interpolation of the LARpp[1..8] to get the LARp[1..8]
|
||||
*/
|
||||
|
||||
/*
|
||||
* Within each frame of 160 analyzed speech samples the short term
|
||||
* analysis and synthesis filters operate with four different sets of
|
||||
* coefficients, derived from the previous set of decoded LARs(LARpp(j-1))
|
||||
* and the actual set of decoded LARs (LARpp(j))
|
||||
*
|
||||
* (Initial value: LARpp(j-1)[1..8] = 0.)
|
||||
*/
|
||||
|
||||
static void Coefficients_0_12 (
|
||||
register word * LARpp_j_1,
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARp++, LARpp_j_1++, LARpp_j++) {
|
||||
*LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 ));
|
||||
*LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j_1, 1));
|
||||
}
|
||||
}
|
||||
|
||||
static void Coefficients_13_26 (
|
||||
register word * LARpp_j_1,
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) {
|
||||
*LARp = GSM_ADD( SASR_W( *LARpp_j_1, 1), SASR_W( *LARpp_j, 1 ));
|
||||
}
|
||||
}
|
||||
|
||||
static void Coefficients_27_39 (
|
||||
register word * LARpp_j_1,
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARpp_j_1++, LARpp_j++, LARp++) {
|
||||
*LARp = GSM_ADD( SASR_W( *LARpp_j_1, 2 ), SASR_W( *LARpp_j, 2 ));
|
||||
*LARp = GSM_ADD( *LARp, SASR_W( *LARpp_j, 1 ));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void Coefficients_40_159 (
|
||||
register word * LARpp_j,
|
||||
register word * LARp)
|
||||
{
|
||||
register int i;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARp++, LARpp_j++)
|
||||
*LARp = *LARpp_j;
|
||||
}
|
||||
|
||||
/* 4.2.9.2 */
|
||||
|
||||
static void LARp_to_rp (
|
||||
register word * LARp) /* [0..7] IN/OUT */
|
||||
/*
|
||||
* The input of this procedure is the interpolated LARp[0..7] array.
|
||||
* The reflection coefficients, rp[i], are used in the analysis
|
||||
* filter and in the synthesis filter.
|
||||
*/
|
||||
{
|
||||
register int i;
|
||||
register word temp;
|
||||
|
||||
for (i = 1; i <= 8; i++, LARp++) {
|
||||
|
||||
/* temp = GSM_ABS( *LARp );
|
||||
*
|
||||
* if (temp < 11059) temp <<= 1;
|
||||
* else if (temp < 20070) temp += 11059;
|
||||
* else temp = GSM_ADD( temp >> 2, 26112 );
|
||||
*
|
||||
* *LARp = *LARp < 0 ? -temp : temp;
|
||||
*/
|
||||
|
||||
if (*LARp < 0) {
|
||||
temp = *LARp == MIN_WORD ? MAX_WORD : -(*LARp);
|
||||
*LARp = - ((temp < 11059) ? temp << 1
|
||||
: ((temp < 20070) ? temp + 11059
|
||||
: GSM_ADD( (word) (temp >> 2), (word) 26112 )));
|
||||
} else {
|
||||
temp = *LARp;
|
||||
*LARp = (temp < 11059) ? temp << 1
|
||||
: ((temp < 20070) ? temp + 11059
|
||||
: GSM_ADD( (word) (temp >> 2), (word) 26112 ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 4.2.10 */
|
||||
static void Short_term_analysis_filtering (
|
||||
struct gsm_state * S,
|
||||
register word * rp, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
/*
|
||||
* This procedure computes the short term residual signal d[..] to be fed
|
||||
* to the RPE-LTP loop from the s[..] signal and from the local rp[..]
|
||||
* array (quantized reflection coefficients). As the call of this
|
||||
* procedure can be done in many ways (see the interpolation of the LAR
|
||||
* coefficient), it is assumed that the computation begins with index
|
||||
* k_start (for arrays d[..] and s[..]) and stops with index k_end
|
||||
* (k_start and k_end are defined in 4.2.9.1). This procedure also
|
||||
* needs to keep the array u[0..7] in memory for each call.
|
||||
*/
|
||||
{
|
||||
register word * u = S->u;
|
||||
register int i;
|
||||
register word di, zzz, ui, sav, rpi;
|
||||
|
||||
for (; k_n--; s++) {
|
||||
|
||||
di = sav = *s;
|
||||
|
||||
for (i = 0; i < 8; i++) { /* YYY */
|
||||
|
||||
ui = u[i];
|
||||
rpi = rp[i];
|
||||
u[i] = sav;
|
||||
|
||||
zzz = GSM_MULT_R(rpi, di);
|
||||
sav = GSM_ADD( ui, zzz);
|
||||
|
||||
zzz = GSM_MULT_R(rpi, ui);
|
||||
di = GSM_ADD( di, zzz );
|
||||
}
|
||||
|
||||
*s = di;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(USE_FLOAT_MUL) && defined(FAST)
|
||||
|
||||
static void Fast_Short_term_analysis_filtering (
|
||||
struct gsm_state * S,
|
||||
register word * rp, /* [0..7] IN */
|
||||
register int k_n, /* k_end - k_start */
|
||||
register word * s /* [0..n-1] IN/OUT */
|
||||
)
|
||||
{
|
||||
register word * u = S->u;
|
||||
register int i;
|
||||
|
||||
float uf[8],
|
||||
rpf[8];
|
||||
|
||||
register float scalef = 3.0517578125e-5;
|
||||
register float sav, di, temp;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
uf[i] = u[i];
|
||||
rpf[i] = rp[i] * scalef;
|
||||
}
|
||||
for (; k_n--; s++) {
|
||||
sav = di = *s;
|
||||
for (i = 0; i < 8; ++i) {
|
||||
register float rpfi = rpf[i];
|
||||
register float ufi = uf[i];
|
||||
|
||||
uf[i] = sav;
|
||||
temp = rpfi * di + ufi;
|
||||
di += rpfi * ufi;
|
||||
sav = temp;
|
||||
}
|
||||
*s = di;
|
||||
}
|
||||
for (i = 0; i < 8; ++i) u[i] = uf[i];
|
||||
}
|
||||
#endif /* ! (defined (USE_FLOAT_MUL) && defined (FAST)) */
|
||||
|
||||
static void Short_term_synthesis_filtering (
|
||||
struct gsm_state * S,
|
||||
register word * rrp, /* [0..7] IN */
|
||||
register int k, /* k_end - k_start */
|
||||
register word * wt, /* [0..k-1] IN */
|
||||
register word * sr /* [0..k-1] OUT */
|
||||
)
|
||||
{
|
||||
register word * v = S->v;
|
||||
register int i;
|
||||
register word sri, tmp1, tmp2;
|
||||
|
||||
while (k--) {
|
||||
sri = *wt++;
|
||||
for (i = 8; i--;) {
|
||||
|
||||
/* sri = GSM_SUB( sri, gsm_mult_r( rrp[i], v[i] ) );
|
||||
*/
|
||||
tmp1 = rrp[i];
|
||||
tmp2 = v[i];
|
||||
tmp2 = ( tmp1 == MIN_WORD && tmp2 == MIN_WORD
|
||||
? MAX_WORD
|
||||
: 0x0FFFF & (( (longword)tmp1 * (longword)tmp2
|
||||
+ 16384) >> 15)) ;
|
||||
|
||||
sri = GSM_SUB( sri, tmp2 );
|
||||
|
||||
/* v[i+1] = GSM_ADD( v[i], gsm_mult_r( rrp[i], sri ) );
|
||||
*/
|
||||
tmp1 = ( tmp1 == MIN_WORD && sri == MIN_WORD
|
||||
? MAX_WORD
|
||||
: 0x0FFFF & (( (longword)tmp1 * (longword)sri
|
||||
+ 16384) >> 15)) ;
|
||||
|
||||
v[i+1] = GSM_ADD( v[i], tmp1);
|
||||
}
|
||||
*sr++ = v[0] = sri;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
|
||||
static void Fast_Short_term_synthesis_filtering (
|
||||
struct gsm_state * S,
|
||||
register word * rrp, /* [0..7] IN */
|
||||
register int k, /* k_end - k_start */
|
||||
register word * wt, /* [0..k-1] IN */
|
||||
register word * sr /* [0..k-1] OUT */
|
||||
)
|
||||
{
|
||||
register word * v = S->v;
|
||||
register int i;
|
||||
|
||||
float va[9], rrpa[8];
|
||||
register float scalef = 3.0517578125e-5, temp;
|
||||
|
||||
for (i = 0; i < 8; ++i) {
|
||||
va[i] = v[i];
|
||||
rrpa[i] = (float)rrp[i] * scalef;
|
||||
}
|
||||
while (k--) {
|
||||
register float sri = *wt++;
|
||||
for (i = 8; i--;) {
|
||||
sri -= rrpa[i] * va[i];
|
||||
if (sri < -32768.) sri = -32768.;
|
||||
else if (sri > 32767.) sri = 32767.;
|
||||
|
||||
temp = va[i] + rrpa[i] * sri;
|
||||
if (temp < -32768.) temp = -32768.;
|
||||
else if (temp > 32767.) temp = 32767.;
|
||||
va[i+1] = temp;
|
||||
}
|
||||
*sr++ = va[0] = sri;
|
||||
}
|
||||
for (i = 0; i < 9; ++i) v[i] = va[i];
|
||||
}
|
||||
|
||||
#endif /* defined(FAST) && defined(USE_FLOAT_MUL) */
|
||||
|
||||
void Gsm_Short_Term_Analysis_Filter (
|
||||
|
||||
struct gsm_state * S,
|
||||
|
||||
word * LARc, /* coded log area ratio [0..7] IN */
|
||||
word * s /* signal [0..159] IN/OUT */
|
||||
)
|
||||
{
|
||||
word * LARpp_j = S->LARpp[ S->j ];
|
||||
word * LARpp_j_1 = S->LARpp[ S->j ^= 1 ];
|
||||
|
||||
word LARp[8];
|
||||
|
||||
#undef FILTER
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
# define FILTER (* (S->fast \
|
||||
? Fast_Short_term_analysis_filtering \
|
||||
: Short_term_analysis_filtering ))
|
||||
|
||||
#else
|
||||
# define FILTER Short_term_analysis_filtering
|
||||
#endif
|
||||
|
||||
Decoding_of_the_coded_Log_Area_Ratios( LARc, LARpp_j );
|
||||
|
||||
Coefficients_0_12( LARpp_j_1, LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 13, s);
|
||||
|
||||
Coefficients_13_26( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 14, s + 13);
|
||||
|
||||
Coefficients_27_39( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 13, s + 27);
|
||||
|
||||
Coefficients_40_159( LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 120, s + 40);
|
||||
}
|
||||
|
||||
void Gsm_Short_Term_Synthesis_Filter (
|
||||
struct gsm_state * S,
|
||||
|
||||
word * LARcr, /* received log area ratios [0..7] IN */
|
||||
word * wt, /* received d [0..159] IN */
|
||||
|
||||
word * s /* signal s [0..159] OUT */
|
||||
)
|
||||
{
|
||||
word * LARpp_j = S->LARpp[ S->j ];
|
||||
word * LARpp_j_1 = S->LARpp[ S->j ^=1 ];
|
||||
|
||||
word LARp[8];
|
||||
|
||||
#undef FILTER
|
||||
#if defined(FAST) && defined(USE_FLOAT_MUL)
|
||||
|
||||
# define FILTER (* (S->fast \
|
||||
? Fast_Short_term_synthesis_filtering \
|
||||
: Short_term_synthesis_filtering ))
|
||||
#else
|
||||
# define FILTER Short_term_synthesis_filtering
|
||||
#endif
|
||||
|
||||
Decoding_of_the_coded_Log_Area_Ratios( LARcr, LARpp_j );
|
||||
|
||||
Coefficients_0_12( LARpp_j_1, LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 13, wt, s );
|
||||
|
||||
Coefficients_13_26( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 14, wt + 13, s + 13 );
|
||||
|
||||
Coefficients_27_39( LARpp_j_1, LARpp_j, LARp);
|
||||
LARp_to_rp( LARp );
|
||||
FILTER( S, LARp, 13, wt + 27, s + 27 );
|
||||
|
||||
Coefficients_40_159( LARpp_j, LARp );
|
||||
LARp_to_rp( LARp );
|
||||
FILTER(S, LARp, 120, wt + 40, s + 40);
|
||||
}
|
||||
60
project/jni/sndfile/src/GSM610/table.c
Normal file
60
project/jni/sndfile/src/GSM610/table.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 1992 by Jutta Degener and Carsten Bormann, Technische
|
||||
* Universitaet Berlin. See the accompanying file "COPYRIGHT" for
|
||||
* details. THERE IS ABSOLUTELY NO WARRANTY FOR THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
/* Most of these tables are inlined at their point of use.
|
||||
*/
|
||||
|
||||
/* 4.4 TABLES USED IN THE FIXED POINT IMPLEMENTATION OF THE RPE-LTP
|
||||
* CODER AND DECODER
|
||||
*
|
||||
* (Most of them inlined, so watch out.)
|
||||
*/
|
||||
|
||||
#define GSM_TABLE_C
|
||||
#include "gsm610_priv.h"
|
||||
|
||||
/* Table 4.1 Quantization of the Log.-Area Ratios
|
||||
*/
|
||||
/* i 1 2 3 4 5 6 7 8 */
|
||||
word gsm_A[8] = {20480, 20480, 20480, 20480, 13964, 15360, 8534, 9036};
|
||||
word gsm_B[8] = { 0, 0, 2048, -2560, 94, -1792, -341, -1144};
|
||||
word gsm_MIC[8] = { -32, -32, -16, -16, -8, -8, -4, -4 };
|
||||
word gsm_MAC[8] = { 31, 31, 15, 15, 7, 7, 3, 3 };
|
||||
|
||||
|
||||
/* Table 4.2 Tabulation of 1/A[1..8]
|
||||
*/
|
||||
word gsm_INVA[8]={ 13107, 13107, 13107, 13107, 19223, 17476, 31454, 29708 };
|
||||
|
||||
|
||||
/* Table 4.3a Decision level of the LTP gain quantizer
|
||||
*/
|
||||
/* bc 0 1 2 3 */
|
||||
word gsm_DLB[4] = { 6554, 16384, 26214, 32767 };
|
||||
|
||||
|
||||
/* Table 4.3b Quantization levels of the LTP gain quantizer
|
||||
*/
|
||||
/* bc 0 1 2 3 */
|
||||
word gsm_QLB[4] = { 3277, 11469, 21299, 32767 };
|
||||
|
||||
|
||||
/* Table 4.4 Coefficients of the weighting filter
|
||||
*/
|
||||
/* i 0 1 2 3 4 5 6 7 8 9 10 */
|
||||
word gsm_H[11] = {-134, -374, 0, 2054, 5741, 8192, 5741, 2054, 0, -374, -134 };
|
||||
|
||||
|
||||
/* Table 4.5 Normalized inverse mantissa used to compute xM/xmax
|
||||
*/
|
||||
/* i 0 1 2 3 4 5 6 7 */
|
||||
word gsm_NRFAC[8] = { 29128, 26215, 23832, 21846, 20165, 18725, 17476, 16384 };
|
||||
|
||||
|
||||
/* Table 4.6 Normalized direct mantissa used to compute xM/xmax
|
||||
*/
|
||||
/* i 0 1 2 3 4 5 6 7 */
|
||||
word gsm_FAC[8] = { 18431, 20479, 22527, 24575, 26623, 28671, 30719, 32767 };
|
||||
1738
project/jni/sndfile/src/aiff.c
Normal file
1738
project/jni/sndfile/src/aiff.c
Normal file
File diff suppressed because it is too large
Load Diff
540
project/jni/sndfile/src/alaw.c
Normal file
540
project/jni/sndfile/src/alaw.c
Normal file
@@ -0,0 +1,540 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
|
||||
static sf_count_t alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static void alaw2s_array (unsigned char *buffer, int count, short *ptr) ;
|
||||
static void alaw2i_array (unsigned char *buffer, int count, int *ptr) ;
|
||||
static void alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact) ;
|
||||
static void alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact) ;
|
||||
|
||||
static void s2alaw_array (const short *buffer, int count, unsigned char *ptr) ;
|
||||
static void i2alaw_array (const int *buffer, int count, unsigned char *ptr) ;
|
||||
static void f2alaw_array (const float *buffer, int count, unsigned char *ptr, float normfact) ;
|
||||
static void d2alaw_array (const double *buffer, int count, unsigned char *ptr, double normfact) ;
|
||||
|
||||
|
||||
int
|
||||
alaw_init (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ psf->read_short = alaw_read_alaw2s ;
|
||||
psf->read_int = alaw_read_alaw2i ;
|
||||
psf->read_float = alaw_read_alaw2f ;
|
||||
psf->read_double = alaw_read_alaw2d ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->write_short = alaw_write_s2alaw ;
|
||||
psf->write_int = alaw_write_i2alaw ;
|
||||
psf->write_float = alaw_write_f2alaw ;
|
||||
psf->write_double = alaw_write_d2alaw ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->sf.channels ;
|
||||
|
||||
if (psf->filelength > psf->dataoffset)
|
||||
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset : psf->filelength - psf->dataoffset ;
|
||||
else
|
||||
psf->datalength = 0 ;
|
||||
|
||||
psf->sf.frames = psf->blockwidth > 0 ? psf->datalength / psf->blockwidth : 0 ;
|
||||
|
||||
return 0 ;
|
||||
} /* alaw_init */
|
||||
|
||||
/*==============================================================================
|
||||
* Private static functions and data.
|
||||
*/
|
||||
|
||||
static
|
||||
short alaw_decode [256] =
|
||||
{ -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
|
||||
-7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
|
||||
-2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
|
||||
-3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
|
||||
-22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
|
||||
-30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
|
||||
-11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
|
||||
-15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
|
||||
-344, -328, -376, -360, -280, -264, -312, -296,
|
||||
-472, -456, -504, -488, -408, -392, -440, -424,
|
||||
-88, -72, -120, -104, -24, -8, -56, -40,
|
||||
-216, -200, -248, -232, -152, -136, -184, -168,
|
||||
-1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
|
||||
-1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
|
||||
-688, -656, -752, -720, -560, -528, -624, -592,
|
||||
-944, -912, -1008, -976, -816, -784, -880, -848,
|
||||
5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
|
||||
7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
|
||||
2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
|
||||
3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
|
||||
22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
|
||||
30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
|
||||
11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
|
||||
15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
|
||||
344, 328, 376, 360, 280, 264, 312, 296,
|
||||
472, 456, 504, 488, 408, 392, 440, 424,
|
||||
88, 72, 120, 104, 24, 8, 56, 40,
|
||||
216, 200, 248, 232, 152, 136, 184, 168,
|
||||
1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
|
||||
1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
|
||||
688, 656, 752, 720, 560, 528, 624, 592,
|
||||
944, 912, 1008, 976, 816, 784, 880, 848
|
||||
} ; /* alaw_decode */
|
||||
|
||||
static
|
||||
unsigned char alaw_encode [2048 + 1] =
|
||||
{ 0xd5, 0xd4, 0xd7, 0xd6, 0xd1, 0xd0, 0xd3, 0xd2, 0xdd, 0xdc, 0xdf, 0xde,
|
||||
0xd9, 0xd8, 0xdb, 0xda, 0xc5, 0xc4, 0xc7, 0xc6, 0xc1, 0xc0, 0xc3, 0xc2,
|
||||
0xcd, 0xcc, 0xcf, 0xce, 0xc9, 0xc8, 0xcb, 0xca, 0xf5, 0xf5, 0xf4, 0xf4,
|
||||
0xf7, 0xf7, 0xf6, 0xf6, 0xf1, 0xf1, 0xf0, 0xf0, 0xf3, 0xf3, 0xf2, 0xf2,
|
||||
0xfd, 0xfd, 0xfc, 0xfc, 0xff, 0xff, 0xfe, 0xfe, 0xf9, 0xf9, 0xf8, 0xf8,
|
||||
0xfb, 0xfb, 0xfa, 0xfa, 0xe5, 0xe5, 0xe5, 0xe5, 0xe4, 0xe4, 0xe4, 0xe4,
|
||||
0xe7, 0xe7, 0xe7, 0xe7, 0xe6, 0xe6, 0xe6, 0xe6, 0xe1, 0xe1, 0xe1, 0xe1,
|
||||
0xe0, 0xe0, 0xe0, 0xe0, 0xe3, 0xe3, 0xe3, 0xe3, 0xe2, 0xe2, 0xe2, 0xe2,
|
||||
0xed, 0xed, 0xed, 0xed, 0xec, 0xec, 0xec, 0xec, 0xef, 0xef, 0xef, 0xef,
|
||||
0xee, 0xee, 0xee, 0xee, 0xe9, 0xe9, 0xe9, 0xe9, 0xe8, 0xe8, 0xe8, 0xe8,
|
||||
0xeb, 0xeb, 0xeb, 0xeb, 0xea, 0xea, 0xea, 0xea, 0x95, 0x95, 0x95, 0x95,
|
||||
0x95, 0x95, 0x95, 0x95, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94, 0x94,
|
||||
0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x97, 0x96, 0x96, 0x96, 0x96,
|
||||
0x96, 0x96, 0x96, 0x96, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91, 0x91,
|
||||
0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x93, 0x93, 0x93, 0x93,
|
||||
0x93, 0x93, 0x93, 0x93, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92, 0x92,
|
||||
0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9d, 0x9c, 0x9c, 0x9c, 0x9c,
|
||||
0x9c, 0x9c, 0x9c, 0x9c, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f, 0x9f,
|
||||
0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x99, 0x99, 0x99, 0x99,
|
||||
0x99, 0x99, 0x99, 0x99, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98, 0x98,
|
||||
0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9b, 0x9a, 0x9a, 0x9a, 0x9a,
|
||||
0x9a, 0x9a, 0x9a, 0x9a, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
|
||||
0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x84, 0x84, 0x84, 0x84,
|
||||
0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84, 0x84,
|
||||
0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87, 0x87,
|
||||
0x87, 0x87, 0x87, 0x87, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86,
|
||||
0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x86, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83,
|
||||
0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x82, 0x82, 0x82, 0x82,
|
||||
0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82, 0x82,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d, 0x8d,
|
||||
0x8d, 0x8d, 0x8d, 0x8d, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c,
|
||||
0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8c, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e, 0x8e,
|
||||
0x8e, 0x8e, 0x8e, 0x8e, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89,
|
||||
0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x89, 0x88, 0x88, 0x88, 0x88,
|
||||
0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b, 0x8b,
|
||||
0x8b, 0x8b, 0x8b, 0x8b, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a,
|
||||
0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0x8a, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5, 0xb5,
|
||||
0xb5, 0xb5, 0xb5, 0xb5, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4, 0xb4,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7,
|
||||
0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb7, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6, 0xb6,
|
||||
0xb6, 0xb6, 0xb6, 0xb6, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1, 0xb1,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0,
|
||||
0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb0, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3, 0xb3,
|
||||
0xb3, 0xb3, 0xb3, 0xb3, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2, 0xb2,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd,
|
||||
0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbd, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc, 0xbc,
|
||||
0xbc, 0xbc, 0xbc, 0xbc, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf, 0xbf,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe,
|
||||
0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xbe, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9, 0xb9,
|
||||
0xb9, 0xb9, 0xb9, 0xb9, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8, 0xb8,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb,
|
||||
0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xbb, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba, 0xba,
|
||||
0xba, 0xba, 0xba, 0xba, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
|
||||
0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4, 0xa4,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7, 0xa7,
|
||||
0xa7, 0xa7, 0xa7, 0xa7, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6,
|
||||
0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa6, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1, 0xa1,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0, 0xa0,
|
||||
0xa0, 0xa0, 0xa0, 0xa0, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3,
|
||||
0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa3, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2, 0xa2,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad, 0xad,
|
||||
0xad, 0xad, 0xad, 0xad, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac,
|
||||
0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xac, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae, 0xae,
|
||||
0xae, 0xae, 0xae, 0xae, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9,
|
||||
0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa9, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8, 0xa8,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab, 0xab,
|
||||
0xab, 0xab, 0xab, 0xab, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
|
||||
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0x2a
|
||||
} ; /* alaw_encode */
|
||||
|
||||
static inline void
|
||||
alaw2s_array (unsigned char *buffer, int count, short *ptr)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = alaw_decode [(int) buffer [count]] ;
|
||||
} /* alaw2s_array */
|
||||
|
||||
static inline void
|
||||
alaw2i_array (unsigned char *buffer, int count, int *ptr)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = alaw_decode [(int) buffer [count]] << 16 ;
|
||||
} /* alaw2i_array */
|
||||
|
||||
static inline void
|
||||
alaw2f_array (unsigned char *buffer, int count, float *ptr, float normfact)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ;
|
||||
} /* alaw2f_array */
|
||||
|
||||
static inline void
|
||||
alaw2d_array (unsigned char *buffer, int count, double *ptr, double normfact)
|
||||
{ while (--count >= 0)
|
||||
ptr [count] = normfact * alaw_decode [(int) buffer [count]] ;
|
||||
} /* alaw2d_array */
|
||||
|
||||
static inline void
|
||||
s2alaw_array (const short *ptr, int count, unsigned char *buffer)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [ptr [count] / 16] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [ptr [count] / -16] ;
|
||||
} ;
|
||||
} /* s2alaw_array */
|
||||
|
||||
static inline void
|
||||
i2alaw_array (const int *ptr, int count, unsigned char *buffer)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [ptr [count] >> (16 + 4)] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [- ptr [count] >> (16 + 4)] ;
|
||||
} ;
|
||||
} /* i2alaw_array */
|
||||
|
||||
static inline void
|
||||
f2alaw_array (const float *ptr, int count, unsigned char *buffer, float normfact)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [lrintf (normfact * ptr [count])] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [- lrintf (normfact * ptr [count])] ;
|
||||
} ;
|
||||
} /* f2alaw_array */
|
||||
|
||||
static inline void
|
||||
d2alaw_array (const double *ptr, int count, unsigned char *buffer, double normfact)
|
||||
{ while (--count >= 0)
|
||||
{ if (ptr [count] >= 0)
|
||||
buffer [count] = alaw_encode [lrint (normfact * ptr [count])] ;
|
||||
else
|
||||
buffer [count] = 0x7F & alaw_encode [- lrint (normfact * ptr [count])] ;
|
||||
} ;
|
||||
} /* d2alaw_array */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2s_array (psf->u.ucbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_read_alaw2s */
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2i_array (psf->u.ucbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_read_alaw2i */
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2f_array (psf->u.ucbuf, readcount, ptr + total, normfact) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_read_alaw2f */
|
||||
|
||||
static sf_count_t
|
||||
alaw_read_alaw2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
alaw2d_array (psf->u.ucbuf, readcount, ptr + total, normfact) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_read_alaw2d */
|
||||
|
||||
/*=============================================================================================
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_s2alaw (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_write_s2alaw */
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_i2alaw (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2alaw_array (ptr + total, bufferlen, psf->u.ucbuf) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_write_i2alaw */
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_f2alaw (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
f2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_write_f2alaw */
|
||||
|
||||
static sf_count_t
|
||||
alaw_write_d2alaw (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double) ? (1.0 * 0x7FFF) / 16.0 : 1.0 / 16.0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.ucbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
d2alaw_array (ptr + total, bufferlen, psf->u.ucbuf, normfact) ;
|
||||
writecount = psf_fwrite (psf->u.ucbuf, 1, bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* alaw_write_d2alaw */
|
||||
|
||||
452
project/jni/sndfile/src/au.c
Normal file
452
project/jni/sndfile/src/au.c
Normal file
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define DOTSND_MARKER (MAKE_MARKER ('.', 's', 'n', 'd'))
|
||||
#define DNSDOT_MARKER (MAKE_MARKER ('d', 'n', 's', '.'))
|
||||
|
||||
#define AU_DATA_OFFSET 24
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Known AU file encoding types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ AU_ENCODING_ULAW_8 = 1, /* 8-bit u-law samples */
|
||||
AU_ENCODING_PCM_8 = 2, /* 8-bit linear samples */
|
||||
AU_ENCODING_PCM_16 = 3, /* 16-bit linear samples */
|
||||
AU_ENCODING_PCM_24 = 4, /* 24-bit linear samples */
|
||||
AU_ENCODING_PCM_32 = 5, /* 32-bit linear samples */
|
||||
|
||||
AU_ENCODING_FLOAT = 6, /* floating-point samples */
|
||||
AU_ENCODING_DOUBLE = 7, /* double-precision float samples */
|
||||
AU_ENCODING_INDIRECT = 8, /* fragmented sampled data */
|
||||
AU_ENCODING_NESTED = 9, /* ? */
|
||||
AU_ENCODING_DSP_CORE = 10, /* DSP program */
|
||||
AU_ENCODING_DSP_DATA_8 = 11, /* 8-bit fixed-point samples */
|
||||
AU_ENCODING_DSP_DATA_16 = 12, /* 16-bit fixed-point samples */
|
||||
AU_ENCODING_DSP_DATA_24 = 13, /* 24-bit fixed-point samples */
|
||||
AU_ENCODING_DSP_DATA_32 = 14, /* 32-bit fixed-point samples */
|
||||
|
||||
AU_ENCODING_DISPLAY = 16, /* non-audio display data */
|
||||
AU_ENCODING_MULAW_SQUELCH = 17, /* ? */
|
||||
AU_ENCODING_EMPHASIZED = 18, /* 16-bit linear with emphasis */
|
||||
AU_ENCODING_NEXT = 19, /* 16-bit linear with compression (NEXT) */
|
||||
AU_ENCODING_COMPRESSED_EMPHASIZED = 20, /* A combination of the two above */
|
||||
AU_ENCODING_DSP_COMMANDS = 21, /* Music Kit DSP commands */
|
||||
AU_ENCODING_DSP_COMMANDS_SAMPLES = 22, /* ? */
|
||||
|
||||
AU_ENCODING_ADPCM_G721_32 = 23, /* G721 32 kbs ADPCM - 4 bits per sample. */
|
||||
AU_ENCODING_ADPCM_G722 = 24, /* G722 64 kbs ADPCM */
|
||||
AU_ENCODING_ADPCM_G723_24 = 25, /* G723 24 kbs ADPCM - 3 bits per sample. */
|
||||
AU_ENCODING_ADPCM_G723_40 = 26, /* G723 40 kbs ADPCM - 5 bits per sample. */
|
||||
|
||||
AU_ENCODING_ALAW_8 = 27
|
||||
} ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int dataoffset ;
|
||||
int datasize ;
|
||||
int encoding ;
|
||||
int samplerate ;
|
||||
int channels ;
|
||||
} AU_FMT ;
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int au_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int au_format_to_encoding (int format) ;
|
||||
|
||||
static int au_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int au_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
au_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = au_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_AU)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
else if (psf->endian != SF_ENDIAN_LITTLE)
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (au_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
psf->write_header = au_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = au_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */
|
||||
ulaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
|
||||
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */
|
||||
alaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
/* Lite remove start */
|
||||
case SF_FORMAT_FLOAT : /* 32-bit floats. */
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE : /* 64-bit double precision floats. */
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_G721_32 :
|
||||
error = g72x_init (psf) ;
|
||||
psf->sf.seekable = SF_FALSE ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_G723_24 :
|
||||
error = g72x_init (psf) ;
|
||||
psf->sf.seekable = SF_FALSE ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_G723_40 :
|
||||
error = g72x_init (psf) ;
|
||||
psf->sf.seekable = SF_FALSE ;
|
||||
break ;
|
||||
/* Lite remove end */
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* au_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
au_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
au_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* au_close */
|
||||
|
||||
static int
|
||||
au_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ sf_count_t current ;
|
||||
int encoding, datalength ;
|
||||
|
||||
if (psf->pipeoffset > 0)
|
||||
return 0 ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
encoding = au_format_to_encoding (SF_CODEC (psf->sf.format)) ;
|
||||
if (! encoding)
|
||||
return (psf->error = SFE_BAD_OPEN_FORMAT) ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
/*
|
||||
** Only attempt to seek if we are not writng to a pipe. If we are
|
||||
** writing to a pipe we shouldn't be here anyway.
|
||||
*/
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
/*
|
||||
** AU format files allow a datalength value of -1 if the datalength
|
||||
** is not know at the time the header is written.
|
||||
** Also use this value of -1 if the datalength > 2 gigabytes.
|
||||
*/
|
||||
if (psf->datalength < 0 || psf->datalength > 0x7FFFFFFF)
|
||||
datalength = -1 ;
|
||||
else
|
||||
datalength = (int) (psf->datalength & 0x7FFFFFFF) ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
{ psf_binheader_writef (psf, "Em4", DOTSND_MARKER, AU_DATA_OFFSET) ;
|
||||
psf_binheader_writef (psf, "E4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
|
||||
}
|
||||
else if (psf->endian == SF_ENDIAN_LITTLE)
|
||||
{ psf_binheader_writef (psf, "em4", DNSDOT_MARKER, AU_DATA_OFFSET) ;
|
||||
psf_binheader_writef (psf, "e4444", datalength, encoding, psf->sf.samplerate, psf->sf.channels) ;
|
||||
}
|
||||
else
|
||||
return (psf->error = SFE_BAD_OPEN_FORMAT) ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* au_write_header */
|
||||
|
||||
static int
|
||||
au_format_to_encoding (int format)
|
||||
{
|
||||
switch (format)
|
||||
{ case SF_FORMAT_PCM_S8 : return AU_ENCODING_PCM_8 ;
|
||||
case SF_FORMAT_PCM_16 : return AU_ENCODING_PCM_16 ;
|
||||
case SF_FORMAT_PCM_24 : return AU_ENCODING_PCM_24 ;
|
||||
case SF_FORMAT_PCM_32 : return AU_ENCODING_PCM_32 ;
|
||||
|
||||
case SF_FORMAT_FLOAT : return AU_ENCODING_FLOAT ;
|
||||
case SF_FORMAT_DOUBLE : return AU_ENCODING_DOUBLE ;
|
||||
|
||||
case SF_FORMAT_ULAW : return AU_ENCODING_ULAW_8 ;
|
||||
case SF_FORMAT_ALAW : return AU_ENCODING_ALAW_8 ;
|
||||
|
||||
case SF_FORMAT_G721_32 : return AU_ENCODING_ADPCM_G721_32 ;
|
||||
case SF_FORMAT_G723_24 : return AU_ENCODING_ADPCM_G723_24 ;
|
||||
case SF_FORMAT_G723_40 : return AU_ENCODING_ADPCM_G723_40 ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
return 0 ;
|
||||
} /* au_format_to_encoding */
|
||||
|
||||
static int
|
||||
au_read_header (SF_PRIVATE *psf)
|
||||
{ AU_FMT au_fmt ;
|
||||
int marker, dword ;
|
||||
|
||||
memset (&au_fmt, 0, sizeof (au_fmt)) ;
|
||||
psf_binheader_readf (psf, "pm", 0, &marker) ;
|
||||
psf_log_printf (psf, "%M\n", marker) ;
|
||||
|
||||
if (marker == DOTSND_MARKER)
|
||||
{ psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
psf_binheader_readf (psf, "E44444", &(au_fmt.dataoffset), &(au_fmt.datasize),
|
||||
&(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ;
|
||||
}
|
||||
else if (marker == DNSDOT_MARKER)
|
||||
{ psf->endian = SF_ENDIAN_LITTLE ;
|
||||
psf_binheader_readf (psf, "e44444", &(au_fmt.dataoffset), &(au_fmt.datasize),
|
||||
&(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ;
|
||||
}
|
||||
else
|
||||
return SFE_AU_NO_DOTSND ;
|
||||
|
||||
psf_log_printf (psf, " Data Offset : %d\n", au_fmt.dataoffset) ;
|
||||
|
||||
if (psf->fileoffset > 0 && au_fmt.datasize == -1)
|
||||
{ psf_log_printf (psf, " Data Size : -1\n") ;
|
||||
return SFE_AU_EMBED_BAD_LEN ;
|
||||
} ;
|
||||
|
||||
if (psf->fileoffset > 0)
|
||||
{ psf->filelength = au_fmt.dataoffset + au_fmt.datasize ;
|
||||
psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ;
|
||||
}
|
||||
else if (au_fmt.datasize == -1 || au_fmt.dataoffset + au_fmt.datasize == psf->filelength)
|
||||
psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ;
|
||||
else if (au_fmt.dataoffset + au_fmt.datasize < psf->filelength)
|
||||
{ psf->filelength = au_fmt.dataoffset + au_fmt.datasize ;
|
||||
psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ;
|
||||
}
|
||||
else
|
||||
{ dword = psf->filelength - au_fmt.dataoffset ;
|
||||
psf_log_printf (psf, " Data Size : %d (should be %d)\n", au_fmt.datasize, dword) ;
|
||||
au_fmt.datasize = dword ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = au_fmt.dataoffset ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf_ftell (psf) < psf->dataoffset)
|
||||
psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ;
|
||||
|
||||
psf->sf.samplerate = au_fmt.samplerate ;
|
||||
psf->sf.channels = au_fmt.channels ;
|
||||
|
||||
/* Only fill in type major. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
psf->sf.format = SF_FORMAT_AU ;
|
||||
else if (psf->endian == SF_ENDIAN_LITTLE)
|
||||
psf->sf.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU ;
|
||||
|
||||
psf_log_printf (psf, " Encoding : %d => ", au_fmt.encoding) ;
|
||||
|
||||
psf->sf.format = SF_ENDIAN (psf->sf.format) ;
|
||||
|
||||
switch (au_fmt.encoding)
|
||||
{ case AU_ENCODING_ULAW_8 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ULAW ;
|
||||
psf->bytewidth = 1 ; /* Before decoding */
|
||||
psf_log_printf (psf, "8-bit ISDN u-law\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_PCM_8 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_S8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
psf_log_printf (psf, "8-bit linear PCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_PCM_16 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
psf_log_printf (psf, "16-bit linear PCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_PCM_24 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_24 ;
|
||||
psf->bytewidth = 3 ;
|
||||
psf_log_printf (psf, "24-bit linear PCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_PCM_32 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_32 ;
|
||||
psf->bytewidth = 4 ;
|
||||
psf_log_printf (psf, "32-bit linear PCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_FLOAT :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_FLOAT ;
|
||||
psf->bytewidth = 4 ;
|
||||
psf_log_printf (psf, "32-bit float\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_DOUBLE :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_DOUBLE ;
|
||||
psf->bytewidth = 8 ;
|
||||
psf_log_printf (psf, "64-bit double precision float\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_ALAW_8 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ALAW ;
|
||||
psf->bytewidth = 1 ; /* Before decoding */
|
||||
psf_log_printf (psf, "8-bit ISDN A-law\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_ADPCM_G721_32 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G721_32 ;
|
||||
psf->bytewidth = 0 ;
|
||||
psf_log_printf (psf, "G721 32kbs ADPCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_ADPCM_G723_24 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_24 ;
|
||||
psf->bytewidth = 0 ;
|
||||
psf_log_printf (psf, "G723 24kbs ADPCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_ADPCM_G723_40 :
|
||||
psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_40 ;
|
||||
psf->bytewidth = 0 ;
|
||||
psf_log_printf (psf, "G723 40kbs ADPCM\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_ADPCM_G722 :
|
||||
psf_log_printf (psf, "G722 64 kbs ADPCM (unsupported)\n") ;
|
||||
break ;
|
||||
|
||||
case AU_ENCODING_NEXT :
|
||||
psf_log_printf (psf, "Weird NeXT encoding format (unsupported)\n") ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "Unknown!!\n") ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " Sample Rate : %d\n", au_fmt.samplerate) ;
|
||||
if (au_fmt.channels < 1)
|
||||
{ psf_log_printf (psf, " Channels : %d **** should be >= 1\n", au_fmt.channels) ;
|
||||
return SFE_CHANNEL_COUNT_ZERO ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Channels : %d\n", au_fmt.channels) ;
|
||||
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
if (! psf->sf.frames && psf->blockwidth)
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
|
||||
return 0 ;
|
||||
} /* au_read_header */
|
||||
|
||||
105
project/jni/sndfile/src/audio_detect.c
Normal file
105
project/jni/sndfile/src/audio_detect.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
typedef struct
|
||||
{ int le_float ;
|
||||
int be_float ;
|
||||
int le_int_24_32 ;
|
||||
int be_int_24_32 ;
|
||||
} VOTE ;
|
||||
|
||||
|
||||
static void vote_for_format (VOTE * vote, const unsigned char * data, int datalen) ;
|
||||
|
||||
int
|
||||
audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen)
|
||||
{ VOTE vote ;
|
||||
|
||||
if (psf == NULL)
|
||||
return 0 ;
|
||||
|
||||
if (ad == NULL || datalen < 256)
|
||||
return 0 ;
|
||||
|
||||
vote_for_format (&vote, data, datalen) ;
|
||||
|
||||
psf_log_printf (psf, "audio_detect :\n"
|
||||
" le_float : %d\n"
|
||||
" be_float : %d\n"
|
||||
" le_int_24_32 : %d\n"
|
||||
" be_int_24_32 : %d\n",
|
||||
vote.le_float, vote.be_float, vote.le_int_24_32, vote.be_int_24_32) ;
|
||||
|
||||
if (0) puts (psf->logbuffer) ;
|
||||
|
||||
if (ad->endianness == SF_ENDIAN_LITTLE && vote.le_float > (3 * datalen) / 4)
|
||||
{ /* Almost certainly 32 bit floats. */
|
||||
return SF_FORMAT_FLOAT ;
|
||||
} ;
|
||||
|
||||
if (ad->endianness == SF_ENDIAN_LITTLE && vote.le_int_24_32 > (3 * datalen) / 4)
|
||||
{ /* Almost certainly 24 bit data stored in 32 bit ints. */
|
||||
return SF_FORMAT_PCM_32 ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* data_detect */
|
||||
|
||||
static void
|
||||
vote_for_format (VOTE * vote, const unsigned char * data, int datalen)
|
||||
{
|
||||
int k ;
|
||||
|
||||
memset (vote, 0, sizeof (VOTE)) ;
|
||||
|
||||
datalen -= datalen % 4 ;
|
||||
|
||||
for (k = 0 ; k < datalen ; k ++)
|
||||
{ if ((k % 4) == 0)
|
||||
{ if (data [k] == 0 && data [k + 1] != 0)
|
||||
vote->le_int_24_32 += 4 ;
|
||||
|
||||
if (data [2] != 0 && data [3] == 0)
|
||||
vote->le_int_24_32 += 4 ;
|
||||
|
||||
if (data [0] != 0 && data [3] > 0x43 && data [3] < 0x4B)
|
||||
vote->le_float += 4 ;
|
||||
|
||||
if (data [3] != 0 && data [0] > 0x43 && data [0] < 0x4B)
|
||||
vote->be_float += 4 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* vote_for_format */
|
||||
|
||||
247
project/jni/sndfile/src/avr.c
Normal file
247
project/jni/sndfile/src/avr.c
Normal file
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
** Copyright (C) 2004-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#define TWOBIT_MARKER (MAKE_MARKER ('2', 'B', 'I', 'T'))
|
||||
#define AVR_HDR_SIZE 128
|
||||
|
||||
#define SFE_AVR_X 666
|
||||
|
||||
/*
|
||||
** From: hyc@hanauma.Jpl.Nasa.Gov (Howard Chu)
|
||||
**
|
||||
** A lot of PD software exists to play Mac .snd files on the ST. One other
|
||||
** format that seems pretty popular (used by a number of commercial packages)
|
||||
** is the AVR format (from Audio Visual Research). This format has a 128 byte
|
||||
** header that looks like this (its actually packed, but thats not portable):
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int marker ; /* 2BIT */
|
||||
char name [8] ; /* null-padded sample name */
|
||||
short mono ; /* 0 = mono, 0xffff = stereo */
|
||||
short rez ; /* 8 = 8 bit, 16 = 16 bit */
|
||||
short sign ; /* 0 = unsigned, 0xffff = signed */
|
||||
|
||||
short loop ; /* 0 = no loop, 0xffff = looping sample */
|
||||
short midi ; /* 0xffff = no MIDI note assigned, */
|
||||
/* 0xffXX = single key note assignment */
|
||||
/* 0xLLHH = key split, low/hi note */
|
||||
int srate ; /* sample frequency in hertz */
|
||||
int frames ; /* sample length in bytes or words (see rez) */
|
||||
int lbeg ; /* offset to start of loop in bytes or words. */
|
||||
/* set to zero if unused */
|
||||
int lend ; /* offset to end of loop in bytes or words. */
|
||||
/* set to sample length if unused */
|
||||
short res1 ; /* Reserved, MIDI keyboard split */
|
||||
short res2 ; /* Reserved, sample compression */
|
||||
short res3 ; /* Reserved */
|
||||
char ext [20] ; /* Additional filename space, used if (name[7] != 0) */
|
||||
char user [64] ; /* User defined. Typically ASCII message */
|
||||
} AVR_HEADER ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int avr_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int avr_read_header (SF_PRIVATE *psf) ;
|
||||
static int avr_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
avr_open (SF_PRIVATE *psf)
|
||||
{ int error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = avr_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_AVR)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (avr_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
psf->write_header = avr_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = avr_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
error = pcm_init (psf) ;
|
||||
|
||||
return error ;
|
||||
} /* avr_open */
|
||||
|
||||
static int
|
||||
avr_read_header (SF_PRIVATE *psf)
|
||||
{ AVR_HEADER hdr ;
|
||||
|
||||
memset (&hdr, 0, sizeof (hdr)) ;
|
||||
|
||||
psf_binheader_readf (psf, "pmb", 0, &hdr.marker, &hdr.name, sizeof (hdr.name)) ;
|
||||
psf_log_printf (psf, "%M\n", hdr.marker) ;
|
||||
|
||||
if (hdr.marker != TWOBIT_MARKER)
|
||||
return SFE_AVR_X ;
|
||||
|
||||
psf_log_printf (psf, " Name : %s\n", hdr.name) ;
|
||||
|
||||
psf_binheader_readf (psf, "E22222", &hdr.mono, &hdr.rez, &hdr.sign, &hdr.loop, &hdr.midi) ;
|
||||
|
||||
psf->sf.channels = (hdr.mono & 1) + 1 ;
|
||||
|
||||
psf_log_printf (psf, " Channels : %d\n Bit width : %d\n Signed : %s\n",
|
||||
(hdr.mono & 1) + 1, hdr.rez, hdr.sign ? "yes" : "no") ;
|
||||
|
||||
switch ((hdr.rez << 16) + (hdr.sign & 1))
|
||||
{ case ((8 << 16) + 0) :
|
||||
psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_U8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
break ;
|
||||
|
||||
case ((8 << 16) + 1) :
|
||||
psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_S8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
break ;
|
||||
|
||||
case ((16 << 16) + 1) :
|
||||
psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "Error : bad rez/sign combination.\n") ;
|
||||
return SFE_AVR_X ;
|
||||
} ;
|
||||
|
||||
psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ;
|
||||
|
||||
psf->sf.frames = hdr.frames ;
|
||||
psf->sf.samplerate = hdr.srate ;
|
||||
|
||||
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
|
||||
psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ;
|
||||
|
||||
psf_binheader_readf (psf, "E222", &hdr.res1, &hdr.res2, &hdr.res3) ;
|
||||
psf_binheader_readf (psf, "bb", hdr.ext, sizeof (hdr.ext), hdr.user, sizeof (hdr.user)) ;
|
||||
|
||||
psf_log_printf (psf, " Ext : %s\n User : %s\n", hdr.ext, hdr.user) ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
psf->dataoffset = AVR_HDR_SIZE ;
|
||||
psf->datalength = hdr.frames * (hdr.rez / 8) ;
|
||||
|
||||
if (psf->fileoffset > 0)
|
||||
psf->filelength = AVR_HDR_SIZE + psf->datalength ;
|
||||
|
||||
if (psf_ftell (psf) != psf->dataoffset)
|
||||
psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ;
|
||||
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
if (psf->sf.frames == 0 && psf->blockwidth)
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
|
||||
return 0 ;
|
||||
} /* avr_read_header */
|
||||
|
||||
static int
|
||||
avr_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ sf_count_t current ;
|
||||
int sign ;
|
||||
|
||||
if (psf->pipeoffset > 0)
|
||||
return 0 ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
/*
|
||||
** Only attempt to seek if we are not writng to a pipe. If we are
|
||||
** writing to a pipe we shouldn't be here anyway.
|
||||
*/
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, make_size_t (8),
|
||||
psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ;
|
||||
|
||||
sign = ((SF_CODEC (psf->sf.format)) == SF_FORMAT_PCM_U8) ? 0 : 0xFFFF ;
|
||||
|
||||
psf_binheader_writef (psf, "E222", sign, 0, 0xFFFF) ;
|
||||
psf_binheader_writef (psf, "E4444", psf->sf.samplerate, psf->sf.frames, 0, 0) ;
|
||||
|
||||
psf_binheader_writef (psf, "E222zz", 0, 0, 0, make_size_t (20), make_size_t (64)) ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* avr_write_header */
|
||||
|
||||
static int
|
||||
avr_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
avr_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* avr_close */
|
||||
|
||||
190
project/jni/sndfile/src/broadcast.c
Normal file
190
project/jni/sndfile/src/broadcast.c
Normal file
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
** Copyright (C) 2006-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2006 Paul Davis <paul@linuxaudiosystems.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
|
||||
static int gen_coding_history (char * added_history, int added_history_max, const SF_INFO * psfinfo) ;
|
||||
|
||||
static inline size_t
|
||||
bc_min_size (const SF_BROADCAST_INFO* info)
|
||||
{ if (info == NULL)
|
||||
return 0 ;
|
||||
|
||||
return offsetof (SF_BROADCAST_INFO, coding_history) + info->coding_history_size ;
|
||||
} /* bc_min_size */
|
||||
|
||||
SF_BROADCAST_INFO_16K*
|
||||
broadcast_var_alloc (void)
|
||||
{ return calloc (1, sizeof (SF_BROADCAST_INFO_16K)) ;
|
||||
} /* broadcast_var_alloc */
|
||||
|
||||
int
|
||||
broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * info, size_t datasize)
|
||||
{ size_t len ;
|
||||
|
||||
if (info == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
if (bc_min_size (info) > datasize)
|
||||
{ psf->error = SFE_BAD_BROADCAST_INFO_SIZE ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
if (datasize >= sizeof (SF_BROADCAST_INFO_16K))
|
||||
{ psf->error = SFE_BAD_BROADCAST_INFO_TOO_BIG ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_16k == NULL)
|
||||
{ if ((psf->broadcast_16k = broadcast_var_alloc ()) == NULL)
|
||||
{ psf->error = SFE_MALLOC_FAILED ;
|
||||
return SF_FALSE ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
memcpy (psf->broadcast_16k, info, offsetof (SF_BROADCAST_INFO, coding_history)) ;
|
||||
|
||||
psf_strlcpy_crlf (psf->broadcast_16k->coding_history, info->coding_history, sizeof (psf->broadcast_16k->coding_history), datasize - offsetof (SF_BROADCAST_INFO, coding_history)) ;
|
||||
len = strlen (psf->broadcast_16k->coding_history) ;
|
||||
|
||||
if (len > 0 && psf->broadcast_16k->coding_history [len - 1] != '\n')
|
||||
psf_strlcat (psf->broadcast_16k->coding_history, sizeof (psf->broadcast_16k->coding_history), "\r\n") ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ char added_history [256] ;
|
||||
|
||||
gen_coding_history (added_history, sizeof (added_history), &(psf->sf)) ;
|
||||
psf_strlcat (psf->broadcast_16k->coding_history, sizeof (psf->broadcast_16k->coding_history), added_history) ;
|
||||
} ;
|
||||
|
||||
/* Force coding_history_size to be even. */
|
||||
len = strlen (psf->broadcast_16k->coding_history) ;
|
||||
len += (len & 1) ? 1 : 2 ;
|
||||
psf->broadcast_16k->coding_history_size = len ;
|
||||
|
||||
/* Currently writing this version. */
|
||||
psf->broadcast_16k->version = 1 ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* broadcast_var_set */
|
||||
|
||||
|
||||
int
|
||||
broadcast_var_get (SF_PRIVATE *psf, SF_BROADCAST_INFO * data, size_t datasize)
|
||||
{ size_t size ;
|
||||
|
||||
if (psf->broadcast_16k == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
size = SF_MIN (datasize, bc_min_size ((const SF_BROADCAST_INFO *) psf->broadcast_16k)) ;
|
||||
|
||||
memcpy (data, psf->broadcast_16k, size) ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* broadcast_var_get */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
gen_coding_history (char * added_history, int added_history_max, const SF_INFO * psfinfo)
|
||||
{ char chnstr [16] ;
|
||||
int count, width ;
|
||||
|
||||
/*
|
||||
** From : http://www.sr.se/utveckling/tu/bwf/docs/codhist2.htm
|
||||
**
|
||||
** Parameter Variable string <allowed option> Unit
|
||||
** ==========================================================================================
|
||||
** Coding Algorithm A=<ANALOGUE, PCM, MPEG1L1, MPEG1L2, MPEG1L3,
|
||||
** MPEG2L1, MPEG2L2, MPEG2L3>
|
||||
** Sampling frequency F=<11000,22050,24000,32000,44100,48000> [Hz]
|
||||
** Bit-rate B=<any bit-rate allowed in MPEG 2 (ISO/IEC [kbit/s per channel]
|
||||
** 13818-3)>
|
||||
** Word Length W=<8, 12, 14, 16, 18, 20, 22, 24> [bits]
|
||||
** Mode M=<mono, stereo, dual-mono, joint-stereo>
|
||||
** Text, free string T=<a free ASCII-text string for in house use.
|
||||
** This string should contain no commas (ASCII
|
||||
** 2Chex). Examples of the contents: ID-No; codec
|
||||
** type; A/D type>
|
||||
*/
|
||||
|
||||
switch (psfinfo->channels)
|
||||
{ case 0 :
|
||||
return SF_FALSE ;
|
||||
|
||||
case 1 :
|
||||
psf_strlcpy (chnstr, sizeof (chnstr), "mono") ;
|
||||
break ;
|
||||
|
||||
case 2 :
|
||||
psf_strlcpy (chnstr, sizeof (chnstr), "stereo") ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
snprintf (chnstr, sizeof (chnstr), "%uchn", psfinfo->channels) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
switch (SF_CODEC (psfinfo->format))
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_S8 :
|
||||
width = 8 ;
|
||||
break ;
|
||||
case SF_FORMAT_PCM_16 :
|
||||
width = 16 ;
|
||||
break ;
|
||||
case SF_FORMAT_PCM_24 :
|
||||
width = 24 ;
|
||||
break ;
|
||||
case SF_FORMAT_PCM_32 :
|
||||
width = 32 ;
|
||||
break ;
|
||||
case SF_FORMAT_FLOAT :
|
||||
width = 24 ; /* Bits in the mantissa + 1 */
|
||||
break ;
|
||||
case SF_FORMAT_DOUBLE :
|
||||
width = 53 ; /* Bits in the mantissa + 1 */
|
||||
break ;
|
||||
case SF_FORMAT_ULAW :
|
||||
case SF_FORMAT_ALAW :
|
||||
width = 12 ;
|
||||
break ;
|
||||
default :
|
||||
width = 42 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
count = snprintf (added_history, added_history_max,
|
||||
"A=PCM,F=%u,W=%hu,M=%s,T=%s-%s\r\n",
|
||||
psfinfo->samplerate, width, chnstr, PACKAGE, VERSION) ;
|
||||
|
||||
if (count >= added_history_max)
|
||||
return 0 ;
|
||||
|
||||
return count ;
|
||||
} /* gen_coding_history */
|
||||
|
||||
620
project/jni/sndfile/src/caf.c
Normal file
620
project/jni/sndfile/src/caf.c
Normal file
@@ -0,0 +1,620 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "chanmap.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define aac_MARKER MAKE_MARKER ('a', 'a', 'c', ' ')
|
||||
#define alac_MARKER MAKE_MARKER ('a', 'l', 'a', 'c')
|
||||
#define alaw_MARKER MAKE_MARKER ('a', 'l', 'a', 'w')
|
||||
#define caff_MARKER MAKE_MARKER ('c', 'a', 'f', 'f')
|
||||
#define chan_MARKER MAKE_MARKER ('c', 'h', 'a', 'n')
|
||||
#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a')
|
||||
#define desc_MARKER MAKE_MARKER ('d', 'e', 's', 'c')
|
||||
#define edct_MARKER MAKE_MARKER ('e', 'd', 'c', 't')
|
||||
#define free_MARKER MAKE_MARKER ('f', 'r', 'e', 'e')
|
||||
#define ima4_MARKER MAKE_MARKER ('i', 'm', 'a', '4')
|
||||
#define info_MARKER MAKE_MARKER ('i', 'n', 'f', 'o')
|
||||
#define inst_MARKER MAKE_MARKER ('i', 'n', 's', 't')
|
||||
#define kuki_MARKER MAKE_MARKER ('k', 'u', 'k', 'i')
|
||||
#define lpcm_MARKER MAKE_MARKER ('l', 'p', 'c', 'm')
|
||||
#define mark_MARKER MAKE_MARKER ('m', 'a', 'r', 'k')
|
||||
#define midi_MARKER MAKE_MARKER ('m', 'i', 'd', 'i')
|
||||
#define mp1_MARKER MAKE_MARKER ('.', 'm', 'p', '1')
|
||||
#define mp2_MARKER MAKE_MARKER ('.', 'm', 'p', '2')
|
||||
#define mp3_MARKER MAKE_MARKER ('.', 'm', 'p', '3')
|
||||
#define ovvw_MARKER MAKE_MARKER ('o', 'v', 'v', 'w')
|
||||
#define pakt_MARKER MAKE_MARKER ('p', 'a', 'k', 't')
|
||||
#define peak_MARKER MAKE_MARKER ('p', 'e', 'a', 'k')
|
||||
#define regn_MARKER MAKE_MARKER ('r', 'e', 'g', 'n')
|
||||
#define strg_MARKER MAKE_MARKER ('s', 't', 'r', 'g')
|
||||
#define umid_MARKER MAKE_MARKER ('u', 'm', 'i', 'd')
|
||||
#define uuid_MARKER MAKE_MARKER ('u', 'u', 'i', 'd')
|
||||
#define ulaw_MARKER MAKE_MARKER ('u', 'l', 'a', 'w')
|
||||
#define MAC3_MARKER MAKE_MARKER ('M', 'A', 'C', '3')
|
||||
#define MAC6_MARKER MAKE_MARKER ('M', 'A', 'C', '6')
|
||||
|
||||
#define CAF_PEAK_CHUNK_SIZE(ch) ((int) (sizeof (int) + ch * (sizeof (float) + 8)))
|
||||
|
||||
#define SFE_CAF_NOT_CAF 666
|
||||
#define SFE_CAF_NO_DESC 667
|
||||
#define SFE_CAF_BAD_PEAK 668
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ unsigned char srate [8] ;
|
||||
unsigned int fmt_id ;
|
||||
unsigned int fmt_flags ;
|
||||
unsigned int pkt_bytes ;
|
||||
unsigned int pkt_frames ;
|
||||
unsigned int channels_per_frame ;
|
||||
unsigned int bits_per_chan ;
|
||||
} DESC_CHUNK ;
|
||||
|
||||
typedef struct
|
||||
{ int chanmap_tag ;
|
||||
} CAF_PRIVATE ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int caf_close (SF_PRIVATE *psf) ;
|
||||
static int caf_read_header (SF_PRIVATE *psf) ;
|
||||
static int caf_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int caf_command (SF_PRIVATE *psf, int command, void *data, int datasize) ;
|
||||
static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
caf_open (SF_PRIVATE *psf)
|
||||
{ int subformat, format, error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = caf_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if ((psf->container_data = calloc (1, sizeof (CAF_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
format = SF_CONTAINER (psf->sf.format) ;
|
||||
if (format != SF_FORMAT_CAF)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
if (psf->file.mode != SFM_RDWR || psf->filelength < 44)
|
||||
{ psf->filelength = 0 ;
|
||||
psf->datalength = 0 ;
|
||||
psf->dataoffset = 0 ;
|
||||
psf->sf.frames = 0 ;
|
||||
} ;
|
||||
|
||||
psf->str_flags = SF_STR_ALLOW_START ;
|
||||
|
||||
/*
|
||||
** By default, add the peak chunk to floating point files. Default behaviour
|
||||
** can be switched off using sf_command (SFC_SET_PEAK_CHUNK, SF_FALSE).
|
||||
*/
|
||||
if (psf->file.mode == SFM_WRITE && (subformat == SF_FORMAT_FLOAT || subformat == SF_FORMAT_DOUBLE))
|
||||
{ if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
psf->peak_info->peak_loc = SF_PEAK_START ;
|
||||
} ;
|
||||
|
||||
if ((error = caf_write_header (psf, SF_FALSE)) != 0)
|
||||
return error ;
|
||||
|
||||
psf->write_header = caf_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = caf_close ;
|
||||
psf->command = caf_command ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
error = ulaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
error = alaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
/* Lite remove start */
|
||||
case SF_FORMAT_FLOAT :
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
/* Lite remove end */
|
||||
|
||||
default :
|
||||
return SFE_UNSUPPORTED_ENCODING ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* caf_open */
|
||||
|
||||
static int
|
||||
caf_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
caf_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_close */
|
||||
|
||||
static int
|
||||
caf_command (SF_PRIVATE * psf, int command, void * UNUSED (data), int UNUSED (datasize))
|
||||
{ CAF_PRIVATE *pcaf ;
|
||||
|
||||
if ((pcaf = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
switch (command)
|
||||
{ case SFC_SET_CHANNEL_MAP_INFO :
|
||||
pcaf->chanmap_tag = aiff_caf_find_channel_layout_tag (psf->channel_map, psf->sf.channels) ;
|
||||
return (pcaf->chanmap_tag != 0) ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_command */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
decode_desc_chunk (SF_PRIVATE *psf, const DESC_CHUNK *desc)
|
||||
{ int format ;
|
||||
|
||||
psf->sf.channels = desc->channels_per_frame ;
|
||||
|
||||
format = SF_FORMAT_CAF | (psf->endian == SF_ENDIAN_LITTLE ? SF_ENDIAN_LITTLE : 0) ;
|
||||
|
||||
if (desc->fmt_id == lpcm_MARKER && desc->fmt_flags & 1)
|
||||
{ /* Floating point data. */
|
||||
if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 4 ;
|
||||
return format | SF_FORMAT_FLOAT ;
|
||||
} ;
|
||||
if (desc->bits_per_chan == 64 && desc->pkt_bytes == 8 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 8 ;
|
||||
return format | SF_FORMAT_DOUBLE ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if ((desc->fmt_flags & 1) != 0)
|
||||
{ psf_log_printf (psf, "**** Ooops, 'desc' chunk suggests float data, but other info invalid.\n") ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (desc->fmt_id == lpcm_MARKER)
|
||||
{ /* Integer data. */
|
||||
if (desc->bits_per_chan == 32 && desc->pkt_bytes == 4 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 4 ;
|
||||
return format | SF_FORMAT_PCM_32 ;
|
||||
} ;
|
||||
if (desc->bits_per_chan == 24 && desc->pkt_bytes == 3 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 3 ;
|
||||
return format | SF_FORMAT_PCM_24 ;
|
||||
} ;
|
||||
if (desc->bits_per_chan == 16 && desc->pkt_bytes == 2 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 2 ;
|
||||
return format | SF_FORMAT_PCM_16 ;
|
||||
} ;
|
||||
if (desc->bits_per_chan == 8 && desc->pkt_bytes == 1 * desc->channels_per_frame)
|
||||
{ psf->bytewidth = 1 ;
|
||||
return format | SF_FORMAT_PCM_S8 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (desc->fmt_id == alaw_MARKER && desc->bits_per_chan == 8)
|
||||
{ psf->bytewidth = 1 ;
|
||||
return format | SF_FORMAT_ALAW ;
|
||||
} ;
|
||||
|
||||
if (desc->fmt_id == ulaw_MARKER && desc->bits_per_chan == 8)
|
||||
{ psf->bytewidth = 1 ;
|
||||
return format | SF_FORMAT_ULAW ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* decode_desc_chunk */
|
||||
|
||||
static int
|
||||
caf_read_header (SF_PRIVATE *psf)
|
||||
{ DESC_CHUNK desc ;
|
||||
sf_count_t chunk_size ;
|
||||
double srate ;
|
||||
short version, flags ;
|
||||
int marker, k, have_data = 0, error ;
|
||||
|
||||
memset (&desc, 0, sizeof (desc)) ;
|
||||
|
||||
/* Set position to start of file to begin reading header. */
|
||||
psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ;
|
||||
psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ;
|
||||
if (marker != caff_MARKER)
|
||||
return SFE_CAF_NOT_CAF ;
|
||||
|
||||
psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ;
|
||||
srate = double64_be_read (psf->u.ucbuf) ;
|
||||
snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ;
|
||||
psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ;
|
||||
if (marker != desc_MARKER)
|
||||
return SFE_CAF_NO_DESC ;
|
||||
|
||||
if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK))
|
||||
{ psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
psf->sf.samplerate = lrint (srate) ;
|
||||
|
||||
psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames,
|
||||
&desc.channels_per_frame, &desc.bits_per_chan) ;
|
||||
psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n"
|
||||
" Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n",
|
||||
desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
|
||||
|
||||
if (desc.channels_per_frame > SF_MAX_CHANNELS)
|
||||
{ psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK))
|
||||
psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ;
|
||||
|
||||
psf->sf.channels = desc.channels_per_frame ;
|
||||
|
||||
while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker))
|
||||
{ psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ;
|
||||
|
||||
switch (marker)
|
||||
{ case peak_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels))
|
||||
{ psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
|
||||
return SFE_CAF_BAD_PEAK ;
|
||||
} ;
|
||||
|
||||
if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
/* read in rest of PEAK chunk. */
|
||||
psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ;
|
||||
psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ;
|
||||
|
||||
psf_log_printf (psf, " Ch Position Value\n") ;
|
||||
for (k = 0 ; k < psf->sf.channels ; k++)
|
||||
{ sf_count_t position ;
|
||||
float value ;
|
||||
|
||||
psf_binheader_readf (psf, "Ef8", &value, &position) ;
|
||||
psf->peak_info->peaks [k].value = value ;
|
||||
psf->peak_info->peaks [k].position = position ;
|
||||
|
||||
snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ;
|
||||
psf_log_printf (psf, psf->u.cbuf) ;
|
||||
} ;
|
||||
|
||||
psf->peak_info->peak_loc = SF_PEAK_START ;
|
||||
break ;
|
||||
|
||||
case chan_MARKER :
|
||||
if (chunk_size < 12)
|
||||
{ psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
break ;
|
||||
}
|
||||
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
|
||||
if ((error = caf_read_chanmap (psf, chunk_size)))
|
||||
return error ;
|
||||
break ;
|
||||
|
||||
case free_MARKER :
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
break ;
|
||||
|
||||
case data_MARKER :
|
||||
if (psf->filelength > 0 && chunk_size + psf->headindex != psf->filelength)
|
||||
psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, chunk_size + 4) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "E4", &k) ;
|
||||
psf_log_printf (psf, " edit : %u\n", k) ;
|
||||
have_data = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ;
|
||||
psf_binheader_readf (psf, "j", (int) chunk_size) ;
|
||||
break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (have_data == 0)
|
||||
{ psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "End\n") ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
|
||||
|
||||
if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0)
|
||||
return SFE_UNSUPPORTED_ENCODING ;
|
||||
|
||||
if (psf->bytewidth > 0)
|
||||
psf->sf.frames = psf->datalength / psf->bytewidth ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_read_header */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
caf_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ CAF_PRIVATE *pcaf ;
|
||||
DESC_CHUNK desc ;
|
||||
sf_count_t current, free_len ;
|
||||
int subformat ;
|
||||
|
||||
if ((pcaf = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
memset (&desc, 0, sizeof (desc)) ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
if (psf->bytewidth > 0)
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
/* 'caff' marker, version and flags. */
|
||||
psf_binheader_writef (psf, "Em22", caff_MARKER, 1, 0) ;
|
||||
|
||||
/* 'desc' marker and chunk size. */
|
||||
psf_binheader_writef (psf, "Em8", desc_MARKER, (sf_count_t) (sizeof (DESC_CHUNK))) ;
|
||||
|
||||
double64_be_write (1.0 * psf->sf.samplerate, psf->u.ucbuf) ;
|
||||
psf_binheader_writef (psf, "b", psf->u.ucbuf, make_size_t (8)) ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
|
||||
if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_LITTLE || psf->endian == SF_ENDIAN_CPU))
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_LITTLE)
|
||||
desc.fmt_flags = 2 ;
|
||||
else
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
/* initial section (same for all, it appears) */
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
psf->bytewidth = 1 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 8 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
psf->bytewidth = 2 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 16 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_24 :
|
||||
psf->bytewidth = 3 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 24 ;
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_32 :
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
psf->bytewidth = 4 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 32 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
desc.fmt_flags |= 1 ;
|
||||
psf->bytewidth = 4 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 32 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
desc.fmt_id = lpcm_MARKER ;
|
||||
desc.fmt_flags |= 1 ;
|
||||
psf->bytewidth = 8 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 64 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
desc.fmt_id = alaw_MARKER ;
|
||||
psf->bytewidth = 1 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 8 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
desc.fmt_id = ulaw_MARKER ;
|
||||
psf->bytewidth = 1 ;
|
||||
desc.pkt_bytes = psf->bytewidth * psf->sf.channels ;
|
||||
desc.pkt_frames = 1 ;
|
||||
desc.channels_per_frame = psf->sf.channels ;
|
||||
desc.bits_per_chan = 8 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
psf_binheader_writef (psf, "mE44444", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ;
|
||||
|
||||
#if 0
|
||||
if (psf->str_flags & SF_STR_LOCATE_START)
|
||||
caf_write_strings (psf, SF_STR_LOCATE_START) ;
|
||||
#endif
|
||||
|
||||
if (psf->peak_info != NULL)
|
||||
{ int k ;
|
||||
psf_binheader_writef (psf, "Em84", peak_MARKER, (sf_count_t) CAF_PEAK_CHUNK_SIZE (psf->sf.channels), psf->peak_info->edit_number) ;
|
||||
for (k = 0 ; k < psf->sf.channels ; k++)
|
||||
psf_binheader_writef (psf, "Ef8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
|
||||
} ;
|
||||
|
||||
if (psf->channel_map && pcaf->chanmap_tag)
|
||||
psf_binheader_writef (psf, "Em8444", chan_MARKER, (sf_count_t) 12, pcaf->chanmap_tag, 0, 0) ;
|
||||
|
||||
/* Add free chunk so that the actual audio data starts at a multiple 0x1000. */
|
||||
free_len = 0x1000 - psf->headindex - 16 - 12 ;
|
||||
while (free_len < 0)
|
||||
free_len += 0x1000 ;
|
||||
psf_binheader_writef (psf, "Em8z", free_MARKER, free_len, (int) free_len) ;
|
||||
|
||||
psf_binheader_writef (psf, "Em84", data_MARKER, psf->datalength + 4, 0) ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
if (current < psf->dataoffset)
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
else if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* caf_write_header */
|
||||
|
||||
static int
|
||||
caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size)
|
||||
{ const AIFF_CAF_CHANNEL_MAP * map_info ;
|
||||
unsigned channel_bitmap, channel_decriptions, bytesread ;
|
||||
int layout_tag ;
|
||||
|
||||
bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ;
|
||||
|
||||
map_info = aiff_caf_of_channel_layout_tag (layout_tag) ;
|
||||
|
||||
psf_log_printf (psf, " Tag : %x\n", layout_tag) ;
|
||||
if (map_info)
|
||||
psf_log_printf (psf, " Layout : %s\n", map_info->name) ;
|
||||
|
||||
if (bytesread < chunk_size)
|
||||
psf_binheader_readf (psf, "j", chunk_size - bytesread) ;
|
||||
|
||||
if (map_info->channel_map != NULL)
|
||||
{ size_t chanmap_size = psf->sf.channels * sizeof (psf->channel_map [0]) ;
|
||||
|
||||
free (psf->channel_map) ;
|
||||
|
||||
if ((psf->channel_map = malloc (chanmap_size)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* caf_read_chanmap */
|
||||
|
||||
262
project/jni/sndfile/src/chanmap.c
Normal file
262
project/jni/sndfile/src/chanmap.c
Normal file
@@ -0,0 +1,262 @@
|
||||
/*
|
||||
** Copyright (C) 2009-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Mostly from "Apple Core Audio Format Specification 1.0":
|
||||
**
|
||||
** http://developer.apple.com/documentation/MusicAudio/Reference/CAFSpec/CAFSpec.pdf
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
#include "chanmap.h"
|
||||
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP zero_chan [] =
|
||||
{ { (0 << 16) | 0, NULL, "Use channel descriptions." },
|
||||
{ (1 << 16) | 0, NULL, "Use channel bitmap." }
|
||||
} ; /* zero_chan */
|
||||
|
||||
|
||||
static const int one_chan_mono [1] = { SF_CHANNEL_MAP_MONO } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP one_chan [] =
|
||||
{ { (100 << 16) | 1, one_chan_mono, "mono" }
|
||||
} ; /* one_chan */
|
||||
|
||||
|
||||
static const int two_channel_stereo [2] = { SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP two_chan [] =
|
||||
{ { (101 << 16) | 2, two_channel_stereo, "stereo (L, R)" },
|
||||
{ (102 << 16) | 2, two_channel_stereo, "stereo headphones (L, R)" },
|
||||
#if 0
|
||||
{ (103 << 16) | 2, NULL, "matrix stereo (Lt, Rt)" },
|
||||
{ (104 << 16) | 2, NULL, "2 channels (mid, side)" },
|
||||
{ (105 << 16) | 2, NULL, "coincident mic pair" },
|
||||
{ (106 << 16) | 2, NULL, "binaural stereo (L, R)"
|
||||
}
|
||||
#endif
|
||||
} ; /* two_chan */
|
||||
|
||||
|
||||
static const int three_channel_mpeg_30a [3] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER } ;
|
||||
static const int three_channel_mpeg_30b [3] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT } ;
|
||||
static const int three_channel_itu_21 [3] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int three_channel_dvd_4 [3] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP three_chan [] =
|
||||
{ { (113 << 16) | 3, three_channel_mpeg_30a, "MPEG 3 0 A (L, R, C)" },
|
||||
{ (114 << 16) | 3, three_channel_mpeg_30b, "MPEG 3 0 B (C, L, R)" },
|
||||
{ (131 << 16) | 3, three_channel_itu_21, "ITU 2.1 (L, R, Cs)" },
|
||||
{ (133 << 16) | 3, three_channel_dvd_4, "DVD 4 (L, R, LFE)" }
|
||||
} ; /* three_chan */
|
||||
|
||||
|
||||
static const int four_channel_ambisonc_b [4] =
|
||||
{ SF_CHANNEL_MAP_AMBISONIC_B_W, SF_CHANNEL_MAP_AMBISONIC_B_X, SF_CHANNEL_MAP_AMBISONIC_B_Y, SF_CHANNEL_MAP_AMBISONIC_B_Z } ;
|
||||
static const int four_channel_quad [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int four_channel_mpeg_40a [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int four_channel_mpeg_40b [4] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int four_channel_itu_23 [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int four_channel_dvd_5 [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int four_channel_dvd_10 [4] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP four_chan [] =
|
||||
{ { (107 << 16) | 4, four_channel_ambisonc_b, "ambisonic B (W, X, Y, Z)" },
|
||||
{ (108 << 16) | 4, four_channel_quad, "quad (Lfront, Rfront, Lrear, Rrear)" },
|
||||
{ (115 << 16) | 4, four_channel_mpeg_40a, "MPEG 4.0 A (L, R, C, Cs)" },
|
||||
{ (116 << 16) | 4, four_channel_mpeg_40b, "MPEG 4.0 B (C, L, R, Cs)" },
|
||||
{ (132 << 16) | 4, four_channel_itu_23, "ITU 2.3 (L, R, Ls, Rs)" },
|
||||
{ (134 << 16) | 4, four_channel_dvd_5, "DVD 5 (L, R, LFE, Cs)" },
|
||||
{ (136 << 16) | 4, four_channel_dvd_10, "DVD 10 (L, R, C, LFE)" }
|
||||
} ; /* four_chan */
|
||||
|
||||
|
||||
static const int five_channel_pentagonal [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER } ;
|
||||
static const int five_channel_mpeg_50_a [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_mpeg_50_b [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER } ;
|
||||
static const int five_channel_mpeg_50_c [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_mpeg_50_d [5] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_dvd_6 [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int five_channel_dvd_11 [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int five_channel_dvd_18 [5] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP five_chan [] =
|
||||
{ { (109 << 16) | 5, five_channel_pentagonal, "pentagonal (L, R, Lrear, Rrear, C)" },
|
||||
{ (117 << 16) | 5, five_channel_mpeg_50_a, "MPEG 5.0 A (L, R, C, Ls, Rs)" },
|
||||
{ (118 << 16) | 5, five_channel_mpeg_50_b, "MPEG 5.0 B (L, R, Ls, Rs, C)" },
|
||||
{ (119 << 16) | 5, five_channel_mpeg_50_c, "MPEG 5.0 C (L, C, R, Ls, Rs,)" },
|
||||
{ (120 << 16) | 5, five_channel_mpeg_50_d, "MPEG 5.0 D (C, L, R, Ls, Rs)" },
|
||||
{ (135 << 16) | 5, five_channel_dvd_6, "DVD 6 (L, R, LFE, Ls, Rs)" },
|
||||
{ (137 << 16) | 5, five_channel_dvd_11, "DVD 11 (L, R, C, LFE, Cs)" },
|
||||
{ (138 << 16) | 5, five_channel_dvd_18, "DVD 18 (L, R, Ls, Rs, LFE)" }
|
||||
} ; /* five_chan */
|
||||
|
||||
|
||||
static const int six_channel_mpeg_51_a [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT } ;
|
||||
static const int six_channel_mpeg_51_b [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE } ;
|
||||
static const int six_channel_mpeg_51_c [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
static const int six_channel_mpeg_51_d [6] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_LFE } ;
|
||||
static const int six_channel_audio_unit_60 [6] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int six_channel_aac_60 [6] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP six_chan [] =
|
||||
{ { (110 << 16) | 6, NULL, "hexagonal (L, R, Lr, Rr, C, Rear)" },
|
||||
{ (121 << 16) | 6, six_channel_mpeg_51_a, "MPEG 5.1 A (L, R, C, LFE, Ls, Rs)" },
|
||||
{ (122 << 16) | 6, six_channel_mpeg_51_b, "MPEG 5.1 B (L, R, Ls, Rs, C, LFE)" },
|
||||
{ (123 << 16) | 6, six_channel_mpeg_51_c, "MPEG 5.1 C (L, C, R, Ls, Rs, LFE)" },
|
||||
{ (124 << 16) | 6, six_channel_mpeg_51_d, "MPEG 5.1 D (C, L, R, Ls, Rs, LFE)" },
|
||||
{ (139 << 16) | 6, six_channel_audio_unit_60, "AudioUnit 6.0 (L, R, Ls, Rs, C, Cs)" },
|
||||
{ (141 << 16) | 6, six_channel_aac_60, "AAC 6.0 (C, L, R, Ls, Rs, Cs)" }
|
||||
} ; /* six_chan */
|
||||
|
||||
|
||||
static const int six_channel_mpeg_61a [7] =
|
||||
{ SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LFE, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER } ;
|
||||
static const int six_channel_aac_61 [7] =
|
||||
{ SF_CHANNEL_MAP_CENTER, SF_CHANNEL_MAP_LEFT, SF_CHANNEL_MAP_RIGHT, SF_CHANNEL_MAP_REAR_LEFT, SF_CHANNEL_MAP_REAR_RIGHT, SF_CHANNEL_MAP_REAR_CENTER, SF_CHANNEL_MAP_LFE } ;
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP seven_chan [] =
|
||||
{ { (125 << 16) | 7, six_channel_mpeg_61a, "MPEG 6.1 A (L, R, C, LFE, Ls, Rs, Cs)" },
|
||||
{ (140 << 16) | 7, NULL, "AudioUnit 7.0 (L, R, Ls, Rs, C, Rls, Rrs)" },
|
||||
{ (142 << 16) | 7, six_channel_aac_61, "AAC 6.1 (C, L, R, Ls, Rs, Cs, Lfe)" },
|
||||
{ (143 << 16) | 7, NULL, "AAC 7.0 (C, L, R, Ls, Rs, Rls, Rrs,)" }
|
||||
} ; /* seven_chan */
|
||||
|
||||
|
||||
static const AIFF_CAF_CHANNEL_MAP eight_chan [] =
|
||||
{ { (111 << 16) | 8, NULL,
|
||||
// front left, front right, rear left, rear right,
|
||||
// front center, rear center, side left, side right
|
||||
"octagonal (Lf, Rf, Lr, Rr, Cf, Cr, Ls, Rs)"
|
||||
},
|
||||
{ (112 << 16) | 8, NULL,
|
||||
// left, right, rear left, rear right
|
||||
// top left, top right, top rear left, top rear right
|
||||
"cube (L, R, Lrear, Rrear, Ltop, Rtop, Ltoprear, Rtoprear)"
|
||||
},
|
||||
{ (126 << 16) | 8, NULL, "MPEG 7.1 A (L, R, C, LFE, Ls, Rs, Lc, Rc)" },
|
||||
{ (127 << 16) | 8, NULL, "MPEG 7.1 B (C, Lc, Rc, L, R, Ls, Rs, LFE)" },
|
||||
{ (128 << 16) | 8, NULL, "MPEG 7.1 C (L, R, C, LFE, Ls, R, Rls, Rrs)" },
|
||||
{ (129 << 16) | 8, NULL, "Emagic Default 7.1 (L, R, Ls, Rs, C, LFE, Lc, Rc)" },
|
||||
{ (130 << 16) | 8, NULL,
|
||||
// (ITU_5_1 plus a matrix encoded stereo mix)
|
||||
"SMPTE DTV (L, R, C, LFE, Ls, Rs, Lt, Rt)"
|
||||
},
|
||||
{ (144 << 16) | 8, NULL, "AAC octagonal (C, L, R, Ls, Rs, Rls, Rrs, Cs)" }
|
||||
} ; /* eight_chan */
|
||||
|
||||
|
||||
|
||||
#if 0
|
||||
|
||||
TMH_10_2_std = (145 << 16) | 16,
|
||||
// L R C Vhc Lsd Rsd Ls Rs Vhl Vhr Lw Rw Csd Cs LFE1 LFE2
|
||||
|
||||
TMH_10_2_full = (146 << 16) | 21,
|
||||
// TMH_10_2_std plus: Lc Rc HI VI Haptic
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct
|
||||
{ const AIFF_CAF_CHANNEL_MAP * map ;
|
||||
int len ;
|
||||
} MAP_MAP ;
|
||||
|
||||
static const MAP_MAP map [] =
|
||||
{ { zero_chan, ARRAY_LEN (zero_chan) },
|
||||
{ one_chan, ARRAY_LEN (one_chan) },
|
||||
{ two_chan, ARRAY_LEN (two_chan) },
|
||||
{ three_chan, ARRAY_LEN (three_chan) },
|
||||
{ four_chan, ARRAY_LEN (four_chan) },
|
||||
{ five_chan, ARRAY_LEN (five_chan) },
|
||||
{ six_chan, ARRAY_LEN (six_chan) },
|
||||
{ seven_chan, ARRAY_LEN (seven_chan) },
|
||||
{ eight_chan, ARRAY_LEN (eight_chan) }
|
||||
} ; /* map */
|
||||
|
||||
|
||||
int
|
||||
aiff_caf_find_channel_layout_tag (const int *chan_map, int channels)
|
||||
{ const AIFF_CAF_CHANNEL_MAP * curr_map ;
|
||||
unsigned k, len ;
|
||||
|
||||
if (channels < 1 || channels > ARRAY_LEN (map))
|
||||
return 0 ;
|
||||
|
||||
curr_map = map [channels].map ;
|
||||
len = map [channels].len ;
|
||||
|
||||
for (k = 0 ; k < len ; k++)
|
||||
if (curr_map [k].channel_map != NULL)
|
||||
if (memcmp (chan_map, curr_map [k].channel_map, channels * sizeof (chan_map [0])) == 0)
|
||||
return curr_map [k].channel_layout_tag ;
|
||||
|
||||
return 0 ;
|
||||
} /* aiff_caf_find_channel_layout_tag */
|
||||
|
||||
const AIFF_CAF_CHANNEL_MAP *
|
||||
aiff_caf_of_channel_layout_tag (int tag)
|
||||
{ const AIFF_CAF_CHANNEL_MAP * curr_map ;
|
||||
unsigned k, len ;
|
||||
int channels = tag & 0xffff ;
|
||||
|
||||
if (channels < 0 || channels > ARRAY_LEN (map))
|
||||
return NULL ;
|
||||
|
||||
curr_map = map [channels].map ;
|
||||
len = map [channels].len ;
|
||||
|
||||
for (k = 0 ; k < len ; k++)
|
||||
if (curr_map [k].channel_layout_tag == tag)
|
||||
return curr_map + k ;
|
||||
|
||||
return NULL ;
|
||||
} /* aiff_caf_of_channel_layout_tag */
|
||||
32
project/jni/sndfile/src/chanmap.h
Normal file
32
project/jni/sndfile/src/chanmap.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
** Copyright (C) 2009-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ /* The tag in the AIFF or CAF file. */
|
||||
int channel_layout_tag ;
|
||||
|
||||
/* The equivalent array of SF_CHANNEL_MAP_* entries. */
|
||||
const int * channel_map ;
|
||||
|
||||
const char * name ;
|
||||
} AIFF_CAF_CHANNEL_MAP ;
|
||||
|
||||
|
||||
int aiff_caf_find_channel_layout_tag (const int *chan_map, int channels) ;
|
||||
|
||||
const AIFF_CAF_CHANNEL_MAP * aiff_caf_of_channel_layout_tag (int tag) ;
|
||||
54
project/jni/sndfile/src/chunk.c
Normal file
54
project/jni/sndfile/src/chunk.c
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
void
|
||||
pchk4_store (PRIV_CHUNK4 * pchk, int marker, sf_count_t offset, sf_count_t len)
|
||||
{
|
||||
if (pchk->count >= ARRAY_LEN (pchk->l))
|
||||
return ;
|
||||
|
||||
pchk->l [pchk->count].chunk = marker ;
|
||||
pchk->l [pchk->count].offset = offset ;
|
||||
pchk->l [pchk->count].len = len ;
|
||||
|
||||
pchk->count ++ ;
|
||||
|
||||
return ;
|
||||
} /* pchk4_store */
|
||||
|
||||
int
|
||||
pchk4_find (PRIV_CHUNK4 * pchk, int marker)
|
||||
{ int k ;
|
||||
|
||||
for (k = 0 ; k < pchk->count ; k++)
|
||||
if (pchk->l [k].chunk == marker)
|
||||
return k ;
|
||||
|
||||
return -1 ;
|
||||
} /* pchk4_find */
|
||||
|
||||
376
project/jni/sndfile/src/command.c
Normal file
376
project/jni/sndfile/src/command.c
Normal file
@@ -0,0 +1,376 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
|
||||
static SF_FORMAT_INFO const simple_formats [] =
|
||||
{
|
||||
{ SF_FORMAT_AIFF | SF_FORMAT_PCM_16,
|
||||
"AIFF (Apple/SGI 16 bit PCM)", "aiff"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_AIFF | SF_FORMAT_FLOAT,
|
||||
"AIFF (Apple/SGI 32 bit float)", "aifc"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_AIFF | SF_FORMAT_PCM_S8,
|
||||
"AIFF (Apple/SGI 8 bit PCM)", "aiff"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_AU | SF_FORMAT_PCM_16,
|
||||
"AU (Sun/Next 16 bit PCM)", "au"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_AU | SF_FORMAT_ULAW,
|
||||
"AU (Sun/Next 8-bit u-law)", "au"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_CAF | SF_FORMAT_PCM_16,
|
||||
"CAF (Apple 16 bit PCM)", "caf"
|
||||
},
|
||||
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_FLAC | SF_FORMAT_PCM_16,
|
||||
"FLAC 16 bit", "flac"
|
||||
},
|
||||
#endif
|
||||
|
||||
{ SF_FORMAT_RAW | SF_FORMAT_VOX_ADPCM,
|
||||
"OKI Dialogic VOX ADPCM", "vox"
|
||||
},
|
||||
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_OGG | SF_FORMAT_VORBIS,
|
||||
"Ogg Vorbis (Xiph Foundation)", "oga"
|
||||
},
|
||||
#endif
|
||||
|
||||
{ SF_FORMAT_WAV | SF_FORMAT_PCM_16,
|
||||
"WAV (Microsoft 16 bit PCM)", "wav"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_WAV | SF_FORMAT_FLOAT,
|
||||
"WAV (Microsoft 32 bit float)", "wav"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_WAV | SF_FORMAT_IMA_ADPCM,
|
||||
"WAV (Microsoft 4 bit IMA ADPCM)", "wav"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_WAV | SF_FORMAT_MS_ADPCM,
|
||||
"WAV (Microsoft 4 bit MS ADPCM)", "wav"
|
||||
},
|
||||
|
||||
{ SF_FORMAT_WAV | SF_FORMAT_PCM_U8,
|
||||
"WAV (Microsoft 8 bit PCM)", "wav"
|
||||
},
|
||||
|
||||
} ; /* simple_formats */
|
||||
|
||||
int
|
||||
psf_get_format_simple_count (void)
|
||||
{ return (sizeof (simple_formats) / sizeof (SF_FORMAT_INFO)) ;
|
||||
} /* psf_get_format_simple_count */
|
||||
|
||||
int
|
||||
psf_get_format_simple (SF_FORMAT_INFO *data)
|
||||
{ int indx ;
|
||||
|
||||
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (simple_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
|
||||
return SFE_BAD_COMMAND_PARAM ;
|
||||
|
||||
indx = data->format ;
|
||||
memcpy (data, &(simple_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ;
|
||||
|
||||
return 0 ;
|
||||
} /* psf_get_format_simple */
|
||||
|
||||
/*============================================================================
|
||||
** Major format info.
|
||||
*/
|
||||
|
||||
static SF_FORMAT_INFO const major_formats [] =
|
||||
{
|
||||
{ SF_FORMAT_AIFF, "AIFF (Apple/SGI)", "aiff" },
|
||||
{ SF_FORMAT_AU, "AU (Sun/NeXT)", "au" },
|
||||
{ SF_FORMAT_AVR, "AVR (Audio Visual Research)", "avr" },
|
||||
{ SF_FORMAT_CAF, "CAF (Apple Core Audio File)", "caf" },
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_FLAC, "FLAC (FLAC Lossless Audio Codec)", "flac" },
|
||||
#endif
|
||||
{ SF_FORMAT_HTK, "HTK (HMM Tool Kit)", "htk" },
|
||||
{ SF_FORMAT_SVX, "IFF (Amiga IFF/SVX8/SV16)", "iff" },
|
||||
{ SF_FORMAT_MAT4, "MAT4 (GNU Octave 2.0 / Matlab 4.2)", "mat" },
|
||||
{ SF_FORMAT_MAT5, "MAT5 (GNU Octave 2.1 / Matlab 5.0)", "mat" },
|
||||
{ SF_FORMAT_MPC2K, "MPC (Akai MPC 2k)", "mpc" },
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_OGG, "OGG (OGG Container format)", "oga" },
|
||||
#endif
|
||||
{ SF_FORMAT_PAF, "PAF (Ensoniq PARIS)", "paf" },
|
||||
{ SF_FORMAT_PVF, "PVF (Portable Voice Format)", "pvf" },
|
||||
{ SF_FORMAT_RAW, "RAW (header-less)", "raw" },
|
||||
{ SF_FORMAT_RF64, "RF64 (RIFF 64)", "rf64" },
|
||||
{ SF_FORMAT_SD2, "SD2 (Sound Designer II)", "sd2" },
|
||||
{ SF_FORMAT_SDS, "SDS (Midi Sample Dump Standard)", "sds" },
|
||||
{ SF_FORMAT_IRCAM, "SF (Berkeley/IRCAM/CARL)", "sf" },
|
||||
{ SF_FORMAT_VOC, "VOC (Creative Labs)", "voc" },
|
||||
{ SF_FORMAT_W64, "W64 (SoundFoundry WAVE 64)", "w64" },
|
||||
{ SF_FORMAT_WAV, "WAV (Microsoft)", "wav" },
|
||||
{ SF_FORMAT_NIST, "WAV (NIST Sphere)", "wav" },
|
||||
{ SF_FORMAT_WAVEX, "WAVEX (Microsoft)", "wav" },
|
||||
{ SF_FORMAT_WVE, "WVE (Psion Series 3)", "wve" },
|
||||
{ SF_FORMAT_XI, "XI (FastTracker 2)", "xi" },
|
||||
|
||||
} ; /* major_formats */
|
||||
|
||||
int
|
||||
psf_get_format_major_count (void)
|
||||
{ return (sizeof (major_formats) / sizeof (SF_FORMAT_INFO)) ;
|
||||
} /* psf_get_format_major_count */
|
||||
|
||||
int
|
||||
psf_get_format_major (SF_FORMAT_INFO *data)
|
||||
{ int indx ;
|
||||
|
||||
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
|
||||
return SFE_BAD_COMMAND_PARAM ;
|
||||
|
||||
indx = data->format ;
|
||||
memcpy (data, &(major_formats [indx]), SIGNED_SIZEOF (SF_FORMAT_INFO)) ;
|
||||
|
||||
return 0 ;
|
||||
} /* psf_get_format_major */
|
||||
|
||||
/*============================================================================
|
||||
** Subtype format info.
|
||||
*/
|
||||
|
||||
static SF_FORMAT_INFO subtype_formats [] =
|
||||
{
|
||||
{ SF_FORMAT_PCM_S8, "Signed 8 bit PCM", NULL },
|
||||
{ SF_FORMAT_PCM_16, "Signed 16 bit PCM", NULL },
|
||||
{ SF_FORMAT_PCM_24, "Signed 24 bit PCM", NULL },
|
||||
{ SF_FORMAT_PCM_32, "Signed 32 bit PCM", NULL },
|
||||
|
||||
{ SF_FORMAT_PCM_U8, "Unsigned 8 bit PCM", NULL },
|
||||
|
||||
{ SF_FORMAT_FLOAT, "32 bit float", NULL },
|
||||
{ SF_FORMAT_DOUBLE, "64 bit float", NULL },
|
||||
|
||||
{ SF_FORMAT_ULAW, "U-Law", NULL },
|
||||
{ SF_FORMAT_ALAW, "A-Law", NULL },
|
||||
{ SF_FORMAT_IMA_ADPCM, "IMA ADPCM", NULL },
|
||||
{ SF_FORMAT_MS_ADPCM, "Microsoft ADPCM", NULL },
|
||||
|
||||
{ SF_FORMAT_GSM610, "GSM 6.10", NULL },
|
||||
|
||||
{ SF_FORMAT_G721_32, "32kbs G721 ADPCM", NULL },
|
||||
{ SF_FORMAT_G723_24, "24kbs G723 ADPCM", NULL },
|
||||
|
||||
{ SF_FORMAT_DWVW_12, "12 bit DWVW", NULL },
|
||||
{ SF_FORMAT_DWVW_16, "16 bit DWVW", NULL },
|
||||
{ SF_FORMAT_DWVW_24, "24 bit DWVW", NULL },
|
||||
{ SF_FORMAT_VOX_ADPCM, "VOX ADPCM", "vox" },
|
||||
|
||||
{ SF_FORMAT_DPCM_16, "16 bit DPCM", NULL },
|
||||
{ SF_FORMAT_DPCM_8, "8 bit DPCM", NULL },
|
||||
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
{ SF_FORMAT_VORBIS, "Vorbis", NULL },
|
||||
#endif
|
||||
} ; /* subtype_formats */
|
||||
|
||||
int
|
||||
psf_get_format_subtype_count (void)
|
||||
{ return (sizeof (subtype_formats) / sizeof (SF_FORMAT_INFO)) ;
|
||||
} /* psf_get_format_subtype_count */
|
||||
|
||||
int
|
||||
psf_get_format_subtype (SF_FORMAT_INFO *data)
|
||||
{ int indx ;
|
||||
|
||||
if (data->format < 0 || data->format >= (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)))
|
||||
return SFE_BAD_COMMAND_PARAM ;
|
||||
|
||||
indx = data->format ;
|
||||
memcpy (data, &(subtype_formats [indx]), sizeof (SF_FORMAT_INFO)) ;
|
||||
|
||||
return 0 ;
|
||||
} /* psf_get_format_subtype */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
int
|
||||
psf_get_format_info (SF_FORMAT_INFO *data)
|
||||
{ int k, format ;
|
||||
|
||||
if (SF_CONTAINER (data->format))
|
||||
{ format = SF_CONTAINER (data->format) ;
|
||||
|
||||
for (k = 0 ; k < (SIGNED_SIZEOF (major_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++)
|
||||
{ if (format == major_formats [k].format)
|
||||
{ memcpy (data, &(major_formats [k]), sizeof (SF_FORMAT_INFO)) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
} ;
|
||||
}
|
||||
else if (SF_CODEC (data->format))
|
||||
{ format = SF_CODEC (data->format) ;
|
||||
|
||||
for (k = 0 ; k < (SIGNED_SIZEOF (subtype_formats) / SIGNED_SIZEOF (SF_FORMAT_INFO)) ; k++)
|
||||
{ if (format == subtype_formats [k].format)
|
||||
{ memcpy (data, &(subtype_formats [k]), sizeof (SF_FORMAT_INFO)) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
memset (data, 0, sizeof (SF_FORMAT_INFO)) ;
|
||||
|
||||
return SFE_BAD_COMMAND_PARAM ;
|
||||
} /* psf_get_format_info */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
double
|
||||
psf_calc_signal_max (SF_PRIVATE *psf, int normalize)
|
||||
{ sf_count_t position ;
|
||||
double max_val, temp, *data ;
|
||||
int k, len, readcount, save_state ;
|
||||
|
||||
/* If the file is not seekable, there is nothing we can do. */
|
||||
if (! psf->sf.seekable)
|
||||
{ psf->error = SFE_NOT_SEEKABLE ;
|
||||
return 0.0 ;
|
||||
} ;
|
||||
|
||||
if (! psf->read_double)
|
||||
{ psf->error = SFE_UNIMPLEMENTED ;
|
||||
return 0.0 ;
|
||||
} ;
|
||||
|
||||
save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ;
|
||||
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ;
|
||||
|
||||
/* Brute force. Read the whole file and find the biggest sample. */
|
||||
/* Get current position in file */
|
||||
position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ;
|
||||
/* Go to start of file. */
|
||||
sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ;
|
||||
|
||||
data = psf->u.dbuf ;
|
||||
len = ARRAY_LEN (psf->u.dbuf) ;
|
||||
|
||||
for (readcount = 1, max_val = 0.0 ; readcount > 0 ; /* nothing */)
|
||||
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
{ temp = fabs (data [k]) ;
|
||||
max_val = temp > max_val ? temp : max_val ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/* Return to SNDFILE to original state. */
|
||||
sf_seek ((SNDFILE*) psf, position, SEEK_SET) ;
|
||||
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
|
||||
|
||||
return max_val ;
|
||||
} /* psf_calc_signal_max */
|
||||
|
||||
int
|
||||
psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize)
|
||||
{ sf_count_t position ;
|
||||
double temp, *data ;
|
||||
int k, len, readcount, save_state ;
|
||||
int chan ;
|
||||
|
||||
/* If the file is not seekable, there is nothing we can do. */
|
||||
if (! psf->sf.seekable)
|
||||
return (psf->error = SFE_NOT_SEEKABLE) ;
|
||||
|
||||
if (! psf->read_double)
|
||||
return (psf->error = SFE_UNIMPLEMENTED) ;
|
||||
|
||||
save_state = sf_command ((SNDFILE*) psf, SFC_GET_NORM_DOUBLE, NULL, 0) ;
|
||||
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, normalize) ;
|
||||
|
||||
memset (peaks, 0, sizeof (double) * psf->sf.channels) ;
|
||||
|
||||
/* Brute force. Read the whole file and find the biggest sample for each channel. */
|
||||
position = sf_seek ((SNDFILE*) psf, 0, SEEK_CUR) ; /* Get current position in file */
|
||||
sf_seek ((SNDFILE*) psf, 0, SEEK_SET) ; /* Go to start of file. */
|
||||
|
||||
len = ARRAY_LEN (psf->u.dbuf) ;
|
||||
|
||||
data = psf->u.dbuf ;
|
||||
|
||||
chan = 0 ;
|
||||
readcount = len ;
|
||||
while (readcount > 0)
|
||||
{ readcount = sf_read_double ((SNDFILE*) psf, data, len) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
{ temp = fabs (data [k]) ;
|
||||
peaks [chan] = temp > peaks [chan] ? temp : peaks [chan] ;
|
||||
chan = (chan + 1) % psf->sf.channels ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
sf_seek ((SNDFILE*) psf, position, SEEK_SET) ; /* Return to original position. */
|
||||
|
||||
sf_command ((SNDFILE*) psf, SFC_SET_NORM_DOUBLE, NULL, save_state) ;
|
||||
|
||||
return 0 ;
|
||||
} /* psf_calc_max_all_channels */
|
||||
|
||||
int
|
||||
psf_get_signal_max (SF_PRIVATE *psf, double *peak)
|
||||
{ int k ;
|
||||
|
||||
if (psf->peak_info == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
peak [0] = psf->peak_info->peaks [0].value ;
|
||||
|
||||
for (k = 1 ; k < psf->sf.channels ; k++)
|
||||
peak [0] = SF_MAX (peak [0], psf->peak_info->peaks [k].value) ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* psf_get_signal_max */
|
||||
|
||||
int
|
||||
psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks)
|
||||
{ int k ;
|
||||
|
||||
if (psf->peak_info == NULL)
|
||||
return SF_FALSE ;
|
||||
|
||||
for (k = 0 ; k < psf->sf.channels ; k++)
|
||||
peaks [k] = psf->peak_info->peaks [k].value ;
|
||||
|
||||
return SF_TRUE ;
|
||||
} /* psf_get_max_all_channels */
|
||||
|
||||
|
||||
1465
project/jni/sndfile/src/common.c
Normal file
1465
project/jni/sndfile/src/common.c
Normal file
File diff suppressed because it is too large
Load Diff
919
project/jni/sndfile/src/common.h
Normal file
919
project/jni/sndfile/src/common.h
Normal file
@@ -0,0 +1,919 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 SNDFILE_COMMON_H
|
||||
#define SNDFILE_COMMON_H
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#ifndef SNDFILE_H
|
||||
#include "sndfile.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
#error "This code is not designed to be compiled with a C++ compiler."
|
||||
#endif
|
||||
|
||||
#if (SIZEOF_LONG == 8)
|
||||
# define SF_PLATFORM_S64(x) x##l
|
||||
#elif (SIZEOF_LONG_LONG == 8)
|
||||
# define SF_PLATFORM_S64(x) x##ll
|
||||
#elif COMPILER_IS_GCC
|
||||
# define SF_PLATFORM_S64(x) x##ll
|
||||
#elif OS_IS_WIN32
|
||||
# define SF_PLATFORM_S64(x) x##I64
|
||||
#else
|
||||
# error "Don't know how to define a 64 bit integer constant."
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/*
|
||||
** Inspiration : http://sourcefrog.net/weblog/software/languages/C/unused.html
|
||||
*/
|
||||
#ifdef UNUSED
|
||||
#elif defined (__GNUC__)
|
||||
# define UNUSED(x) UNUSED_ ## x __attribute__ ((unused))
|
||||
#elif defined (__LCLINT__)
|
||||
# define UNUSED(x) /*@unused@*/ x
|
||||
#else
|
||||
# define UNUSED(x) x
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
# define WARN_UNUSED __attribute__ ((warn_unused_result))
|
||||
#else
|
||||
# define WARN_UNUSED
|
||||
#endif
|
||||
|
||||
#define SF_BUFFER_LEN (8192*2)
|
||||
#define SF_FILENAME_LEN (512)
|
||||
#define SF_SYSERR_LEN (256)
|
||||
#define SF_MAX_STRINGS (32)
|
||||
#define SF_STR_BUFFER_LEN (8192)
|
||||
#define SF_HEADER_LEN (4100 + SF_STR_BUFFER_LEN)
|
||||
|
||||
#define PSF_SEEK_ERROR ((sf_count_t) -1)
|
||||
|
||||
|
||||
#define BITWIDTH2BYTES(x) (((x) + 7) / 8)
|
||||
|
||||
/* For some reason sizeof returns an unsigned value which causes
|
||||
** a warning when that value is added or subtracted from a signed
|
||||
** value. Use SIGNED_SIZEOF instead.
|
||||
*/
|
||||
#define SIGNED_SIZEOF(x) ((int) sizeof (x))
|
||||
|
||||
#define ARRAY_LEN(x) ((int) (sizeof (x) / sizeof ((x) [0])))
|
||||
|
||||
#define NOT(x) (! (x))
|
||||
|
||||
#if (COMPILER_IS_GCC == 1)
|
||||
#define SF_MAX(x,y) ({ \
|
||||
typeof (x) sf_max_x1 = (x) ; \
|
||||
typeof (y) sf_max_y1 = (y) ; \
|
||||
(void) (&sf_max_x1 == &sf_max_y1) ; \
|
||||
sf_max_x1 > sf_max_y1 ? sf_max_x1 : sf_max_y1 ; })
|
||||
|
||||
#define SF_MIN(x,y) ({ \
|
||||
typeof (x) sf_min_x2 = (x) ; \
|
||||
typeof (y) sf_min_y2 = (y) ; \
|
||||
(void) (&sf_min_x2 == &sf_min_y2) ; \
|
||||
sf_min_x2 < sf_min_y2 ? sf_min_x2 : sf_min_y2 ; })
|
||||
#else
|
||||
#define SF_MAX(a,b) ((a) > (b) ? (a) : (b))
|
||||
#define SF_MIN(a,b) ((a) < (b) ? (a) : (b))
|
||||
#endif
|
||||
|
||||
|
||||
#define SF_MAX_CHANNELS 256
|
||||
|
||||
|
||||
/*
|
||||
* Macros for spliting the format file of SF_INFI into contrainer type,
|
||||
** codec type and endian-ness.
|
||||
*/
|
||||
#define SF_CONTAINER(x) ((x) & SF_FORMAT_TYPEMASK)
|
||||
#define SF_CODEC(x) ((x) & SF_FORMAT_SUBMASK)
|
||||
#define SF_ENDIAN(x) ((x) & SF_FORMAT_ENDMASK)
|
||||
|
||||
enum
|
||||
{ /* PEAK chunk location. */
|
||||
SF_PEAK_START = 42,
|
||||
SF_PEAK_END = 43,
|
||||
|
||||
/* PEAK chunk location. */
|
||||
SF_SCALE_MAX = 52,
|
||||
SF_SCALE_MIN = 53,
|
||||
|
||||
/* str_flags values. */
|
||||
SF_STR_ALLOW_START = 0x0100,
|
||||
SF_STR_ALLOW_END = 0x0200,
|
||||
|
||||
/* Location of strings. */
|
||||
SF_STR_LOCATE_START = 0x0400,
|
||||
SF_STR_LOCATE_END = 0x0800,
|
||||
|
||||
SFD_TYPEMASK = 0x0FFFFFFF
|
||||
} ;
|
||||
|
||||
#define SFM_MASK (SFM_READ | SFM_WRITE | SFM_RDWR)
|
||||
#define SFM_UNMASK (~SFM_MASK)
|
||||
|
||||
/*---------------------------------------------------------------------------------------
|
||||
** Formats that may be supported at some time in the future.
|
||||
** When support is finalised, these values move to src/sndfile.h.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /* Work in progress. */
|
||||
SF_FORMAT_SPEEX = 0x5000000,
|
||||
SF_FORMAT_OGGFLAC = 0x5000001,
|
||||
|
||||
/* Formats supported read only. */
|
||||
SF_FORMAT_TXW = 0x4030000, /* Yamaha TX16 sampler file */
|
||||
SF_FORMAT_DWD = 0x4040000, /* DiamondWare Digirized */
|
||||
|
||||
/* Following are detected but not supported. */
|
||||
SF_FORMAT_REX = 0x40A0000, /* Propellorheads Rex/Rcy */
|
||||
SF_FORMAT_REX2 = 0x40D0000, /* Propellorheads Rex2 */
|
||||
SF_FORMAT_KRZ = 0x40E0000, /* Kurzweil sampler file */
|
||||
SF_FORMAT_WMA = 0x4100000, /* Windows Media Audio. */
|
||||
SF_FORMAT_SHN = 0x4110000, /* Shorten. */
|
||||
|
||||
/* Unsupported encodings. */
|
||||
SF_FORMAT_SVX_FIB = 0x1020, /* SVX Fibonacci Delta encoding. */
|
||||
SF_FORMAT_SVX_EXP = 0x1021, /* SVX Exponential Delta encoding. */
|
||||
|
||||
SF_FORMAT_PCM_N = 0x1030
|
||||
} ;
|
||||
|
||||
/*---------------------------------------------------------------------------------------
|
||||
** PEAK_CHUNK - This chunk type is common to both AIFF and WAVE files although their
|
||||
** endian encodings are different.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ double value ; /* signed value of peak */
|
||||
sf_count_t position ; /* the sample frame for the peak */
|
||||
} PEAK_POS ;
|
||||
|
||||
typedef struct
|
||||
{ /* libsndfile internal : write a PEAK chunk at the start or end of the file? */
|
||||
int peak_loc ;
|
||||
|
||||
/* WAV/AIFF */
|
||||
unsigned int version ; /* version of the PEAK chunk */
|
||||
unsigned int timestamp ; /* secs since 1/1/1970 */
|
||||
|
||||
/* CAF */
|
||||
unsigned int edit_number ;
|
||||
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
/* the per channel peak info */
|
||||
PEAK_POS peaks [] ;
|
||||
#else
|
||||
/*
|
||||
** This is not ISO compliant C. It works on some compilers which
|
||||
** don't support the ISO standard flexible struct array which is
|
||||
** used above. If your compiler doesn't like this I suggest you find
|
||||
** youself a 1999 ISO C standards compilant compiler. GCC-3.X is
|
||||
** highly recommended.
|
||||
*/
|
||||
PEAK_POS peaks [0] ;
|
||||
#endif
|
||||
} PEAK_INFO ;
|
||||
|
||||
static inline PEAK_INFO *
|
||||
peak_info_calloc (int channels)
|
||||
{ return calloc (1, sizeof (PEAK_INFO) + channels * sizeof (PEAK_POS)) ;
|
||||
} /* peak_info_calloc */
|
||||
|
||||
typedef struct
|
||||
{ int type ;
|
||||
int flags ;
|
||||
char *str ;
|
||||
} STR_DATA ;
|
||||
|
||||
static inline size_t
|
||||
make_size_t (int x)
|
||||
{ return (size_t) x ;
|
||||
} /* size_t_of_int */
|
||||
|
||||
typedef SF_BROADCAST_INFO_VAR (16 * 1024) SF_BROADCAST_INFO_16K ;
|
||||
|
||||
#if SIZEOF_WCHAR_T == 2
|
||||
typedef wchar_t sfwchar_t ;
|
||||
#else
|
||||
typedef int16_t sfwchar_t ;
|
||||
#endif
|
||||
|
||||
/*
|
||||
** This version of isprint specifically ignores any locale info. Its used for
|
||||
** determining which characters can be printed in things like hexdumps.
|
||||
*/
|
||||
static inline int
|
||||
psf_isprint (int ch)
|
||||
{ return (ch >= ' ' && ch <= '~') ;
|
||||
} /* psf_isprint */
|
||||
|
||||
/*=======================================================================================
|
||||
** SF_PRIVATE stuct - a pointer to this struct is passed back to the caller of the
|
||||
** sf_open_XXXX functions. The caller however has no knowledge of the struct's
|
||||
** contents.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN] ;
|
||||
} path ;
|
||||
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN] ;
|
||||
} dir ;
|
||||
|
||||
union
|
||||
{ char c [SF_FILENAME_LEN / 4] ;
|
||||
sfwchar_t wc [SF_FILENAME_LEN / 4] ;
|
||||
} name ;
|
||||
|
||||
#if USE_WINDOWS_API
|
||||
/*
|
||||
** These fields can only be used in src/file_io.c.
|
||||
** They are basically the same as a windows file HANDLE.
|
||||
*/
|
||||
void *handle, *hsaved ;
|
||||
|
||||
int use_wchar ;
|
||||
#else
|
||||
/* These fields can only be used in src/file_io.c. */
|
||||
int filedes, savedes ;
|
||||
#endif
|
||||
|
||||
int do_not_close_descriptor ;
|
||||
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
|
||||
} PSF_FILE ;
|
||||
|
||||
|
||||
typedef struct sf_private_tag
|
||||
{
|
||||
/* Canary in a coal mine. */
|
||||
union
|
||||
{ /* Place a double here to encourage double alignment. */
|
||||
double d [2] ;
|
||||
char c [16] ;
|
||||
} canary ;
|
||||
|
||||
/* Force the compiler to double align the start of buffer. */
|
||||
union
|
||||
{ double dbuf [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
int64_t lbuf [SF_BUFFER_LEN / sizeof (int64_t)] ;
|
||||
#else
|
||||
long lbuf [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
#endif
|
||||
float fbuf [SF_BUFFER_LEN / sizeof (float)] ;
|
||||
int ibuf [SF_BUFFER_LEN / sizeof (int)] ;
|
||||
short sbuf [SF_BUFFER_LEN / sizeof (short)] ;
|
||||
char cbuf [SF_BUFFER_LEN / sizeof (char)] ;
|
||||
signed char scbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
|
||||
unsigned char ucbuf [SF_BUFFER_LEN / sizeof (signed char)] ;
|
||||
} u ;
|
||||
|
||||
|
||||
PSF_FILE file, rsrc ;
|
||||
|
||||
char syserr [SF_SYSERR_LEN] ;
|
||||
|
||||
/* logbuffer and logindex should only be changed within the logging functions
|
||||
** of common.c
|
||||
*/
|
||||
char logbuffer [SF_BUFFER_LEN] ;
|
||||
unsigned char header [SF_HEADER_LEN] ; /* Must be unsigned */
|
||||
int rwf_endian ; /* Header endian-ness flag. */
|
||||
|
||||
/* Storage and housekeeping data for adding/reading strings from
|
||||
** sound files.
|
||||
*/
|
||||
STR_DATA strings [SF_MAX_STRINGS] ;
|
||||
char str_storage [SF_STR_BUFFER_LEN] ;
|
||||
char *str_end ;
|
||||
int str_flags ;
|
||||
|
||||
/* Guard value. If this changes the buffers above have overflowed. */
|
||||
int Magick ;
|
||||
|
||||
unsigned unique_id ;
|
||||
|
||||
/* Index variables for maintaining logbuffer and header above. */
|
||||
int logindex ;
|
||||
int headindex, headend ;
|
||||
int has_text ;
|
||||
|
||||
int error ;
|
||||
|
||||
int endian ; /* File endianness : SF_ENDIAN_LITTLE or SF_ENDIAN_BIG. */
|
||||
int data_endswap ; /* Need to endswap data? */
|
||||
|
||||
/*
|
||||
** Maximum float value for calculating the multiplier for
|
||||
** float/double to short/int conversions.
|
||||
*/
|
||||
int float_int_mult ;
|
||||
float float_max ;
|
||||
|
||||
int scale_int_float ;
|
||||
|
||||
/* Vairables for handling pipes. */
|
||||
int is_pipe ; /* True if file is a pipe. */
|
||||
sf_count_t pipeoffset ; /* Number of bytes read from a pipe. */
|
||||
|
||||
/* True if clipping must be performed on float->int conversions. */
|
||||
int add_clipping ;
|
||||
|
||||
SF_INFO sf ;
|
||||
|
||||
int have_written ; /* Has a single write been done to the file? */
|
||||
PEAK_INFO *peak_info ;
|
||||
|
||||
/* Loop Info */
|
||||
SF_LOOP_INFO *loop_info ;
|
||||
SF_INSTRUMENT *instrument ;
|
||||
|
||||
/* Broadcast (EBU) Info */
|
||||
SF_BROADCAST_INFO_16K *broadcast_16k ;
|
||||
|
||||
/* Channel map data (if present) : an array of ints. */
|
||||
int *channel_map ;
|
||||
|
||||
sf_count_t filelength ; /* Overall length of (embedded) file. */
|
||||
sf_count_t fileoffset ; /* Offset in number of bytes from beginning of file. */
|
||||
|
||||
sf_count_t rsrclength ; /* Length of the resource fork (if it exists). */
|
||||
|
||||
sf_count_t dataoffset ; /* Offset in number of bytes from beginning of file. */
|
||||
sf_count_t datalength ; /* Length in bytes of the audio data. */
|
||||
sf_count_t dataend ; /* Offset to file tailer. */
|
||||
|
||||
int blockwidth ; /* Size in bytes of one set of interleaved samples. */
|
||||
int bytewidth ; /* Size in bytes of one sample (one channel). */
|
||||
|
||||
void *dither ;
|
||||
void *interleave ;
|
||||
|
||||
int last_op ; /* Last operation; either SFM_READ or SFM_WRITE */
|
||||
sf_count_t read_current ;
|
||||
sf_count_t write_current ;
|
||||
|
||||
void *container_data ; /* This is a pointer to dynamically allocated file
|
||||
** container format specific data.
|
||||
*/
|
||||
|
||||
void *codec_data ; /* This is a pointer to dynamically allocated file
|
||||
** codec format specific data.
|
||||
*/
|
||||
|
||||
SF_DITHER_INFO write_dither ;
|
||||
SF_DITHER_INFO read_dither ;
|
||||
|
||||
int norm_double ;
|
||||
int norm_float ;
|
||||
|
||||
int auto_header ;
|
||||
|
||||
int ieee_replace ;
|
||||
|
||||
/* A set of file specific function pointers */
|
||||
sf_count_t (*read_short) (struct sf_private_tag*, short *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_int) (struct sf_private_tag*, int *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_float) (struct sf_private_tag*, float *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_double) (struct sf_private_tag*, double *ptr, sf_count_t len) ;
|
||||
|
||||
sf_count_t (*write_short) (struct sf_private_tag*, const short *ptr, sf_count_t len) ;
|
||||
sf_count_t (*write_int) (struct sf_private_tag*, const int *ptr, sf_count_t len) ;
|
||||
sf_count_t (*write_float) (struct sf_private_tag*, const float *ptr, sf_count_t len) ;
|
||||
sf_count_t (*write_double) (struct sf_private_tag*, const double *ptr, sf_count_t len) ;
|
||||
|
||||
sf_count_t (*seek) (struct sf_private_tag*, int mode, sf_count_t samples_from_start) ;
|
||||
int (*write_header) (struct sf_private_tag*, int calc_length) ;
|
||||
int (*command) (struct sf_private_tag*, int command, void *data, int datasize) ;
|
||||
|
||||
/*
|
||||
** Separate close functions for the codec and the container.
|
||||
** The codec close function is always called first.
|
||||
*/
|
||||
int (*codec_close) (struct sf_private_tag*) ;
|
||||
int (*container_close) (struct sf_private_tag*) ;
|
||||
|
||||
char *format_desc ;
|
||||
|
||||
/* Virtual I/O functions. */
|
||||
int virtual_io ;
|
||||
SF_VIRTUAL_IO vio ;
|
||||
void *vio_user_data ;
|
||||
} SF_PRIVATE ;
|
||||
|
||||
|
||||
|
||||
enum
|
||||
{ SFE_NO_ERROR = SF_ERR_NO_ERROR,
|
||||
SFE_BAD_OPEN_FORMAT = SF_ERR_UNRECOGNISED_FORMAT,
|
||||
SFE_SYSTEM = SF_ERR_SYSTEM,
|
||||
SFE_MALFORMED_FILE = SF_ERR_MALFORMED_FILE,
|
||||
SFE_UNSUPPORTED_ENCODING = SF_ERR_UNSUPPORTED_ENCODING,
|
||||
|
||||
SFE_ZERO_MAJOR_FORMAT,
|
||||
SFE_ZERO_MINOR_FORMAT,
|
||||
SFE_BAD_FILE,
|
||||
SFE_BAD_FILE_READ,
|
||||
SFE_OPEN_FAILED,
|
||||
SFE_BAD_SNDFILE_PTR,
|
||||
SFE_BAD_SF_INFO_PTR,
|
||||
SFE_BAD_SF_INCOMPLETE,
|
||||
SFE_BAD_FILE_PTR,
|
||||
SFE_BAD_INT_PTR,
|
||||
SFE_BAD_STAT_SIZE,
|
||||
SFE_MALLOC_FAILED,
|
||||
SFE_UNIMPLEMENTED,
|
||||
SFE_BAD_READ_ALIGN,
|
||||
SFE_BAD_WRITE_ALIGN,
|
||||
SFE_UNKNOWN_FORMAT,
|
||||
SFE_NOT_READMODE,
|
||||
SFE_NOT_WRITEMODE,
|
||||
SFE_BAD_MODE_RW,
|
||||
SFE_BAD_SF_INFO,
|
||||
SFE_BAD_OFFSET,
|
||||
SFE_NO_EMBED_SUPPORT,
|
||||
SFE_NO_EMBEDDED_RDWR,
|
||||
SFE_NO_PIPE_WRITE,
|
||||
|
||||
SFE_INTERNAL,
|
||||
SFE_BAD_COMMAND_PARAM,
|
||||
SFE_BAD_ENDIAN,
|
||||
SFE_CHANNEL_COUNT_ZERO,
|
||||
SFE_CHANNEL_COUNT,
|
||||
|
||||
SFE_BAD_VIRTUAL_IO,
|
||||
|
||||
SFE_INTERLEAVE_MODE,
|
||||
SFE_INTERLEAVE_SEEK,
|
||||
SFE_INTERLEAVE_READ,
|
||||
|
||||
SFE_BAD_SEEK,
|
||||
SFE_NOT_SEEKABLE,
|
||||
SFE_AMBIGUOUS_SEEK,
|
||||
SFE_WRONG_SEEK,
|
||||
SFE_SEEK_FAILED,
|
||||
|
||||
SFE_BAD_OPEN_MODE,
|
||||
SFE_OPEN_PIPE_RDWR,
|
||||
SFE_RDWR_POSITION,
|
||||
SFE_RDWR_BAD_HEADER,
|
||||
SFE_CMD_HAS_DATA,
|
||||
SFE_BAD_BROADCAST_INFO_SIZE,
|
||||
SFE_BAD_BROADCAST_INFO_TOO_BIG,
|
||||
|
||||
SFE_STR_NO_SUPPORT,
|
||||
SFE_STR_NOT_WRITE,
|
||||
SFE_STR_MAX_DATA,
|
||||
SFE_STR_MAX_COUNT,
|
||||
SFE_STR_BAD_TYPE,
|
||||
SFE_STR_NO_ADD_END,
|
||||
SFE_STR_BAD_STRING,
|
||||
SFE_STR_WEIRD,
|
||||
|
||||
SFE_WAV_NO_RIFF,
|
||||
SFE_WAV_NO_WAVE,
|
||||
SFE_WAV_NO_FMT,
|
||||
SFE_WAV_BAD_FMT,
|
||||
SFE_WAV_FMT_SHORT,
|
||||
SFE_WAV_BAD_FACT,
|
||||
SFE_WAV_BAD_PEAK,
|
||||
SFE_WAV_PEAK_B4_FMT,
|
||||
SFE_WAV_BAD_FORMAT,
|
||||
SFE_WAV_BAD_BLOCKALIGN,
|
||||
SFE_WAV_NO_DATA,
|
||||
SFE_WAV_BAD_LIST,
|
||||
SFE_WAV_ADPCM_NOT4BIT,
|
||||
SFE_WAV_ADPCM_CHANNELS,
|
||||
SFE_WAV_GSM610_FORMAT,
|
||||
SFE_WAV_UNKNOWN_CHUNK,
|
||||
SFE_WAV_WVPK_DATA,
|
||||
|
||||
SFE_AIFF_NO_FORM,
|
||||
SFE_AIFF_AIFF_NO_FORM,
|
||||
SFE_AIFF_COMM_NO_FORM,
|
||||
SFE_AIFF_SSND_NO_COMM,
|
||||
SFE_AIFF_UNKNOWN_CHUNK,
|
||||
SFE_AIFF_COMM_CHUNK_SIZE,
|
||||
SFE_AIFF_BAD_COMM_CHUNK,
|
||||
SFE_AIFF_PEAK_B4_COMM,
|
||||
SFE_AIFF_BAD_PEAK,
|
||||
SFE_AIFF_NO_SSND,
|
||||
SFE_AIFF_NO_DATA,
|
||||
SFE_AIFF_RW_SSND_NOT_LAST,
|
||||
|
||||
SFE_AU_UNKNOWN_FORMAT,
|
||||
SFE_AU_NO_DOTSND,
|
||||
SFE_AU_EMBED_BAD_LEN,
|
||||
|
||||
SFE_RAW_READ_BAD_SPEC,
|
||||
SFE_RAW_BAD_BITWIDTH,
|
||||
SFE_RAW_BAD_FORMAT,
|
||||
|
||||
SFE_PAF_NO_MARKER,
|
||||
SFE_PAF_VERSION,
|
||||
SFE_PAF_UNKNOWN_FORMAT,
|
||||
SFE_PAF_SHORT_HEADER,
|
||||
SFE_PAF_BAD_CHANNELS,
|
||||
|
||||
SFE_SVX_NO_FORM,
|
||||
SFE_SVX_NO_BODY,
|
||||
SFE_SVX_NO_DATA,
|
||||
SFE_SVX_BAD_COMP,
|
||||
SFE_SVX_BAD_NAME_LENGTH,
|
||||
|
||||
SFE_NIST_BAD_HEADER,
|
||||
SFE_NIST_CRLF_CONVERISON,
|
||||
SFE_NIST_BAD_ENCODING,
|
||||
|
||||
SFE_VOC_NO_CREATIVE,
|
||||
SFE_VOC_BAD_FORMAT,
|
||||
SFE_VOC_BAD_VERSION,
|
||||
SFE_VOC_BAD_MARKER,
|
||||
SFE_VOC_BAD_SECTIONS,
|
||||
SFE_VOC_MULTI_SAMPLERATE,
|
||||
SFE_VOC_MULTI_SECTION,
|
||||
SFE_VOC_MULTI_PARAM,
|
||||
SFE_VOC_SECTION_COUNT,
|
||||
SFE_VOC_NO_PIPE,
|
||||
|
||||
SFE_IRCAM_NO_MARKER,
|
||||
SFE_IRCAM_BAD_CHANNELS,
|
||||
SFE_IRCAM_UNKNOWN_FORMAT,
|
||||
|
||||
SFE_W64_64_BIT,
|
||||
SFE_W64_NO_RIFF,
|
||||
SFE_W64_NO_WAVE,
|
||||
SFE_W64_NO_DATA,
|
||||
SFE_W64_ADPCM_NOT4BIT,
|
||||
SFE_W64_ADPCM_CHANNELS,
|
||||
SFE_W64_GSM610_FORMAT,
|
||||
|
||||
SFE_MAT4_BAD_NAME,
|
||||
SFE_MAT4_NO_SAMPLERATE,
|
||||
|
||||
SFE_MAT5_BAD_ENDIAN,
|
||||
SFE_MAT5_NO_BLOCK,
|
||||
SFE_MAT5_SAMPLE_RATE,
|
||||
|
||||
SFE_PVF_NO_PVF1,
|
||||
SFE_PVF_BAD_HEADER,
|
||||
SFE_PVF_BAD_BITWIDTH,
|
||||
|
||||
SFE_DWVW_BAD_BITWIDTH,
|
||||
SFE_G72X_NOT_MONO,
|
||||
|
||||
SFE_XI_BAD_HEADER,
|
||||
SFE_XI_EXCESS_SAMPLES,
|
||||
SFE_XI_NO_PIPE,
|
||||
|
||||
SFE_HTK_NO_PIPE,
|
||||
|
||||
SFE_SDS_NOT_SDS,
|
||||
SFE_SDS_BAD_BIT_WIDTH,
|
||||
|
||||
SFE_SD2_FD_DISALLOWED,
|
||||
SFE_SD2_BAD_DATA_OFFSET,
|
||||
SFE_SD2_BAD_MAP_OFFSET,
|
||||
SFE_SD2_BAD_DATA_LENGTH,
|
||||
SFE_SD2_BAD_MAP_LENGTH,
|
||||
SFE_SD2_BAD_RSRC,
|
||||
SFE_SD2_BAD_SAMPLE_SIZE,
|
||||
|
||||
SFE_FLAC_BAD_HEADER,
|
||||
SFE_FLAC_NEW_DECODER,
|
||||
SFE_FLAC_INIT_DECODER,
|
||||
SFE_FLAC_LOST_SYNC,
|
||||
SFE_FLAC_BAD_SAMPLE_RATE,
|
||||
SFE_FLAC_UNKOWN_ERROR,
|
||||
|
||||
SFE_WVE_NOT_WVE,
|
||||
SFE_WVE_NO_PIPE,
|
||||
|
||||
SFE_VORBIS_ENCODER_BUG,
|
||||
|
||||
SFE_RF64_NOT_RF64,
|
||||
|
||||
SFE_MAX_ERROR /* This must be last in list. */
|
||||
} ;
|
||||
|
||||
int subformat_to_bytewidth (int format) ;
|
||||
int s_bitwidth_to_subformat (int bits) ;
|
||||
int u_bitwidth_to_subformat (int bits) ;
|
||||
|
||||
/* Functions for reading and writing floats and doubles on processors
|
||||
** with non-IEEE floats/doubles.
|
||||
*/
|
||||
float float32_be_read (unsigned char *cptr) ;
|
||||
float float32_le_read (unsigned char *cptr) ;
|
||||
void float32_be_write (float in, unsigned char *out) ;
|
||||
void float32_le_write (float in, unsigned char *out) ;
|
||||
|
||||
double double64_be_read (unsigned char *cptr) ;
|
||||
double double64_le_read (unsigned char *cptr) ;
|
||||
void double64_be_write (double in, unsigned char *out) ;
|
||||
void double64_le_write (double in, unsigned char *out) ;
|
||||
|
||||
/* Functions for writing to the internal logging buffer. */
|
||||
|
||||
void psf_log_printf (SF_PRIVATE *psf, const char *format, ...) ;
|
||||
void psf_log_SF_INFO (SF_PRIVATE *psf) ;
|
||||
|
||||
int32_t psf_rand_int32 (void) ;
|
||||
|
||||
void append_snprintf (char * dest, size_t maxlen, const char * fmt, ...) ;
|
||||
void psf_strlcpy_crlf (char *dest, const char *src, size_t destmax, size_t srcmax) ;
|
||||
|
||||
/* Functions used when writing file headers. */
|
||||
|
||||
int psf_binheader_writef (SF_PRIVATE *psf, const char *format, ...) ;
|
||||
void psf_asciiheader_printf (SF_PRIVATE *psf, const char *format, ...) ;
|
||||
|
||||
/* Functions used when reading file headers. */
|
||||
|
||||
int psf_binheader_readf (SF_PRIVATE *psf, char const *format, ...) ;
|
||||
|
||||
/* Functions used in the write function for updating the peak chunk. */
|
||||
|
||||
void peak_update_short (SF_PRIVATE *psf, short *ptr, size_t items) ;
|
||||
void peak_update_int (SF_PRIVATE *psf, int *ptr, size_t items) ;
|
||||
void peak_update_double (SF_PRIVATE *psf, double *ptr, size_t items) ;
|
||||
|
||||
/* Functions defined in command.c. */
|
||||
|
||||
int psf_get_format_simple_count (void) ;
|
||||
int psf_get_format_simple (SF_FORMAT_INFO *data) ;
|
||||
|
||||
int psf_get_format_info (SF_FORMAT_INFO *data) ;
|
||||
|
||||
int psf_get_format_major_count (void) ;
|
||||
int psf_get_format_major (SF_FORMAT_INFO *data) ;
|
||||
|
||||
int psf_get_format_subtype_count (void) ;
|
||||
int psf_get_format_subtype (SF_FORMAT_INFO *data) ;
|
||||
|
||||
void psf_generate_format_desc (SF_PRIVATE *psf) ;
|
||||
|
||||
double psf_calc_signal_max (SF_PRIVATE *psf, int normalize) ;
|
||||
int psf_calc_max_all_channels (SF_PRIVATE *psf, double *peaks, int normalize) ;
|
||||
|
||||
int psf_get_signal_max (SF_PRIVATE *psf, double *peak) ;
|
||||
int psf_get_max_all_channels (SF_PRIVATE *psf, double *peaks) ;
|
||||
|
||||
/* Functions in strings.c. */
|
||||
|
||||
const char* psf_get_string (SF_PRIVATE *psf, int str_type) ;
|
||||
int psf_set_string (SF_PRIVATE *psf, int str_type, const char *str) ;
|
||||
int psf_store_string (SF_PRIVATE *psf, int str_type, const char *str) ;
|
||||
int psf_location_string_count (const SF_PRIVATE * psf, int location) ;
|
||||
|
||||
/* Default seek function. Use for PCM and float encoded data. */
|
||||
sf_count_t psf_default_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start) ;
|
||||
|
||||
int macos_guess_file_type (SF_PRIVATE *psf, const char *filename) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** File I/O functions which will allow access to large files (> 2 Gig) on
|
||||
** some 32 bit OSes. Implementation in file_io.c.
|
||||
*/
|
||||
|
||||
int psf_fopen (SF_PRIVATE *psf) ;
|
||||
int psf_set_stdio (SF_PRIVATE *psf) ;
|
||||
int psf_file_valid (SF_PRIVATE *psf) ;
|
||||
void psf_set_file (SF_PRIVATE *psf, int fd) ;
|
||||
void psf_init_files (SF_PRIVATE *psf) ;
|
||||
void psf_use_rsrc (SF_PRIVATE *psf, int on_off) ;
|
||||
|
||||
SNDFILE * psf_open_file (SF_PRIVATE *psf, SF_INFO *sfinfo) ;
|
||||
|
||||
sf_count_t psf_fseek (SF_PRIVATE *psf, sf_count_t offset, int whence) ;
|
||||
sf_count_t psf_fread (void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ;
|
||||
sf_count_t psf_fwrite (const void *ptr, sf_count_t bytes, sf_count_t count, SF_PRIVATE *psf) ;
|
||||
sf_count_t psf_fgets (char *buffer, sf_count_t bufsize, SF_PRIVATE *psf) ;
|
||||
sf_count_t psf_ftell (SF_PRIVATE *psf) ;
|
||||
sf_count_t psf_get_filelen (SF_PRIVATE *psf) ;
|
||||
|
||||
void psf_fsync (SF_PRIVATE *psf) ;
|
||||
|
||||
int psf_is_pipe (SF_PRIVATE *psf) ;
|
||||
|
||||
int psf_ftruncate (SF_PRIVATE *psf, sf_count_t len) ;
|
||||
int psf_fclose (SF_PRIVATE *psf) ;
|
||||
|
||||
/* Open and close the resource fork of a file. */
|
||||
int psf_open_rsrc (SF_PRIVATE *psf) ;
|
||||
int psf_close_rsrc (SF_PRIVATE *psf) ;
|
||||
|
||||
/*
|
||||
void psf_fclearerr (SF_PRIVATE *psf) ;
|
||||
int psf_ferror (SF_PRIVATE *psf) ;
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Functions for reading and writing different file formats.
|
||||
*/
|
||||
|
||||
int aiff_open (SF_PRIVATE *psf) ;
|
||||
int au_open (SF_PRIVATE *psf) ;
|
||||
int avr_open (SF_PRIVATE *psf) ;
|
||||
int htk_open (SF_PRIVATE *psf) ;
|
||||
int ircam_open (SF_PRIVATE *psf) ;
|
||||
int mat4_open (SF_PRIVATE *psf) ;
|
||||
int mat5_open (SF_PRIVATE *psf) ;
|
||||
int nist_open (SF_PRIVATE *psf) ;
|
||||
int paf_open (SF_PRIVATE *psf) ;
|
||||
int pvf_open (SF_PRIVATE *psf) ;
|
||||
int raw_open (SF_PRIVATE *psf) ;
|
||||
int sd2_open (SF_PRIVATE *psf) ;
|
||||
int sds_open (SF_PRIVATE *psf) ;
|
||||
int svx_open (SF_PRIVATE *psf) ;
|
||||
int voc_open (SF_PRIVATE *psf) ;
|
||||
int w64_open (SF_PRIVATE *psf) ;
|
||||
int wav_open (SF_PRIVATE *psf) ;
|
||||
int xi_open (SF_PRIVATE *psf) ;
|
||||
int flac_open (SF_PRIVATE *psf) ;
|
||||
int caf_open (SF_PRIVATE *psf) ;
|
||||
int mpc2k_open (SF_PRIVATE *psf) ;
|
||||
int rf64_open (SF_PRIVATE *psf) ;
|
||||
|
||||
/* In progress. Do not currently work. */
|
||||
|
||||
int ogg_vorbis_open (SF_PRIVATE *psf) ;
|
||||
int ogg_speex_open (SF_PRIVATE *psf) ;
|
||||
int ogg_pcm_open (SF_PRIVATE *psf) ;
|
||||
|
||||
|
||||
int mpeg_open (SF_PRIVATE *psf) ;
|
||||
int ogg_open (SF_PRIVATE *psf) ;
|
||||
int rx2_open (SF_PRIVATE *psf) ;
|
||||
int txw_open (SF_PRIVATE *psf) ;
|
||||
int wve_open (SF_PRIVATE *psf) ;
|
||||
int dwd_open (SF_PRIVATE *psf) ;
|
||||
|
||||
int macbinary3_open (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Init functions for a number of common data encodings.
|
||||
*/
|
||||
|
||||
int pcm_init (SF_PRIVATE *psf) ;
|
||||
int ulaw_init (SF_PRIVATE *psf) ;
|
||||
int alaw_init (SF_PRIVATE *psf) ;
|
||||
int float32_init (SF_PRIVATE *psf) ;
|
||||
int double64_init (SF_PRIVATE *psf) ;
|
||||
int dwvw_init (SF_PRIVATE *psf, int bitwidth) ;
|
||||
int gsm610_init (SF_PRIVATE *psf) ;
|
||||
int vox_adpcm_init (SF_PRIVATE *psf) ;
|
||||
int flac_init (SF_PRIVATE *psf) ;
|
||||
int g72x_init (SF_PRIVATE * psf) ;
|
||||
|
||||
int dither_init (SF_PRIVATE *psf, int mode) ;
|
||||
|
||||
int wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
|
||||
int wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
|
||||
|
||||
int aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
|
||||
|
||||
int interleave_init (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Chunk logging functions.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ struct
|
||||
{ int chunk ;
|
||||
sf_count_t offset ;
|
||||
sf_count_t len ;
|
||||
} l [100] ;
|
||||
|
||||
int count ;
|
||||
} PRIV_CHUNK4 ;
|
||||
|
||||
void pchk4_store (PRIV_CHUNK4 * pchk, int marker, sf_count_t offset, sf_count_t len) ;
|
||||
int pchk4_find (PRIV_CHUNK4 * pchk, int marker) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Functions that work like OpenBSD's strlcpy/strlcat to replace strncpy/strncat.
|
||||
**
|
||||
** See : http://www.gratisoft.us/todd/papers/strlcpy.html
|
||||
**
|
||||
** These functions are available on *BSD, but are not avaialble everywhere so we
|
||||
** implement them here.
|
||||
**
|
||||
** The argument order has been changed to that of strncpy/strncat to cause
|
||||
** compiler errors if code is carelessly converted from one to the other.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
psf_strlcat (char *dest, size_t n, const char *src)
|
||||
{ strncat (dest, src, n - strlen (dest) - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcat */
|
||||
|
||||
static inline void
|
||||
psf_strlcpy (char *dest, size_t n, const char *src)
|
||||
{ strncpy (dest, src, n - 1) ;
|
||||
dest [n - 1] = 0 ;
|
||||
} /* psf_strlcpy */
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Other helper functions.
|
||||
*/
|
||||
|
||||
void *psf_memset (void *s, int c, sf_count_t n) ;
|
||||
|
||||
SF_INSTRUMENT * psf_instrument_alloc (void) ;
|
||||
|
||||
void psf_sanitize_string (char * cptr, int len) ;
|
||||
|
||||
/* Generate the current date as a string. */
|
||||
void psf_get_date_str (char *str, int maxlen) ;
|
||||
|
||||
SF_BROADCAST_INFO_16K * broadcast_var_alloc (void) ;
|
||||
int broadcast_var_set (SF_PRIVATE *psf, const SF_BROADCAST_INFO * data, size_t datasize) ;
|
||||
int broadcast_var_get (SF_PRIVATE *psf, SF_BROADCAST_INFO * data, size_t datasize) ;
|
||||
|
||||
|
||||
typedef struct
|
||||
{ int channels ;
|
||||
int endianness ;
|
||||
} AUDIO_DETECT ;
|
||||
|
||||
int audio_detect (SF_PRIVATE * psf, AUDIO_DETECT *ad, const unsigned char * data, int datalen) ;
|
||||
int id3_skip (SF_PRIVATE * psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Helper/debug functions.
|
||||
*/
|
||||
|
||||
void psf_hexdump (const void *ptr, int len) ;
|
||||
|
||||
const char * str_of_major_format (int format) ;
|
||||
const char * str_of_minor_format (int format) ;
|
||||
const char * str_of_open_mode (int mode) ;
|
||||
const char * str_of_endianness (int end) ;
|
||||
|
||||
/*------------------------------------------------------------------------------------
|
||||
** Extra commands for sf_command(). Not for public use yet.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFC_TEST_AIFF_ADD_INST_CHUNK = 0x2000,
|
||||
SFC_TEST_WAV_ADD_INFO_CHUNK = 0x2010
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Maybe, one day, make these functions or something like them, public.
|
||||
**
|
||||
** Buffer to buffer dithering. Pointer in and out are allowed to point
|
||||
** to the same buffer for in-place dithering.
|
||||
*/
|
||||
|
||||
#if 0
|
||||
int sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int count) ;
|
||||
int sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int count) ;
|
||||
int sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int count) ;
|
||||
int sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int count) ;
|
||||
#endif
|
||||
|
||||
#endif /* SNDFILE_COMMON_H */
|
||||
|
||||
291
project/jni/sndfile/src/config.h
Normal file
291
project/jni/sndfile/src/config.h
Normal file
@@ -0,0 +1,291 @@
|
||||
/* src/config.h. Generated from config.h.in by configure. */
|
||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Set to 1 if the compile is GNU GCC. */
|
||||
#define COMPILER_IS_GCC 1
|
||||
|
||||
/* Target processor clips on negative float to int conversion. */
|
||||
#define CPU_CLIPS_NEGATIVE 0
|
||||
|
||||
/* Target processor clips on positive float to int conversion. */
|
||||
#define CPU_CLIPS_POSITIVE 0
|
||||
|
||||
/* Target processor is big endian. */
|
||||
#define CPU_IS_BIG_ENDIAN 0
|
||||
|
||||
/* Target processor is little endian. */
|
||||
#define CPU_IS_LITTLE_ENDIAN 1
|
||||
|
||||
/* Set to 1 to enable experimental code. */
|
||||
#define ENABLE_EXPERIMENTAL_CODE 0
|
||||
|
||||
/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
|
||||
/* #define HAVE_ALSA_ASOUNDLIB_H 1 */
|
||||
|
||||
/* Define to 1 if you have the <byteswap.h> header file. */
|
||||
#define HAVE_BYTESWAP_H 1
|
||||
|
||||
/* Define to 1 if you have the `calloc' function. */
|
||||
#define HAVE_CALLOC 1
|
||||
|
||||
/* Define to 1 if you have the `ceil' function. */
|
||||
#define HAVE_CEIL 1
|
||||
|
||||
/* Set to 1 if S_IRGRP is defined. */
|
||||
#define HAVE_DECL_S_IRGRP 1
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#define HAVE_DLFCN_H 1
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
#define HAVE_ENDIAN_H 1
|
||||
|
||||
/* Will be set to 1 if flac, ogg and vorbis are available. */
|
||||
/* #define HAVE_EXTERNAL_LIBS 1 */
|
||||
|
||||
/* Set to 1 if the compile supports the struct hack. */
|
||||
#define HAVE_FLEXIBLE_ARRAY 1
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#define HAVE_FLOOR 1
|
||||
|
||||
/* Define to 1 if you have the `fmod' function. */
|
||||
#define HAVE_FMOD 1
|
||||
|
||||
/* Define to 1 if you have the `free' function. */
|
||||
#define HAVE_FREE 1
|
||||
|
||||
/* Define to 1 if you have the `fstat' function. */
|
||||
#define HAVE_FSTAT 1
|
||||
|
||||
/* Define to 1 if you have the `fsync' function. */
|
||||
#define HAVE_FSYNC 1
|
||||
|
||||
/* Define to 1 if you have the `ftruncate' function. */
|
||||
#define HAVE_FTRUNCATE 1
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#define HAVE_GETPAGESIZE 1
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#define HAVE_GETTIMEOFDAY 1
|
||||
|
||||
/* Define to 1 if you have the `gmtime' function. */
|
||||
#define HAVE_GMTIME 1
|
||||
|
||||
/* Define to 1 if you have the `gmtime_r' function. */
|
||||
#define HAVE_GMTIME_R 1
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#define HAVE_INTTYPES_H 1
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#define HAVE_LIBM 1
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
/* #define HAVE_LOCALE_H 1 */
|
||||
|
||||
/* Define to 1 if you have the `localtime' function. */
|
||||
#define HAVE_LOCALTIME 1
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#define HAVE_LOCALTIME_R 1
|
||||
|
||||
/* Define if you have C99's lrint function. */
|
||||
#define HAVE_LRINT 1
|
||||
|
||||
/* Define if you have C99's lrintf function. */
|
||||
#define HAVE_LRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `lseek' function. */
|
||||
#define HAVE_LSEEK 1
|
||||
|
||||
/* Define to 1 if you have the `malloc' function. */
|
||||
#define HAVE_MALLOC 1
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#define HAVE_MEMORY_H 1
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#define HAVE_MMAP 1
|
||||
|
||||
/* Define to 1 if you have the `open' function. */
|
||||
#define HAVE_OPEN 1
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#define HAVE_PIPE 1
|
||||
|
||||
/* Define to 1 if you have the `pread' function. */
|
||||
#define HAVE_PREAD 1
|
||||
|
||||
/* Define to 1 if you have the `pwrite' function. */
|
||||
#define HAVE_PWRITE 1
|
||||
|
||||
/* Define to 1 if you have the `read' function. */
|
||||
#define HAVE_READ 1
|
||||
|
||||
/* Define to 1 if you have the `realloc' function. */
|
||||
#define HAVE_REALLOC 1
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
/* #define HAVE_SETLOCALE 1 */
|
||||
|
||||
/* Define to 1 if you have the <sndio.h> header file. */
|
||||
/* #undef HAVE_SNDIO_H */
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#define HAVE_SNPRINTF 1
|
||||
|
||||
/* Set to 1 if you have libsqlite3. */
|
||||
#define HAVE_SQLITE3 0
|
||||
|
||||
/* Define to 1 if the system has the type `ssize_t'. */
|
||||
#define HAVE_SSIZE_T 1
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#define HAVE_STDINT_H 1
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#define HAVE_STDLIB_H 1
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#define HAVE_STRINGS_H 1
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#define HAVE_STRING_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#define HAVE_SYS_STAT_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#define HAVE_SYS_TIME_H 1
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#define HAVE_SYS_TYPES_H 1
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#define HAVE_SYS_WAIT_H 1
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#define HAVE_UNISTD_H 1
|
||||
|
||||
/* Define to 1 if you have the `vsnprintf' function. */
|
||||
#define HAVE_VSNPRINTF 1
|
||||
|
||||
/* Define to 1 if you have the `waitpid' function. */
|
||||
#define HAVE_WAITPID 1
|
||||
|
||||
/* Define to 1 if you have the `write' function. */
|
||||
#define HAVE_WRITE 1
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#define LT_OBJDIR ".libs/"
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
/* #undef NO_MINUS_C_MINUS_O */
|
||||
|
||||
/* Set to 1 if compiling for MacOSX */
|
||||
#define OS_IS_MACOSX 0
|
||||
|
||||
/* Set to 1 if compiling for Win32 */
|
||||
#define OS_IS_WIN32 0
|
||||
|
||||
/* Name of package */
|
||||
#define PACKAGE "libsndfile"
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#define PACKAGE_BUGREPORT "sndfile@mega-nerd.com"
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#define PACKAGE_NAME "libsndfile"
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#define PACKAGE_STRING "libsndfile 1.0.25"
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#define PACKAGE_TARNAME "libsndfile"
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#define PACKAGE_URL "http://www.mega-nerd.com/libsndfile/"
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#define PACKAGE_VERSION "1.0.25"
|
||||
|
||||
/* Set to maximum allowed value of sf_count_t type. */
|
||||
#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||
|
||||
/* The size of `double', as computed by sizeof. */
|
||||
#define SIZEOF_DOUBLE 8
|
||||
|
||||
/* The size of `float', as computed by sizeof. */
|
||||
#define SIZEOF_FLOAT 4
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#define SIZEOF_INT 4
|
||||
|
||||
/* The size of `int64_t', as computed by sizeof. */
|
||||
#define SIZEOF_INT64_T 8
|
||||
|
||||
/* The size of `loff_t', as computed by sizeof. */
|
||||
/* #undef SIZEOF_LOFF_T */
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG 4
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#define SIZEOF_LONG_LONG 8
|
||||
|
||||
/* The size of `off64_t', as computed by sizeof. */
|
||||
#define SIZEOF_OFF64_T 8
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
#define SIZEOF_OFF_T 4
|
||||
|
||||
/* Set to sizeof (long) if unknown. */
|
||||
#define SIZEOF_SF_COUNT_T 8
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#define SIZEOF_SHORT 2
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#define SIZEOF_SIZE_T 4
|
||||
|
||||
/* The size of `ssize_t', as computed by sizeof. */
|
||||
#define SIZEOF_SSIZE_T 4
|
||||
|
||||
/* The size of `void*', as computed by sizeof. */
|
||||
#define SIZEOF_VOIDP 4
|
||||
|
||||
/* The size of `wchar_t', as computed by sizeof. */
|
||||
#define SIZEOF_WCHAR_T 4
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#define STDC_HEADERS 1
|
||||
|
||||
/* Set to long if unknown. */
|
||||
#define TYPEOF_SF_COUNT_T int64_t
|
||||
|
||||
/* Set to 1 to use the native windows API */
|
||||
#define USE_WINDOWS_API 0
|
||||
|
||||
/* Version number of package */
|
||||
#define VERSION "1.0.25"
|
||||
|
||||
/* Set to 1 if windows DLL is being built. */
|
||||
#define WIN32_TARGET_DLL 0
|
||||
|
||||
/* Target processor is big endian. */
|
||||
#define WORDS_BIGENDIAN 0
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
/* #undef _FILE_OFFSET_BITS */
|
||||
|
||||
/* Define to make fseeko etc. visible, on some hosts. */
|
||||
/* #undef _LARGEFILE_SOURCE */
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
/* #undef _LARGE_FILES */
|
||||
|
||||
/* Set to 1 to use C99 printf/snprintf in MinGW. */
|
||||
/* #undef __USE_MINGW_ANSI_STDIO */
|
||||
290
project/jni/sndfile/src/config.h.in
Normal file
290
project/jni/sndfile/src/config.h.in
Normal file
@@ -0,0 +1,290 @@
|
||||
/* src/config.h.in. Generated from configure.ac by autoheader. */
|
||||
|
||||
/* Set to 1 if the compile is GNU GCC. */
|
||||
#undef COMPILER_IS_GCC
|
||||
|
||||
/* Target processor clips on negative float to int conversion. */
|
||||
#undef CPU_CLIPS_NEGATIVE
|
||||
|
||||
/* Target processor clips on positive float to int conversion. */
|
||||
#undef CPU_CLIPS_POSITIVE
|
||||
|
||||
/* Target processor is big endian. */
|
||||
#undef CPU_IS_BIG_ENDIAN
|
||||
|
||||
/* Target processor is little endian. */
|
||||
#undef CPU_IS_LITTLE_ENDIAN
|
||||
|
||||
/* Set to 1 to enable experimental code. */
|
||||
#undef ENABLE_EXPERIMENTAL_CODE
|
||||
|
||||
/* Define to 1 if you have the <alsa/asoundlib.h> header file. */
|
||||
#undef HAVE_ALSA_ASOUNDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <byteswap.h> header file. */
|
||||
#undef HAVE_BYTESWAP_H
|
||||
|
||||
/* Define to 1 if you have the `calloc' function. */
|
||||
#undef HAVE_CALLOC
|
||||
|
||||
/* Define to 1 if you have the `ceil' function. */
|
||||
#undef HAVE_CEIL
|
||||
|
||||
/* Set to 1 if S_IRGRP is defined. */
|
||||
#undef HAVE_DECL_S_IRGRP
|
||||
|
||||
/* Define to 1 if you have the <dlfcn.h> header file. */
|
||||
#undef HAVE_DLFCN_H
|
||||
|
||||
/* Define to 1 if you have the <endian.h> header file. */
|
||||
#undef HAVE_ENDIAN_H
|
||||
|
||||
/* Will be set to 1 if flac, ogg and vorbis are available. */
|
||||
#undef HAVE_EXTERNAL_LIBS
|
||||
|
||||
/* Set to 1 if the compile supports the struct hack. */
|
||||
#undef HAVE_FLEXIBLE_ARRAY
|
||||
|
||||
/* Define to 1 if you have the `floor' function. */
|
||||
#undef HAVE_FLOOR
|
||||
|
||||
/* Define to 1 if you have the `fmod' function. */
|
||||
#undef HAVE_FMOD
|
||||
|
||||
/* Define to 1 if you have the `free' function. */
|
||||
#undef HAVE_FREE
|
||||
|
||||
/* Define to 1 if you have the `fstat' function. */
|
||||
#undef HAVE_FSTAT
|
||||
|
||||
/* Define to 1 if you have the `fsync' function. */
|
||||
#undef HAVE_FSYNC
|
||||
|
||||
/* Define to 1 if you have the `ftruncate' function. */
|
||||
#undef HAVE_FTRUNCATE
|
||||
|
||||
/* Define to 1 if you have the `getpagesize' function. */
|
||||
#undef HAVE_GETPAGESIZE
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
|
||||
/* Define to 1 if you have the `gmtime' function. */
|
||||
#undef HAVE_GMTIME
|
||||
|
||||
/* Define to 1 if you have the `gmtime_r' function. */
|
||||
#undef HAVE_GMTIME_R
|
||||
|
||||
/* Define to 1 if you have the <inttypes.h> header file. */
|
||||
#undef HAVE_INTTYPES_H
|
||||
|
||||
/* Define to 1 if you have the `m' library (-lm). */
|
||||
#undef HAVE_LIBM
|
||||
|
||||
/* Define to 1 if you have the <locale.h> header file. */
|
||||
#undef HAVE_LOCALE_H
|
||||
|
||||
/* Define to 1 if you have the `localtime' function. */
|
||||
#undef HAVE_LOCALTIME
|
||||
|
||||
/* Define to 1 if you have the `localtime_r' function. */
|
||||
#undef HAVE_LOCALTIME_R
|
||||
|
||||
/* Define if you have C99's lrint function. */
|
||||
#undef HAVE_LRINT
|
||||
|
||||
/* Define if you have C99's lrintf function. */
|
||||
#undef HAVE_LRINTF
|
||||
|
||||
/* Define to 1 if you have the `lseek' function. */
|
||||
#undef HAVE_LSEEK
|
||||
|
||||
/* Define to 1 if you have the `malloc' function. */
|
||||
#undef HAVE_MALLOC
|
||||
|
||||
/* Define to 1 if you have the <memory.h> header file. */
|
||||
#undef HAVE_MEMORY_H
|
||||
|
||||
/* Define to 1 if you have the `mmap' function. */
|
||||
#undef HAVE_MMAP
|
||||
|
||||
/* Define to 1 if you have the `open' function. */
|
||||
#undef HAVE_OPEN
|
||||
|
||||
/* Define to 1 if you have the `pipe' function. */
|
||||
#undef HAVE_PIPE
|
||||
|
||||
/* Define to 1 if you have the `pread' function. */
|
||||
#undef HAVE_PREAD
|
||||
|
||||
/* Define to 1 if you have the `pwrite' function. */
|
||||
#undef HAVE_PWRITE
|
||||
|
||||
/* Define to 1 if you have the `read' function. */
|
||||
#undef HAVE_READ
|
||||
|
||||
/* Define to 1 if you have the `realloc' function. */
|
||||
#undef HAVE_REALLOC
|
||||
|
||||
/* Define to 1 if you have the `setlocale' function. */
|
||||
#undef HAVE_SETLOCALE
|
||||
|
||||
/* Define to 1 if you have the <sndio.h> header file. */
|
||||
#undef HAVE_SNDIO_H
|
||||
|
||||
/* Define to 1 if you have the `snprintf' function. */
|
||||
#undef HAVE_SNPRINTF
|
||||
|
||||
/* Set to 1 if you have libsqlite3. */
|
||||
#undef HAVE_SQLITE3
|
||||
|
||||
/* Define to 1 if the system has the type `ssize_t'. */
|
||||
#undef HAVE_SSIZE_T
|
||||
|
||||
/* Define to 1 if you have the <stdint.h> header file. */
|
||||
#undef HAVE_STDINT_H
|
||||
|
||||
/* Define to 1 if you have the <stdlib.h> header file. */
|
||||
#undef HAVE_STDLIB_H
|
||||
|
||||
/* Define to 1 if you have the <strings.h> header file. */
|
||||
#undef HAVE_STRINGS_H
|
||||
|
||||
/* Define to 1 if you have the <string.h> header file. */
|
||||
#undef HAVE_STRING_H
|
||||
|
||||
/* Define to 1 if you have the <sys/stat.h> header file. */
|
||||
#undef HAVE_SYS_STAT_H
|
||||
|
||||
/* Define to 1 if you have the <sys/time.h> header file. */
|
||||
#undef HAVE_SYS_TIME_H
|
||||
|
||||
/* Define to 1 if you have the <sys/types.h> header file. */
|
||||
#undef HAVE_SYS_TYPES_H
|
||||
|
||||
/* Define to 1 if you have <sys/wait.h> that is POSIX.1 compatible. */
|
||||
#undef HAVE_SYS_WAIT_H
|
||||
|
||||
/* Define to 1 if you have the <unistd.h> header file. */
|
||||
#undef HAVE_UNISTD_H
|
||||
|
||||
/* Define to 1 if you have the `vsnprintf' function. */
|
||||
#undef HAVE_VSNPRINTF
|
||||
|
||||
/* Define to 1 if you have the `waitpid' function. */
|
||||
#undef HAVE_WAITPID
|
||||
|
||||
/* Define to 1 if you have the `write' function. */
|
||||
#undef HAVE_WRITE
|
||||
|
||||
/* Define to the sub-directory in which libtool stores uninstalled libraries.
|
||||
*/
|
||||
#undef LT_OBJDIR
|
||||
|
||||
/* Define to 1 if your C compiler doesn't accept -c and -o together. */
|
||||
#undef NO_MINUS_C_MINUS_O
|
||||
|
||||
/* Set to 1 if compiling for MacOSX */
|
||||
#undef OS_IS_MACOSX
|
||||
|
||||
/* Set to 1 if compiling for Win32 */
|
||||
#undef OS_IS_WIN32
|
||||
|
||||
/* Name of package */
|
||||
#undef PACKAGE
|
||||
|
||||
/* Define to the address where bug reports for this package should be sent. */
|
||||
#undef PACKAGE_BUGREPORT
|
||||
|
||||
/* Define to the full name of this package. */
|
||||
#undef PACKAGE_NAME
|
||||
|
||||
/* Define to the full name and version of this package. */
|
||||
#undef PACKAGE_STRING
|
||||
|
||||
/* Define to the one symbol short name of this package. */
|
||||
#undef PACKAGE_TARNAME
|
||||
|
||||
/* Define to the home page for this package. */
|
||||
#undef PACKAGE_URL
|
||||
|
||||
/* Define to the version of this package. */
|
||||
#undef PACKAGE_VERSION
|
||||
|
||||
/* Set to maximum allowed value of sf_count_t type. */
|
||||
#undef SF_COUNT_MAX
|
||||
|
||||
/* The size of `double', as computed by sizeof. */
|
||||
#undef SIZEOF_DOUBLE
|
||||
|
||||
/* The size of `float', as computed by sizeof. */
|
||||
#undef SIZEOF_FLOAT
|
||||
|
||||
/* The size of `int', as computed by sizeof. */
|
||||
#undef SIZEOF_INT
|
||||
|
||||
/* The size of `int64_t', as computed by sizeof. */
|
||||
#undef SIZEOF_INT64_T
|
||||
|
||||
/* The size of `loff_t', as computed by sizeof. */
|
||||
#undef SIZEOF_LOFF_T
|
||||
|
||||
/* The size of `long', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG
|
||||
|
||||
/* The size of `long long', as computed by sizeof. */
|
||||
#undef SIZEOF_LONG_LONG
|
||||
|
||||
/* The size of `off64_t', as computed by sizeof. */
|
||||
#undef SIZEOF_OFF64_T
|
||||
|
||||
/* The size of `off_t', as computed by sizeof. */
|
||||
#undef SIZEOF_OFF_T
|
||||
|
||||
/* Set to sizeof (long) if unknown. */
|
||||
#undef SIZEOF_SF_COUNT_T
|
||||
|
||||
/* The size of `short', as computed by sizeof. */
|
||||
#undef SIZEOF_SHORT
|
||||
|
||||
/* The size of `size_t', as computed by sizeof. */
|
||||
#undef SIZEOF_SIZE_T
|
||||
|
||||
/* The size of `ssize_t', as computed by sizeof. */
|
||||
#undef SIZEOF_SSIZE_T
|
||||
|
||||
/* The size of `void*', as computed by sizeof. */
|
||||
#undef SIZEOF_VOIDP
|
||||
|
||||
/* The size of `wchar_t', as computed by sizeof. */
|
||||
#undef SIZEOF_WCHAR_T
|
||||
|
||||
/* Define to 1 if you have the ANSI C header files. */
|
||||
#undef STDC_HEADERS
|
||||
|
||||
/* Set to long if unknown. */
|
||||
#undef TYPEOF_SF_COUNT_T
|
||||
|
||||
/* Set to 1 to use the native windows API */
|
||||
#undef USE_WINDOWS_API
|
||||
|
||||
/* Version number of package */
|
||||
#undef VERSION
|
||||
|
||||
/* Set to 1 if windows DLL is being built. */
|
||||
#undef WIN32_TARGET_DLL
|
||||
|
||||
/* Target processor is big endian. */
|
||||
#undef WORDS_BIGENDIAN
|
||||
|
||||
/* Number of bits in a file offset, on hosts where this is settable. */
|
||||
#undef _FILE_OFFSET_BITS
|
||||
|
||||
/* Define to make fseeko etc. visible, on some hosts. */
|
||||
#undef _LARGEFILE_SOURCE
|
||||
|
||||
/* Define for large files, on AIX-style hosts. */
|
||||
#undef _LARGE_FILES
|
||||
|
||||
/* Set to 1 to use C99 printf/snprintf in MinGW. */
|
||||
#undef __USE_MINGW_ANSI_STDIO
|
||||
534
project/jni/sndfile/src/dither.c
Normal file
534
project/jni/sndfile/src/dither.c
Normal file
@@ -0,0 +1,534 @@
|
||||
/*
|
||||
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*============================================================================
|
||||
** Rule number 1 is to only apply dither when going from a larger bitwidth
|
||||
** to a smaller bitwidth. This can happen on both read and write.
|
||||
**
|
||||
** Need to apply dither on all conversions marked X below.
|
||||
**
|
||||
** Dither on write:
|
||||
**
|
||||
** Input
|
||||
** | short int float double
|
||||
** --------+-----------------------------------------------
|
||||
** O 8 bit | X X X X
|
||||
** u 16 bit | none X X X
|
||||
** t 24 bit | none X X X
|
||||
** p 32 bit | none none X X
|
||||
** u float | none none none none
|
||||
** t double | none none none none
|
||||
**
|
||||
** Dither on read:
|
||||
**
|
||||
** Input
|
||||
** O | 8 bit 16 bit 24 bit 32 bit float double
|
||||
** u --------+-------------------------------------------------
|
||||
** t short | none none X X X X
|
||||
** p int | none none none X X X
|
||||
** u float | none none none none none none
|
||||
** t double | none none none none none none
|
||||
*/
|
||||
|
||||
#define SFE_DITHER_BAD_PTR 666
|
||||
#define SFE_DITHER_BAD_TYPE 667
|
||||
|
||||
typedef struct
|
||||
{ int read_short_dither_bits, read_int_dither_bits ;
|
||||
int write_short_dither_bits, write_int_dither_bits ;
|
||||
double read_float_dither_scale, read_double_dither_bits ;
|
||||
double write_float_dither_scale, write_double_dither_bits ;
|
||||
|
||||
sf_count_t (*read_short) (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_int) (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_float) (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_double) (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
sf_count_t (*write_short) (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
sf_count_t (*write_int) (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
sf_count_t (*write_float) (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
sf_count_t (*write_double) (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
double buffer [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
} DITHER_DATA ;
|
||||
|
||||
static sf_count_t dither_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
int
|
||||
dither_init (SF_PRIVATE *psf, int mode)
|
||||
{ DITHER_DATA *pdither ;
|
||||
|
||||
pdither = psf->dither ; /* This may be NULL. */
|
||||
|
||||
/* Turn off dither on read. */
|
||||
if (mode == SFM_READ && psf->read_dither.type == SFD_NO_DITHER)
|
||||
{ if (pdither == NULL)
|
||||
return 0 ; /* Dither is already off, so just return. */
|
||||
|
||||
if (pdither->read_short)
|
||||
psf->read_short = pdither->read_short ;
|
||||
if (pdither->read_int)
|
||||
psf->read_int = pdither->read_int ;
|
||||
if (pdither->read_float)
|
||||
psf->read_float = pdither->read_float ;
|
||||
if (pdither->read_double)
|
||||
psf->read_double = pdither->read_double ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
/* Turn off dither on write. */
|
||||
if (mode == SFM_WRITE && psf->write_dither.type == SFD_NO_DITHER)
|
||||
{ if (pdither == NULL)
|
||||
return 0 ; /* Dither is already off, so just return. */
|
||||
|
||||
if (pdither->write_short)
|
||||
psf->write_short = pdither->write_short ;
|
||||
if (pdither->write_int)
|
||||
psf->write_int = pdither->write_int ;
|
||||
if (pdither->write_float)
|
||||
psf->write_float = pdither->write_float ;
|
||||
if (pdither->write_double)
|
||||
psf->write_double = pdither->write_double ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
/* Turn on dither on read if asked. */
|
||||
if (mode == SFM_READ && psf->read_dither.type != 0)
|
||||
{ if (pdither == NULL)
|
||||
pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ;
|
||||
if (pdither == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_FLOAT :
|
||||
pdither->read_int = psf->read_int ;
|
||||
psf->read_int = dither_read_int ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_32 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
pdither->read_short = psf->read_short ;
|
||||
psf->read_short = dither_read_short ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/* Turn on dither on write if asked. */
|
||||
if (mode == SFM_WRITE && psf->write_dither.type != 0)
|
||||
{ if (pdither == NULL)
|
||||
pdither = psf->dither = calloc (1, sizeof (DITHER_DATA)) ;
|
||||
if (pdither == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_FLOAT :
|
||||
pdither->write_int = psf->write_int ;
|
||||
psf->write_int = dither_write_int ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_32 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
pdither->write_short = psf->write_short ;
|
||||
psf->write_short = dither_write_short ;
|
||||
|
||||
pdither->write_int = psf->write_int ;
|
||||
psf->write_int = dither_write_int ;
|
||||
|
||||
pdither->write_float = psf->write_float ;
|
||||
psf->write_float = dither_write_float ;
|
||||
|
||||
pdither->write_double = psf->write_double ;
|
||||
psf->write_double = dither_write_double ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* dither_init */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static void dither_short (const short *in, short *out, int frames, int channels) ;
|
||||
static void dither_int (const int *in, int *out, int frames, int channels) ;
|
||||
|
||||
static void dither_float (const float *in, float *out, int frames, int channels) ;
|
||||
static void dither_double (const double *in, double *out, int frames, int channels) ;
|
||||
|
||||
static sf_count_t
|
||||
dither_read_short (SF_PRIVATE * UNUSED (psf), short * UNUSED (ptr), sf_count_t len)
|
||||
{
|
||||
return len ;
|
||||
} /* dither_read_short */
|
||||
|
||||
static sf_count_t
|
||||
dither_read_int (SF_PRIVATE * UNUSED (psf), int * UNUSED (ptr), sf_count_t len)
|
||||
{
|
||||
return len ;
|
||||
} /* dither_read_int */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
dither_write_short (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ DITHER_DATA *pdither ;
|
||||
int bufferlen, writecount, thiswrite ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((pdither = psf->dither) == NULL)
|
||||
{ psf->error = SFE_DITHER_BAD_PTR ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_DPCM_8 :
|
||||
break ;
|
||||
|
||||
default :
|
||||
return pdither->write_short (psf, ptr, len) ;
|
||||
} ;
|
||||
|
||||
bufferlen = sizeof (pdither->buffer) / sizeof (short) ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
writecount /= psf->sf.channels ;
|
||||
writecount *= psf->sf.channels ;
|
||||
|
||||
dither_short (ptr, (short*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_short (psf, (short*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dither_write_short */
|
||||
|
||||
static sf_count_t
|
||||
dither_write_int (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ DITHER_DATA *pdither ;
|
||||
int bufferlen, writecount, thiswrite ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((pdither = psf->dither) == NULL)
|
||||
{ psf->error = SFE_DITHER_BAD_PTR ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DPCM_8 :
|
||||
case SF_FORMAT_DPCM_16 :
|
||||
break ;
|
||||
|
||||
default :
|
||||
return pdither->write_int (psf, ptr, len) ;
|
||||
} ;
|
||||
|
||||
|
||||
bufferlen = sizeof (pdither->buffer) / sizeof (int) ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
writecount /= psf->sf.channels ;
|
||||
writecount *= psf->sf.channels ;
|
||||
|
||||
dither_int (ptr, (int*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_int (psf, (int*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dither_write_int */
|
||||
|
||||
static sf_count_t
|
||||
dither_write_float (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ DITHER_DATA *pdither ;
|
||||
int bufferlen, writecount, thiswrite ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((pdither = psf->dither) == NULL)
|
||||
{ psf->error = SFE_DITHER_BAD_PTR ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DPCM_8 :
|
||||
case SF_FORMAT_DPCM_16 :
|
||||
break ;
|
||||
|
||||
default :
|
||||
return pdither->write_float (psf, ptr, len) ;
|
||||
} ;
|
||||
|
||||
bufferlen = sizeof (pdither->buffer) / sizeof (float) ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (float) len ;
|
||||
writecount /= psf->sf.channels ;
|
||||
writecount *= psf->sf.channels ;
|
||||
|
||||
dither_float (ptr, (float*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_float (psf, (float*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dither_write_float */
|
||||
|
||||
static sf_count_t
|
||||
dither_write_double (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ DITHER_DATA *pdither ;
|
||||
int bufferlen, writecount, thiswrite ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if ((pdither = psf->dither) == NULL)
|
||||
{ psf->error = SFE_DITHER_BAD_PTR ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DPCM_8 :
|
||||
case SF_FORMAT_DPCM_16 :
|
||||
break ;
|
||||
|
||||
default :
|
||||
return pdither->write_double (psf, ptr, len) ;
|
||||
} ;
|
||||
|
||||
|
||||
bufferlen = sizeof (pdither->buffer) / sizeof (double) ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (double) len ;
|
||||
writecount /= psf->sf.channels ;
|
||||
writecount *= psf->sf.channels ;
|
||||
|
||||
dither_double (ptr, (double*) pdither->buffer, writecount / psf->sf.channels, psf->sf.channels) ;
|
||||
|
||||
thiswrite = pdither->write_double (psf, (double*) pdither->buffer, writecount) ;
|
||||
total += thiswrite ;
|
||||
len -= thiswrite ;
|
||||
if (thiswrite < writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dither_write_double */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static void
|
||||
dither_short (const short *in, short *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
|
||||
} /* dither_short */
|
||||
|
||||
static void
|
||||
dither_int (const int *in, int *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
|
||||
} /* dither_int */
|
||||
|
||||
static void
|
||||
dither_float (const float *in, float *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
|
||||
} /* dither_float */
|
||||
|
||||
static void
|
||||
dither_double (const double *in, double *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
|
||||
} /* dither_double */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
#if 0
|
||||
|
||||
/*
|
||||
** Not made public because this (maybe) requires storage of state information.
|
||||
**
|
||||
** Also maybe need separate state info for each channel!!!!
|
||||
*/
|
||||
|
||||
int
|
||||
DO_NOT_USE_sf_dither_short (const SF_DITHER_INFO *dither, const short *in, short *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
if (! dither)
|
||||
return SFE_DITHER_BAD_PTR ;
|
||||
|
||||
switch (dither->type & SFD_TYPEMASK)
|
||||
{ case SFD_WHITE :
|
||||
case SFD_TRIANGULAR_PDF :
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_DITHER_BAD_TYPE ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* DO_NOT_USE_sf_dither_short */
|
||||
|
||||
int
|
||||
DO_NOT_USE_sf_dither_int (const SF_DITHER_INFO *dither, const int *in, int *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
if (! dither)
|
||||
return SFE_DITHER_BAD_PTR ;
|
||||
|
||||
switch (dither->type & SFD_TYPEMASK)
|
||||
{ case SFD_WHITE :
|
||||
case SFD_TRIANGULAR_PDF :
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_DITHER_BAD_TYPE ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* DO_NOT_USE_sf_dither_int */
|
||||
|
||||
int
|
||||
DO_NOT_USE_sf_dither_float (const SF_DITHER_INFO *dither, const float *in, float *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
if (! dither)
|
||||
return SFE_DITHER_BAD_PTR ;
|
||||
|
||||
switch (dither->type & SFD_TYPEMASK)
|
||||
{ case SFD_WHITE :
|
||||
case SFD_TRIANGULAR_PDF :
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_DITHER_BAD_TYPE ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* DO_NOT_USE_sf_dither_float */
|
||||
|
||||
int
|
||||
DO_NOT_USE_sf_dither_double (const SF_DITHER_INFO *dither, const double *in, double *out, int frames, int channels)
|
||||
{ int ch, k ;
|
||||
|
||||
if (! dither)
|
||||
return SFE_DITHER_BAD_PTR ;
|
||||
|
||||
switch (dither->type & SFD_TYPEMASK)
|
||||
{ case SFD_WHITE :
|
||||
case SFD_TRIANGULAR_PDF :
|
||||
for (ch = 0 ; ch < channels ; ch++)
|
||||
for (k = ch ; k < channels * frames ; k += channels)
|
||||
out [k] = in [k] ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_DITHER_BAD_TYPE ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* DO_NOT_USE_sf_dither_double */
|
||||
|
||||
#endif
|
||||
|
||||
1043
project/jni/sndfile/src/double64.c
Normal file
1043
project/jni/sndfile/src/double64.c
Normal file
File diff suppressed because it is too large
Load Diff
200
project/jni/sndfile/src/dwd.c
Normal file
200
project/jni/sndfile/src/dwd.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE == 0)
|
||||
|
||||
int
|
||||
dwd_open (SF_PRIVATE *psf)
|
||||
{ if (psf)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
return 0 ;
|
||||
} /* dwd_open */
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define SFE_DWD_NO_DWD 1666
|
||||
#define SFE_DWD_BAND_BIT_WIDTH 1667
|
||||
#define SFE_DWD_COMPRESSION 1668
|
||||
|
||||
#define DWD_IDENTIFIER "DiamondWare Digitized\n\0\x1a"
|
||||
#define DWD_IDENTIFIER_LEN 24
|
||||
|
||||
#define DWD_HEADER_LEN 57
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int dwd_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
static int dwd_close (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
dwd_open (SF_PRIVATE *psf)
|
||||
{ int error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = dwd_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_DWD)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{
|
||||
/*-psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU)
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
else if (psf->endian != SF_ENDIAN_LITTLE)
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (! (encoding = dwd_write_header (psf, SF_FALSE)))
|
||||
return psf->error ;
|
||||
|
||||
psf->write_header = dwd_write_header ;
|
||||
-*/
|
||||
} ;
|
||||
|
||||
psf->container_close = dwd_close ;
|
||||
|
||||
/*-psf->blockwidth = psf->bytewidth * psf->sf.channels ;-*/
|
||||
|
||||
return error ;
|
||||
} /* dwd_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
dwd_close (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* dwd_close */
|
||||
|
||||
/* This struct contains all the fields of interest om the DWD header, but does not
|
||||
** do so in the same order and layout as the actual file, header.
|
||||
** No assumptions are made about the packing of this struct.
|
||||
*/
|
||||
typedef struct
|
||||
{ unsigned char major, minor, compression, channels, bitwidth ;
|
||||
unsigned short srate, maxval ;
|
||||
unsigned int id, datalen, frames, offset ;
|
||||
} DWD_HEADER ;
|
||||
|
||||
static int
|
||||
dwd_read_header (SF_PRIVATE *psf)
|
||||
{ DWD_HEADER dwdh ;
|
||||
|
||||
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
|
||||
/* Set position to start of file to begin reading header. */
|
||||
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, DWD_IDENTIFIER_LEN) ;
|
||||
|
||||
if (memcmp (psf->u.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0)
|
||||
return SFE_DWD_NO_DWD ;
|
||||
|
||||
psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", psf->u.cbuf) ;
|
||||
|
||||
psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ;
|
||||
psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ;
|
||||
psf_binheader_readf (psf, "e211", &dwdh.srate, &dwdh.channels, &dwdh.bitwidth) ;
|
||||
psf_binheader_readf (psf, "e24", &dwdh.maxval, &dwdh.datalen) ;
|
||||
psf_binheader_readf (psf, "e44", &dwdh.frames, &dwdh.offset) ;
|
||||
|
||||
psf_log_printf (psf, " Version Major : %d\n Version Minor : %d\n Unique ID : %08X\n",
|
||||
dwdh.major, dwdh.minor, dwdh.id) ;
|
||||
psf_log_printf (psf, " Compression : %d => ", dwdh.compression) ;
|
||||
|
||||
if (dwdh.compression != 0)
|
||||
{ psf_log_printf (psf, "Unsupported compression\n") ;
|
||||
return SFE_DWD_COMPRESSION ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, "None\n") ;
|
||||
|
||||
psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n"
|
||||
" Bit Width : %d\n",
|
||||
dwdh.srate, dwdh.channels, dwdh.bitwidth) ;
|
||||
|
||||
switch (dwdh.bitwidth)
|
||||
{ case 8 :
|
||||
psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_S8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
break ;
|
||||
|
||||
case 16 :
|
||||
psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "*** Bad bit width %d\n", dwdh.bitwidth) ;
|
||||
return SFE_DWD_BAND_BIT_WIDTH ;
|
||||
} ;
|
||||
|
||||
if (psf->filelength != dwdh.offset + dwdh.datalen)
|
||||
{ psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ;
|
||||
dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ;
|
||||
|
||||
psf_log_printf (psf, " Max Value : %d\n", dwdh.maxval) ;
|
||||
psf_log_printf (psf, " Frames : %d\n", dwdh.frames) ;
|
||||
psf_log_printf (psf, " Data Offset : %d\n", dwdh.offset) ;
|
||||
|
||||
psf->datalength = dwdh.datalen ;
|
||||
psf->dataoffset = dwdh.offset ;
|
||||
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf->sf.samplerate = dwdh.srate ;
|
||||
psf->sf.channels = dwdh.channels ;
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
return pcm_init (psf) ;
|
||||
} /* dwd_read_header */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#endif
|
||||
|
||||
662
project/jni/sndfile/src/dwvw.c
Normal file
662
project/jni/sndfile/src/dwvw.c
Normal file
@@ -0,0 +1,662 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*===========================================================================
|
||||
** Delta Word Variable Width
|
||||
**
|
||||
** This decoder and encoder were implemented using information found in this
|
||||
** document : http://home.swbell.net/rubywand/R011SNDFMTS.TXT
|
||||
**
|
||||
** According to the document, the algorithm "was invented 1991 by Magnus
|
||||
** Lidstrom and is copyright 1993 by NuEdge Development".
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
typedef struct
|
||||
{ int dwm_maxsize, bit_width, max_delta, span ;
|
||||
int samplecount ;
|
||||
int bit_count, bits, last_delta_width, last_sample ;
|
||||
struct
|
||||
{ int index, end ;
|
||||
unsigned char buffer [256] ;
|
||||
} b ;
|
||||
} DWVW_PRIVATE ;
|
||||
|
||||
/*============================================================================================
|
||||
*/
|
||||
|
||||
static sf_count_t dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t dwvw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
static int dwvw_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len) ;
|
||||
static int dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count) ;
|
||||
|
||||
static int dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len) ;
|
||||
static void dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits) ;
|
||||
static void dwvw_read_reset (DWVW_PRIVATE *pdwvw) ;
|
||||
|
||||
/*============================================================================================
|
||||
** DWVW initialisation function.
|
||||
*/
|
||||
|
||||
int
|
||||
dwvw_init (SF_PRIVATE *psf, int bitwidth)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
|
||||
if (psf->codec_data != NULL)
|
||||
{ psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (bitwidth > 24)
|
||||
return SFE_DWVW_BAD_BITWIDTH ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if ((pdwvw = calloc (1, sizeof (DWVW_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = (void*) pdwvw ;
|
||||
|
||||
pdwvw->bit_width = bitwidth ;
|
||||
pdwvw->dwm_maxsize = bitwidth / 2 ;
|
||||
pdwvw->max_delta = 1 << (bitwidth - 1) ;
|
||||
pdwvw->span = 1 << bitwidth ;
|
||||
|
||||
dwvw_read_reset (pdwvw) ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ psf->read_short = dwvw_read_s ;
|
||||
psf->read_int = dwvw_read_i ;
|
||||
psf->read_float = dwvw_read_f ;
|
||||
psf->read_double = dwvw_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ psf->write_short = dwvw_write_s ;
|
||||
psf->write_int = dwvw_write_i ;
|
||||
psf->write_float = dwvw_write_f ;
|
||||
psf->write_double = dwvw_write_d ;
|
||||
} ;
|
||||
|
||||
psf->codec_close = dwvw_close ;
|
||||
psf->seek = dwvw_seek ;
|
||||
|
||||
/* FIXME : This is bogus. */
|
||||
psf->sf.frames = SF_COUNT_MAX ;
|
||||
psf->datalength = psf->sf.frames ;
|
||||
/* EMXIF : This is bogus. */
|
||||
|
||||
return 0 ;
|
||||
} /* dwvw_init */
|
||||
|
||||
/*--------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
dwvw_close (SF_PRIVATE *psf)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ static int last_values [12] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } ;
|
||||
|
||||
/* Write 8 zero samples to fully flush output. */
|
||||
dwvw_encode_data (psf, pdwvw, last_values, 12) ;
|
||||
|
||||
/* Write the last buffer worth of data to disk. */
|
||||
psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ;
|
||||
|
||||
if (psf->write_header)
|
||||
psf->write_header (psf, SF_TRUE) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* dwvw_close */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
{ psf->error = SFE_INTERNAL ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (offset == 0)
|
||||
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
dwvw_read_reset (pdwvw) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} /* dwvw_seek */
|
||||
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
dwvw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = iptr [k] >> 16 ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_read_s */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = dwvw_decode_data (psf, pdwvw, ptr, readcount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_read_i */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x80000000) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (float) (iptr [k]) ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_read_f */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x80000000) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = dwvw_decode_data (psf, pdwvw, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (iptr [k]) ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_read_d */
|
||||
|
||||
static int
|
||||
dwvw_decode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int *ptr, int len)
|
||||
{ int count ;
|
||||
int delta_width_modifier, delta_width, delta_negative, delta, sample ;
|
||||
|
||||
/* Restore state from last decode call. */
|
||||
delta_width = pdwvw->last_delta_width ;
|
||||
sample = pdwvw->last_sample ;
|
||||
|
||||
for (count = 0 ; count < len ; count++)
|
||||
{ /* If bit_count parameter is zero get the delta_width_modifier. */
|
||||
delta_width_modifier = dwvw_decode_load_bits (psf, pdwvw, -1) ;
|
||||
|
||||
/* Check for end of input bit stream. Break loop if end. */
|
||||
if (delta_width_modifier < 0)
|
||||
break ;
|
||||
|
||||
if (delta_width_modifier && dwvw_decode_load_bits (psf, pdwvw, 1))
|
||||
delta_width_modifier = - delta_width_modifier ;
|
||||
|
||||
/* Calculate the current word width. */
|
||||
delta_width = (delta_width + delta_width_modifier + pdwvw->bit_width) % pdwvw->bit_width ;
|
||||
|
||||
/* Load the delta. */
|
||||
delta = 0 ;
|
||||
if (delta_width)
|
||||
{ delta = dwvw_decode_load_bits (psf, pdwvw, delta_width - 1) | (1 << (delta_width - 1)) ;
|
||||
delta_negative = dwvw_decode_load_bits (psf, pdwvw, 1) ;
|
||||
if (delta == pdwvw->max_delta - 1)
|
||||
delta += dwvw_decode_load_bits (psf, pdwvw, 1) ;
|
||||
if (delta_negative)
|
||||
delta = -delta ;
|
||||
} ;
|
||||
|
||||
/* Calculate the sample */
|
||||
sample += delta ;
|
||||
|
||||
if (sample >= pdwvw->max_delta)
|
||||
sample -= pdwvw->span ;
|
||||
else if (sample < - pdwvw->max_delta)
|
||||
sample += pdwvw->span ;
|
||||
|
||||
/* Store the sample justifying to the most significant bit. */
|
||||
ptr [count] = sample << (32 - pdwvw->bit_width) ;
|
||||
|
||||
if (pdwvw->b.end == 0 && pdwvw->bit_count == 0)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
pdwvw->last_delta_width = delta_width ;
|
||||
pdwvw->last_sample = sample ;
|
||||
|
||||
pdwvw->samplecount += count ;
|
||||
|
||||
return count ;
|
||||
} /* dwvw_decode_data */
|
||||
|
||||
static int
|
||||
dwvw_decode_load_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int bit_count)
|
||||
{ int output = 0, get_dwm = SF_FALSE ;
|
||||
|
||||
/*
|
||||
** Depending on the value of parameter bit_count, either get the
|
||||
** required number of bits (ie bit_count > 0) or the
|
||||
** delta_width_modifier (otherwise).
|
||||
*/
|
||||
|
||||
if (bit_count < 0)
|
||||
{ get_dwm = SF_TRUE ;
|
||||
/* modify bit_count to ensure we have enought bits for finding dwm. */
|
||||
bit_count = pdwvw->dwm_maxsize ;
|
||||
} ;
|
||||
|
||||
/* Load bits in bit reseviour. */
|
||||
while (pdwvw->bit_count < bit_count)
|
||||
{ if (pdwvw->b.index >= pdwvw->b.end)
|
||||
{ pdwvw->b.end = psf_fread (pdwvw->b.buffer, 1, sizeof (pdwvw->b.buffer), psf) ;
|
||||
pdwvw->b.index = 0 ;
|
||||
} ;
|
||||
|
||||
/* Check for end of input stream. */
|
||||
if (bit_count < 8 && pdwvw->b.end == 0)
|
||||
return -1 ;
|
||||
|
||||
pdwvw->bits = (pdwvw->bits << 8) ;
|
||||
|
||||
if (pdwvw->b.index < pdwvw->b.end)
|
||||
{ pdwvw->bits |= pdwvw->b.buffer [pdwvw->b.index] ;
|
||||
pdwvw->b.index ++ ;
|
||||
} ;
|
||||
pdwvw->bit_count += 8 ;
|
||||
} ;
|
||||
|
||||
/* If asked to get bits do so. */
|
||||
if (! get_dwm)
|
||||
{ output = (pdwvw->bits >> (pdwvw->bit_count - bit_count)) & ((1 << bit_count) - 1) ;
|
||||
pdwvw->bit_count -= bit_count ;
|
||||
return output ;
|
||||
} ;
|
||||
|
||||
/* Otherwise must have been asked to get delta_width_modifier. */
|
||||
while (output < (pdwvw->dwm_maxsize))
|
||||
{ pdwvw->bit_count -= 1 ;
|
||||
if (pdwvw->bits & (1 << pdwvw->bit_count))
|
||||
break ;
|
||||
output += 1 ;
|
||||
} ;
|
||||
|
||||
return output ;
|
||||
} /* dwvw_decode_load_bits */
|
||||
|
||||
static void
|
||||
dwvw_read_reset (DWVW_PRIVATE *pdwvw)
|
||||
{ pdwvw->samplecount = 0 ;
|
||||
pdwvw->b.index = 0 ;
|
||||
pdwvw->b.end = 0 ;
|
||||
pdwvw->bit_count = 0 ;
|
||||
pdwvw->bits = 0 ;
|
||||
pdwvw->last_delta_width = 0 ;
|
||||
pdwvw->last_sample = 0 ;
|
||||
} /* dwvw_read_reset */
|
||||
|
||||
static void
|
||||
dwvw_encode_store_bits (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, int data, int new_bits)
|
||||
{ int byte ;
|
||||
|
||||
/* Shift the bits into the resevoir. */
|
||||
pdwvw->bits = (pdwvw->bits << new_bits) | (data & ((1 << new_bits) - 1)) ;
|
||||
pdwvw->bit_count += new_bits ;
|
||||
|
||||
/* Transfer bit to buffer. */
|
||||
while (pdwvw->bit_count >= 8)
|
||||
{ byte = pdwvw->bits >> (pdwvw->bit_count - 8) ;
|
||||
pdwvw->bit_count -= 8 ;
|
||||
pdwvw->b.buffer [pdwvw->b.index] = byte & 0xFF ;
|
||||
pdwvw->b.index ++ ;
|
||||
} ;
|
||||
|
||||
if (pdwvw->b.index > SIGNED_SIZEOF (pdwvw->b.buffer) - 4)
|
||||
{ psf_fwrite (pdwvw->b.buffer, 1, pdwvw->b.index, psf) ;
|
||||
pdwvw->b.index = 0 ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* dwvw_encode_store_bits */
|
||||
|
||||
#if 0
|
||||
/* Debigging routine. */
|
||||
static void
|
||||
dump_bits (DWVW_PRIVATE *pdwvw)
|
||||
{ int k, mask ;
|
||||
|
||||
for (k = 0 ; k < 10 && k < pdwvw->b.index ; k++)
|
||||
{ mask = 0x80 ;
|
||||
while (mask)
|
||||
{ putchar (mask & pdwvw->b.buffer [k] ? '1' : '0') ;
|
||||
mask >>= 1 ;
|
||||
} ;
|
||||
putchar (' ') ;
|
||||
}
|
||||
|
||||
for (k = pdwvw->bit_count - 1 ; k >= 0 ; k --)
|
||||
putchar (pdwvw->bits & (1 << k) ? '1' : '0') ;
|
||||
|
||||
putchar ('\n') ;
|
||||
} /* dump_bits */
|
||||
#endif
|
||||
|
||||
#define HIGHEST_BIT(x,count) \
|
||||
{ int y = x ; \
|
||||
(count) = 0 ; \
|
||||
while (y) \
|
||||
{ (count) ++ ; \
|
||||
y >>= 1 ; \
|
||||
} ; \
|
||||
} ;
|
||||
|
||||
static int
|
||||
dwvw_encode_data (SF_PRIVATE *psf, DWVW_PRIVATE *pdwvw, const int *ptr, int len)
|
||||
{ int count ;
|
||||
int delta_width_modifier, delta, delta_negative, delta_width, extra_bit ;
|
||||
|
||||
for (count = 0 ; count < len ; count++)
|
||||
{ delta = (ptr [count] >> (32 - pdwvw->bit_width)) - pdwvw->last_sample ;
|
||||
|
||||
/* Calculate extra_bit if needed. */
|
||||
extra_bit = -1 ;
|
||||
delta_negative = 0 ;
|
||||
if (delta < -pdwvw->max_delta)
|
||||
delta = pdwvw->max_delta + (delta % pdwvw->max_delta) ;
|
||||
else if (delta == -pdwvw->max_delta)
|
||||
{ extra_bit = 1 ;
|
||||
delta_negative = 1 ;
|
||||
delta = pdwvw->max_delta - 1 ;
|
||||
}
|
||||
else if (delta > pdwvw->max_delta)
|
||||
{ delta_negative = 1 ;
|
||||
delta = pdwvw->span - delta ;
|
||||
delta = abs (delta) ;
|
||||
}
|
||||
else if (delta == pdwvw->max_delta)
|
||||
{ extra_bit = 1 ;
|
||||
delta = pdwvw->max_delta - 1 ;
|
||||
}
|
||||
else if (delta < 0)
|
||||
{ delta_negative = 1 ;
|
||||
delta = abs (delta) ;
|
||||
} ;
|
||||
|
||||
if (delta == pdwvw->max_delta - 1 && extra_bit == -1)
|
||||
extra_bit = 0 ;
|
||||
|
||||
/* Find width in bits of delta */
|
||||
HIGHEST_BIT (delta, delta_width) ;
|
||||
|
||||
/* Calculate the delta_width_modifier */
|
||||
delta_width_modifier = (delta_width - pdwvw->last_delta_width) % pdwvw->bit_width ;
|
||||
if (delta_width_modifier > pdwvw->dwm_maxsize)
|
||||
delta_width_modifier -= pdwvw->bit_width ;
|
||||
if (delta_width_modifier < -pdwvw->dwm_maxsize)
|
||||
delta_width_modifier += pdwvw->bit_width ;
|
||||
|
||||
/* Write delta_width_modifier zeros, followed by terminating '1'. */
|
||||
dwvw_encode_store_bits (psf, pdwvw, 0, abs (delta_width_modifier)) ;
|
||||
if (abs (delta_width_modifier) != pdwvw->dwm_maxsize)
|
||||
dwvw_encode_store_bits (psf, pdwvw, 1, 1) ;
|
||||
|
||||
/* Write delta_width_modifier sign. */
|
||||
if (delta_width_modifier < 0)
|
||||
dwvw_encode_store_bits (psf, pdwvw, 1, 1) ;
|
||||
if (delta_width_modifier > 0)
|
||||
dwvw_encode_store_bits (psf, pdwvw, 0, 1) ;
|
||||
|
||||
/* Write delta and delta sign bit. */
|
||||
if (delta_width)
|
||||
{ dwvw_encode_store_bits (psf, pdwvw, delta, abs (delta_width) - 1) ;
|
||||
dwvw_encode_store_bits (psf, pdwvw, (delta_negative ? 1 : 0), 1) ;
|
||||
} ;
|
||||
|
||||
/* Write extra bit!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
|
||||
if (extra_bit >= 0)
|
||||
dwvw_encode_store_bits (psf, pdwvw, extra_bit, 1) ;
|
||||
|
||||
pdwvw->last_sample = ptr [count] >> (32 - pdwvw->bit_width) ;
|
||||
pdwvw->last_delta_width = delta_width ;
|
||||
} ;
|
||||
|
||||
pdwvw->samplecount += count ;
|
||||
|
||||
return count ;
|
||||
} /* dwvw_encode_data */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = ptr [total + k] << 16 ;
|
||||
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_write_s */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = dwvw_encode_data (psf, pdwvw, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_write_i */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = lrintf (normfact * ptr [total + k]) ;
|
||||
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_write_f */
|
||||
|
||||
static sf_count_t
|
||||
dwvw_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ DWVW_PRIVATE *pdwvw ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pdwvw = (DWVW_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : 1.0 ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = lrint (normfact * ptr [total + k]) ;
|
||||
count = dwvw_encode_data (psf, pdwvw, iptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* dwvw_write_d */
|
||||
|
||||
1547
project/jni/sndfile/src/file_io.c
Normal file
1547
project/jni/sndfile/src/file_io.c
Normal file
File diff suppressed because it is too large
Load Diff
1324
project/jni/sndfile/src/flac.c
Normal file
1324
project/jni/sndfile/src/flac.c
Normal file
File diff suppressed because it is too large
Load Diff
996
project/jni/sndfile/src/float32.c
Normal file
996
project/jni/sndfile/src/float32.c
Normal file
@@ -0,0 +1,996 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if CPU_IS_LITTLE_ENDIAN
|
||||
#define FLOAT32_READ float32_le_read
|
||||
#define FLOAT32_WRITE float32_le_write
|
||||
#elif CPU_IS_BIG_ENDIAN
|
||||
#define FLOAT32_READ float32_be_read
|
||||
#define FLOAT32_WRITE float32_be_write
|
||||
#endif
|
||||
|
||||
/*--------------------------------------------------------------------------------------------
|
||||
** Processor floating point capabilities. float32_get_capability () returns one of the
|
||||
** latter four values.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ FLOAT_UNKNOWN = 0x00,
|
||||
FLOAT_CAN_RW_LE = 0x12,
|
||||
FLOAT_CAN_RW_BE = 0x23,
|
||||
FLOAT_BROKEN_LE = 0x34,
|
||||
FLOAT_BROKEN_BE = 0x45
|
||||
} ;
|
||||
|
||||
/*--------------------------------------------------------------------------------------------
|
||||
** Prototypes for private functions.
|
||||
*/
|
||||
|
||||
static sf_count_t host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static void float32_peak_update (SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx) ;
|
||||
|
||||
static sf_count_t replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static void bf2f_array (float *buffer, int count) ;
|
||||
static void f2bf_array (float *buffer, int count) ;
|
||||
|
||||
static int float32_get_capability (SF_PRIVATE *psf) ;
|
||||
|
||||
/*--------------------------------------------------------------------------------------------
|
||||
** Exported functions.
|
||||
*/
|
||||
|
||||
int
|
||||
float32_init (SF_PRIVATE *psf)
|
||||
{ static int float_caps ;
|
||||
|
||||
float_caps = float32_get_capability (psf) ;
|
||||
|
||||
psf->blockwidth = sizeof (float) * psf->sf.channels ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ switch (psf->endian + float_caps)
|
||||
{ case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->read_short = host_read_f2s ;
|
||||
psf->read_int = host_read_f2i ;
|
||||
psf->read_float = host_read_f ;
|
||||
psf->read_double = host_read_f2d ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->read_short = host_read_f2s ;
|
||||
psf->read_int = host_read_f2i ;
|
||||
psf->read_float = host_read_f ;
|
||||
psf->read_double = host_read_f2d ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->read_short = host_read_f2s ;
|
||||
psf->read_int = host_read_f2i ;
|
||||
psf->read_float = host_read_f ;
|
||||
psf->read_double = host_read_f2d ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->read_short = host_read_f2s ;
|
||||
psf->read_int = host_read_f2i ;
|
||||
psf->read_float = host_read_f ;
|
||||
psf->read_double = host_read_f2d ;
|
||||
break ;
|
||||
|
||||
/* When the CPU is not IEEE compatible. */
|
||||
case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->read_short = replace_read_f2s ;
|
||||
psf->read_int = replace_read_f2i ;
|
||||
psf->read_float = replace_read_f ;
|
||||
psf->read_double = replace_read_f2d ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->read_short = replace_read_f2s ;
|
||||
psf->read_int = replace_read_f2i ;
|
||||
psf->read_float = replace_read_f ;
|
||||
psf->read_double = replace_read_f2d ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->read_short = replace_read_f2s ;
|
||||
psf->read_int = replace_read_f2i ;
|
||||
psf->read_float = replace_read_f ;
|
||||
psf->read_double = replace_read_f2d ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->read_short = replace_read_f2s ;
|
||||
psf->read_int = replace_read_f2i ;
|
||||
psf->read_float = replace_read_f ;
|
||||
psf->read_double = replace_read_f2d ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ switch (psf->endian + float_caps)
|
||||
{ case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->write_short = host_write_s2f ;
|
||||
psf->write_int = host_write_i2f ;
|
||||
psf->write_float = host_write_f ;
|
||||
psf->write_double = host_write_d2f ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->write_short = host_write_s2f ;
|
||||
psf->write_int = host_write_i2f ;
|
||||
psf->write_float = host_write_f ;
|
||||
psf->write_double = host_write_d2f ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_BIG + FLOAT_CAN_RW_LE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->write_short = host_write_s2f ;
|
||||
psf->write_int = host_write_i2f ;
|
||||
psf->write_float = host_write_f ;
|
||||
psf->write_double = host_write_d2f ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_BE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->write_short = host_write_s2f ;
|
||||
psf->write_int = host_write_i2f ;
|
||||
psf->write_float = host_write_f ;
|
||||
psf->write_double = host_write_d2f ;
|
||||
break ;
|
||||
|
||||
/* When the CPU is not IEEE compatible. */
|
||||
case (SF_ENDIAN_BIG + FLOAT_BROKEN_LE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->write_short = replace_write_s2f ;
|
||||
psf->write_int = replace_write_i2f ;
|
||||
psf->write_float = replace_write_f ;
|
||||
psf->write_double = replace_write_d2f ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_LE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->write_short = replace_write_s2f ;
|
||||
psf->write_int = replace_write_i2f ;
|
||||
psf->write_float = replace_write_f ;
|
||||
psf->write_double = replace_write_d2f ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_BIG + FLOAT_BROKEN_BE) :
|
||||
psf->data_endswap = SF_FALSE ;
|
||||
psf->write_short = replace_write_s2f ;
|
||||
psf->write_int = replace_write_i2f ;
|
||||
psf->write_float = replace_write_f ;
|
||||
psf->write_double = replace_write_d2f ;
|
||||
break ;
|
||||
|
||||
case (SF_ENDIAN_LITTLE + FLOAT_BROKEN_BE) :
|
||||
psf->data_endswap = SF_TRUE ;
|
||||
psf->write_short = replace_write_s2f ;
|
||||
psf->write_int = replace_write_i2f ;
|
||||
psf->write_float = replace_write_f ;
|
||||
psf->write_double = replace_write_d2f ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->filelength > psf->dataoffset)
|
||||
{ psf->datalength = (psf->dataend > 0) ? psf->dataend - psf->dataoffset :
|
||||
psf->filelength - psf->dataoffset ;
|
||||
}
|
||||
else
|
||||
psf->datalength = 0 ;
|
||||
|
||||
psf->sf.frames = psf->blockwidth > 0 ? psf->datalength / psf->blockwidth : 0 ;
|
||||
|
||||
return 0 ;
|
||||
} /* float32_init */
|
||||
|
||||
float
|
||||
float32_be_read (unsigned char *cptr)
|
||||
{ int exponent, mantissa, negative ;
|
||||
float fvalue ;
|
||||
|
||||
negative = cptr [0] & 0x80 ;
|
||||
exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ;
|
||||
mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ;
|
||||
|
||||
if (! (exponent || mantissa))
|
||||
return 0.0 ;
|
||||
|
||||
mantissa |= 0x800000 ;
|
||||
exponent = exponent ? exponent - 127 : 0 ;
|
||||
|
||||
fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
|
||||
|
||||
if (negative)
|
||||
fvalue *= -1 ;
|
||||
|
||||
if (exponent > 0)
|
||||
fvalue *= pow (2.0, exponent) ;
|
||||
else if (exponent < 0)
|
||||
fvalue /= pow (2.0, abs (exponent)) ;
|
||||
|
||||
return fvalue ;
|
||||
} /* float32_be_read */
|
||||
|
||||
float
|
||||
float32_le_read (unsigned char *cptr)
|
||||
{ int exponent, mantissa, negative ;
|
||||
float fvalue ;
|
||||
|
||||
negative = cptr [3] & 0x80 ;
|
||||
exponent = ((cptr [3] & 0x7F) << 1) | ((cptr [2] & 0x80) ? 1 : 0) ;
|
||||
mantissa = ((cptr [2] & 0x7F) << 16) | (cptr [1] << 8) | (cptr [0]) ;
|
||||
|
||||
if (! (exponent || mantissa))
|
||||
return 0.0 ;
|
||||
|
||||
mantissa |= 0x800000 ;
|
||||
exponent = exponent ? exponent - 127 : 0 ;
|
||||
|
||||
fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
|
||||
|
||||
if (negative)
|
||||
fvalue *= -1 ;
|
||||
|
||||
if (exponent > 0)
|
||||
fvalue *= pow (2.0, exponent) ;
|
||||
else if (exponent < 0)
|
||||
fvalue /= pow (2.0, abs (exponent)) ;
|
||||
|
||||
return fvalue ;
|
||||
} /* float32_le_read */
|
||||
|
||||
void
|
||||
float32_le_write (float in, unsigned char *out)
|
||||
{ int exponent, mantissa, negative = 0 ;
|
||||
|
||||
memset (out, 0, sizeof (int)) ;
|
||||
|
||||
if (fabs (in) < 1e-30)
|
||||
return ;
|
||||
|
||||
if (in < 0.0)
|
||||
{ in *= -1.0 ;
|
||||
negative = 1 ;
|
||||
} ;
|
||||
|
||||
in = frexp (in, &exponent) ;
|
||||
|
||||
exponent += 126 ;
|
||||
|
||||
in *= (float) 0x1000000 ;
|
||||
mantissa = (((int) in) & 0x7FFFFF) ;
|
||||
|
||||
if (negative)
|
||||
out [3] |= 0x80 ;
|
||||
|
||||
if (exponent & 0x01)
|
||||
out [2] |= 0x80 ;
|
||||
|
||||
out [0] = mantissa & 0xFF ;
|
||||
out [1] = (mantissa >> 8) & 0xFF ;
|
||||
out [2] |= (mantissa >> 16) & 0x7F ;
|
||||
out [3] |= (exponent >> 1) & 0x7F ;
|
||||
|
||||
return ;
|
||||
} /* float32_le_write */
|
||||
|
||||
void
|
||||
float32_be_write (float in, unsigned char *out)
|
||||
{ int exponent, mantissa, negative = 0 ;
|
||||
|
||||
memset (out, 0, sizeof (int)) ;
|
||||
|
||||
if (fabs (in) < 1e-30)
|
||||
return ;
|
||||
|
||||
if (in < 0.0)
|
||||
{ in *= -1.0 ;
|
||||
negative = 1 ;
|
||||
} ;
|
||||
|
||||
in = frexp (in, &exponent) ;
|
||||
|
||||
exponent += 126 ;
|
||||
|
||||
in *= (float) 0x1000000 ;
|
||||
mantissa = (((int) in) & 0x7FFFFF) ;
|
||||
|
||||
if (negative)
|
||||
out [0] |= 0x80 ;
|
||||
|
||||
if (exponent & 0x01)
|
||||
out [1] |= 0x80 ;
|
||||
|
||||
out [3] = mantissa & 0xFF ;
|
||||
out [2] = (mantissa >> 8) & 0xFF ;
|
||||
out [1] |= (mantissa >> 16) & 0x7F ;
|
||||
out [0] |= (exponent >> 1) & 0x7F ;
|
||||
|
||||
return ;
|
||||
} /* float32_be_write */
|
||||
|
||||
/*==============================================================================================
|
||||
** Private functions.
|
||||
*/
|
||||
|
||||
static void
|
||||
float32_peak_update (SF_PRIVATE *psf, const float *buffer, int count, sf_count_t indx)
|
||||
{ int chan ;
|
||||
int k, position ;
|
||||
float fmaxval ;
|
||||
|
||||
for (chan = 0 ; chan < psf->sf.channels ; chan++)
|
||||
{ fmaxval = fabs (buffer [chan]) ;
|
||||
position = 0 ;
|
||||
for (k = chan ; k < count ; k += psf->sf.channels)
|
||||
if (fmaxval < fabs (buffer [k]))
|
||||
{ fmaxval = fabs (buffer [k]) ;
|
||||
position = k ;
|
||||
} ;
|
||||
|
||||
if (fmaxval > psf->peak_info->peaks [chan].value)
|
||||
{ psf->peak_info->peaks [chan].value = fmaxval ;
|
||||
psf->peak_info->peaks [chan].position = psf->write_current + indx + (position / psf->sf.channels) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* float32_peak_update */
|
||||
|
||||
static int
|
||||
float32_get_capability (SF_PRIVATE *psf)
|
||||
{ union
|
||||
{ float f ;
|
||||
int i ;
|
||||
unsigned char c [4] ;
|
||||
} data ;
|
||||
|
||||
data.f = (float) 1.23456789 ; /* Some abitrary value. */
|
||||
|
||||
if (! psf->ieee_replace)
|
||||
{ /* If this test is true ints and floats are compatible and little endian. */
|
||||
if (data.c [0] == 0x52 && data.c [1] == 0x06 && data.c [2] == 0x9e && data.c [3] == 0x3f)
|
||||
return FLOAT_CAN_RW_LE ;
|
||||
|
||||
/* If this test is true ints and floats are compatible and big endian. */
|
||||
if (data.c [3] == 0x52 && data.c [2] == 0x06 && data.c [1] == 0x9e && data.c [0] == 0x3f)
|
||||
return FLOAT_CAN_RW_BE ;
|
||||
} ;
|
||||
|
||||
/* Floats are broken. Don't expect reading or writing to be fast. */
|
||||
psf_log_printf (psf, "Using IEEE replacement code for float.\n") ;
|
||||
|
||||
return (CPU_IS_LITTLE_ENDIAN) ? FLOAT_BROKEN_LE : FLOAT_BROKEN_BE ;
|
||||
} /* float32_get_capability */
|
||||
|
||||
/*=======================================================================================
|
||||
*/
|
||||
|
||||
static void
|
||||
f2s_array (const float *src, int count, short *dest, float scale)
|
||||
{
|
||||
while (--count >= 0)
|
||||
{ dest [count] = lrintf (scale * src [count]) ;
|
||||
} ;
|
||||
} /* f2s_array */
|
||||
|
||||
static void
|
||||
f2s_clip_array (const float *src, int count, short *dest, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ float tmp = scale * src [count] ;
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > 32767.0)
|
||||
dest [count] = SHRT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < -32768.0)
|
||||
dest [count] = SHRT_MIN ;
|
||||
else
|
||||
dest [count] = lrintf (tmp) ;
|
||||
} ;
|
||||
} /* f2s_clip_array */
|
||||
|
||||
static inline void
|
||||
f2i_array (const float *src, int count, int *dest, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = lrintf (scale * src [count]) ;
|
||||
} ;
|
||||
} /* f2i_array */
|
||||
|
||||
static inline void
|
||||
f2i_clip_array (const float *src, int count, int *dest, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ float tmp = scale * src [count] ;
|
||||
|
||||
if (CPU_CLIPS_POSITIVE == 0 && tmp > (1.0 * INT_MAX))
|
||||
dest [count] = INT_MAX ;
|
||||
else if (CPU_CLIPS_NEGATIVE == 0 && tmp < (-1.0 * INT_MAX))
|
||||
dest [count] = INT_MIN ;
|
||||
else
|
||||
dest [count] = lrintf (tmp) ;
|
||||
} ;
|
||||
} /* f2i_clip_array */
|
||||
|
||||
static inline void
|
||||
f2d_array (const float *src, int count, double *dest)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = src [count] ;
|
||||
} ;
|
||||
} /* f2d_array */
|
||||
|
||||
static inline void
|
||||
s2f_array (const short *src, float *dest, int count, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = scale * src [count] ;
|
||||
} ;
|
||||
} /* s2f_array */
|
||||
|
||||
static inline void
|
||||
i2f_array (const int *src, float *dest, int count, float scale)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = scale * src [count] ;
|
||||
} ;
|
||||
} /* i2f_array */
|
||||
|
||||
static inline void
|
||||
d2f_array (const double *src, float *dest, int count)
|
||||
{ while (--count >= 0)
|
||||
{ dest [count] = src [count] ;
|
||||
} ;
|
||||
} /* d2f_array */
|
||||
|
||||
/*----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
host_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ void (*convert) (const float *, int, short *, float) ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
convert = (psf->add_clipping) ? f2s_clip_array : f2s_array ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
/* Fix me : Need lef2s_array */
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
convert (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_read_f2s */
|
||||
|
||||
static sf_count_t
|
||||
host_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ void (*convert) (const float *, int, int *, float) ;
|
||||
int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
convert = (psf->add_clipping) ? f2i_clip_array : f2i_array ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFFFFFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
convert (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_read_f2i */
|
||||
|
||||
static sf_count_t
|
||||
host_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->data_endswap != SF_TRUE)
|
||||
return psf_fread (ptr, sizeof (float), len, psf) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
endswap_int_copy ((int*) (ptr + total), psf->u.ibuf, readcount) ;
|
||||
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_read_f */
|
||||
|
||||
static sf_count_t
|
||||
host_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
/* Fix me : Need lef2d_array */
|
||||
f2d_array (psf->u.fbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_read_f2d */
|
||||
|
||||
static sf_count_t
|
||||
host_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
/* Erik */
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_write_s2f */
|
||||
|
||||
static sf_count_t
|
||||
host_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_write_i2f */
|
||||
|
||||
static sf_count_t
|
||||
host_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, ptr, len, 0) ;
|
||||
|
||||
if (psf->data_endswap != SF_TRUE)
|
||||
return psf_fwrite (ptr, sizeof (float), len, psf) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
endswap_int_copy (psf->u.ibuf, (const int*) (ptr + total), bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_write_f */
|
||||
|
||||
static sf_count_t
|
||||
host_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
d2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* host_write_d2f */
|
||||
|
||||
/*=======================================================================================
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f2s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
f2s_array (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_read_f2s */
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f2i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
scale = (psf->float_int_mult == 0) ? 1.0 : 0x7FFF / psf->float_max ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
f2i_array (psf->u.fbuf, readcount, ptr + total, scale) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_read_f2i */
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
/* FIX THIS */
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
memcpy (ptr + total, psf->u.fbuf, bufferlen * sizeof (float)) ;
|
||||
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_read_f */
|
||||
|
||||
static sf_count_t
|
||||
replace_read_f2d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ int bufferlen, readcount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
readcount = psf_fread (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
bf2f_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
f2d_array (psf->u.fbuf, readcount, ptr + total) ;
|
||||
total += readcount ;
|
||||
if (readcount < bufferlen)
|
||||
break ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_read_f2d */
|
||||
|
||||
static sf_count_t
|
||||
replace_write_s2f (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / 0x8000 ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
s2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_write_s2f */
|
||||
|
||||
static sf_count_t
|
||||
replace_write_i2f (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
float scale ;
|
||||
|
||||
scale = (psf->scale_int_float == 0) ? 1.0 : 1.0 / (8.0 * 0x10000000) ;
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
i2f_array (ptr + total, psf->u.fbuf, bufferlen, scale) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_write_i2f */
|
||||
|
||||
static sf_count_t
|
||||
replace_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
/* FIX THIS */
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, ptr, len, 0) ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
|
||||
memcpy (psf->u.fbuf, ptr + total, bufferlen * sizeof (float)) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float) , bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_write_f */
|
||||
|
||||
static sf_count_t
|
||||
replace_write_d2f (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ int bufferlen, writecount ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = ARRAY_LEN (psf->u.fbuf) ;
|
||||
|
||||
while (len > 0)
|
||||
{ if (len < bufferlen)
|
||||
bufferlen = (int) len ;
|
||||
d2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->peak_info)
|
||||
float32_peak_update (psf, psf->u.fbuf, bufferlen, total / psf->sf.channels) ;
|
||||
|
||||
f2bf_array (psf->u.fbuf, bufferlen) ;
|
||||
|
||||
if (psf->data_endswap == SF_TRUE)
|
||||
endswap_int_array (psf->u.ibuf, bufferlen) ;
|
||||
|
||||
writecount = psf_fwrite (psf->u.fbuf, sizeof (float), bufferlen, psf) ;
|
||||
total += writecount ;
|
||||
if (writecount < bufferlen)
|
||||
break ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* replace_write_d2f */
|
||||
|
||||
/*----------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static void
|
||||
bf2f_array (float *buffer, int count)
|
||||
{ while (--count >= 0)
|
||||
{ buffer [count] = FLOAT32_READ ((unsigned char *) (buffer + count)) ;
|
||||
} ;
|
||||
} /* bf2f_array */
|
||||
|
||||
static void
|
||||
f2bf_array (float *buffer, int count)
|
||||
{ while (--count >= 0)
|
||||
{ FLOAT32_WRITE (buffer [count], (unsigned char*) (buffer + count)) ;
|
||||
} ;
|
||||
} /* f2bf_array */
|
||||
|
||||
604
project/jni/sndfile/src/g72x.c
Normal file
604
project/jni/sndfile/src/g72x.c
Normal file
@@ -0,0 +1,604 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "G72x/g72x.h"
|
||||
|
||||
/* This struct is private to the G72x code. */
|
||||
struct g72x_state ;
|
||||
typedef struct g72x_state G72x_STATE ;
|
||||
|
||||
typedef struct
|
||||
{ /* Private data. Don't mess with it. */
|
||||
struct g72x_state * private ;
|
||||
|
||||
/* Public data. Read only. */
|
||||
int blocksize, samplesperblock, bytesperblock ;
|
||||
|
||||
/* Public data. Read and write. */
|
||||
int blocks_total, block_curr, sample_curr ;
|
||||
unsigned char block [G72x_BLOCK_SIZE] ;
|
||||
short samples [G72x_BLOCK_SIZE] ;
|
||||
} G72x_PRIVATE ;
|
||||
|
||||
static int psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ;
|
||||
static int psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x) ;
|
||||
|
||||
static sf_count_t g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
|
||||
static int g72x_close (SF_PRIVATE *psf) ;
|
||||
|
||||
|
||||
/*============================================================================================
|
||||
** WAV G721 Reader initialisation function.
|
||||
*/
|
||||
|
||||
int
|
||||
g72x_init (SF_PRIVATE * psf)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
int bitspersample, bytesperblock, codec ;
|
||||
|
||||
if (psf->codec_data != NULL)
|
||||
{ psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->sf.seekable = SF_FALSE ;
|
||||
|
||||
if (psf->sf.channels != 1)
|
||||
return SFE_G72X_NOT_MONO ;
|
||||
|
||||
if ((pg72x = calloc (1, sizeof (G72x_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = (void*) pg72x ;
|
||||
|
||||
pg72x->block_curr = 0 ;
|
||||
pg72x->sample_curr = 0 ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_G721_32 :
|
||||
codec = G721_32_BITS_PER_SAMPLE ;
|
||||
bytesperblock = G721_32_BYTES_PER_BLOCK ;
|
||||
bitspersample = G721_32_BITS_PER_SAMPLE ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_G723_24:
|
||||
codec = G723_24_BITS_PER_SAMPLE ;
|
||||
bytesperblock = G723_24_BYTES_PER_BLOCK ;
|
||||
bitspersample = G723_24_BITS_PER_SAMPLE ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_G723_40:
|
||||
codec = G723_40_BITS_PER_SAMPLE ;
|
||||
bytesperblock = G723_40_BYTES_PER_BLOCK ;
|
||||
bitspersample = G723_40_BITS_PER_SAMPLE ;
|
||||
break ;
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth = 1 ;
|
||||
|
||||
psf->filelength = psf_get_filelen (psf) ;
|
||||
if (psf->filelength < psf->dataoffset)
|
||||
psf->filelength = psf->dataoffset ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
if (psf->dataend > 0)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ pg72x->private = g72x_reader_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
|
||||
if (pg72x->private == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
pg72x->bytesperblock = bytesperblock ;
|
||||
|
||||
psf->read_short = g72x_read_s ;
|
||||
psf->read_int = g72x_read_i ;
|
||||
psf->read_float = g72x_read_f ;
|
||||
psf->read_double = g72x_read_d ;
|
||||
|
||||
psf->seek = g72x_seek ;
|
||||
|
||||
if (psf->datalength % pg72x->blocksize)
|
||||
{ psf_log_printf (psf, "*** Odd psf->datalength (%D) should be a multiple of %d\n", psf->datalength, pg72x->blocksize) ;
|
||||
pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ;
|
||||
}
|
||||
else
|
||||
pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
|
||||
|
||||
psf->sf.frames = pg72x->blocks_total * pg72x->samplesperblock ;
|
||||
|
||||
psf_g72x_decode_block (psf, pg72x) ;
|
||||
}
|
||||
else if (psf->file.mode == SFM_WRITE)
|
||||
{ pg72x->private = g72x_writer_init (codec, &(pg72x->blocksize), &(pg72x->samplesperblock)) ;
|
||||
if (pg72x->private == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
pg72x->bytesperblock = bytesperblock ;
|
||||
|
||||
psf->write_short = g72x_write_s ;
|
||||
psf->write_int = g72x_write_i ;
|
||||
psf->write_float = g72x_write_f ;
|
||||
psf->write_double = g72x_write_d ;
|
||||
|
||||
if (psf->datalength % pg72x->blocksize)
|
||||
pg72x->blocks_total = (psf->datalength / pg72x->blocksize) + 1 ;
|
||||
else
|
||||
pg72x->blocks_total = psf->datalength / pg72x->blocksize ;
|
||||
|
||||
if (psf->datalength > 0)
|
||||
psf->sf.frames = (8 * psf->datalength) / bitspersample ;
|
||||
|
||||
if ((psf->sf.frames * bitspersample) / 8 != psf->datalength)
|
||||
psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ;
|
||||
} ;
|
||||
|
||||
psf->codec_close = g72x_close ;
|
||||
|
||||
return 0 ;
|
||||
} /* g72x_init */
|
||||
|
||||
/*============================================================================================
|
||||
** G721 Read Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
psf_g72x_decode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x)
|
||||
{ int k ;
|
||||
|
||||
pg72x->block_curr ++ ;
|
||||
pg72x->sample_curr = 0 ;
|
||||
|
||||
if (pg72x->block_curr > pg72x->blocks_total)
|
||||
{ memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pg72x->block, 1, pg72x->bytesperblock, psf)) != pg72x->bytesperblock)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pg72x->bytesperblock) ;
|
||||
|
||||
pg72x->blocksize = k ;
|
||||
g72x_decode_block (pg72x->private, pg72x->block, pg72x->samples) ;
|
||||
|
||||
return 1 ;
|
||||
} /* psf_g72x_decode_block */
|
||||
|
||||
static int
|
||||
g72x_read_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ if (pg72x->block_curr > pg72x->blocks_total)
|
||||
{ memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
if (pg72x->sample_curr >= pg72x->samplesperblock)
|
||||
psf_g72x_decode_block (psf, pg72x) ;
|
||||
|
||||
count = pg72x->samplesperblock - pg72x->sample_curr ;
|
||||
count = (len - indx > count) ? count : len - indx ;
|
||||
|
||||
memcpy (&(ptr [indx]), &(pg72x->samples [pg72x->sample_curr]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pg72x->sample_curr += count ;
|
||||
total = indx ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_read_block */
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
int readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = g72x_read_block (psf, pg72x, ptr, readcount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_read_s */
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
|
||||
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = sptr [k] << 16 ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_read_i */
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_read_f */
|
||||
|
||||
static sf_count_t
|
||||
g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = g72x_read_block (psf, pg72x, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (sptr [k]) ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_read_d */
|
||||
|
||||
static sf_count_t
|
||||
g72x_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t UNUSED (offset))
|
||||
{
|
||||
psf_log_printf (psf, "seek unsupported\n") ;
|
||||
|
||||
/* No simple solution. To do properly, would need to seek
|
||||
** to start of file and decode everything up to seek position.
|
||||
** Maybe implement SEEK_SET to 0 only?
|
||||
*/
|
||||
return 0 ;
|
||||
|
||||
/*
|
||||
** G72x_PRIVATE *pg72x ;
|
||||
** int newblock, newsample, sample_curr ;
|
||||
**
|
||||
** if (psf->codec_data == NULL)
|
||||
** return 0 ;
|
||||
** pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
**
|
||||
** if (! (psf->datalength && psf->dataoffset))
|
||||
** { psf->error = SFE_BAD_SEEK ;
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
**
|
||||
** sample_curr = (8 * psf->datalength) / G721_32_BITS_PER_SAMPLE ;
|
||||
**
|
||||
** switch (whence)
|
||||
** { case SEEK_SET :
|
||||
** if (offset < 0 || offset > sample_curr)
|
||||
** { psf->error = SFE_BAD_SEEK ;
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
** newblock = offset / pg72x->samplesperblock ;
|
||||
** newsample = offset % pg72x->samplesperblock ;
|
||||
** break ;
|
||||
**
|
||||
** case SEEK_CUR :
|
||||
** if (psf->current + offset < 0 || psf->current + offset > sample_curr)
|
||||
** { psf->error = SFE_BAD_SEEK ;
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
** newblock = (8 * (psf->current + offset)) / pg72x->samplesperblock ;
|
||||
** newsample = (8 * (psf->current + offset)) % pg72x->samplesperblock ;
|
||||
** break ;
|
||||
**
|
||||
** case SEEK_END :
|
||||
** if (offset > 0 || sample_curr + offset < 0)
|
||||
** { psf->error = SFE_BAD_SEEK ;
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
** newblock = (sample_curr + offset) / pg72x->samplesperblock ;
|
||||
** newsample = (sample_curr + offset) % pg72x->samplesperblock ;
|
||||
** break ;
|
||||
**
|
||||
** default :
|
||||
** psf->error = SFE_BAD_SEEK ;
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
**
|
||||
** if (psf->file.mode == SFM_READ)
|
||||
** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ;
|
||||
** pg72x->block_curr = newblock ;
|
||||
** psf_g72x_decode_block (psf, pg72x) ;
|
||||
** pg72x->sample_curr = newsample ;
|
||||
** }
|
||||
** else
|
||||
** { /+* What to do about write??? *+/
|
||||
** psf->error = SFE_BAD_SEEK ;
|
||||
** return PSF_SEEK_ERROR ;
|
||||
** } ;
|
||||
**
|
||||
** psf->current = newblock * pg72x->samplesperblock + newsample ;
|
||||
** return psf->current ;
|
||||
**
|
||||
*/
|
||||
} /* g72x_seek */
|
||||
|
||||
/*==========================================================================================
|
||||
** G72x Write Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
psf_g72x_encode_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x)
|
||||
{ int k ;
|
||||
|
||||
/* Encode the samples. */
|
||||
g72x_encode_block (pg72x->private, pg72x->samples, pg72x->block) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pg72x->block, 1, pg72x->blocksize, psf)) != pg72x->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pg72x->blocksize) ;
|
||||
|
||||
pg72x->sample_curr = 0 ;
|
||||
pg72x->block_curr ++ ;
|
||||
|
||||
/* Set samples to zero for next block. */
|
||||
memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
|
||||
|
||||
return 1 ;
|
||||
} /* psf_g72x_encode_block */
|
||||
|
||||
static int
|
||||
g72x_write_block (SF_PRIVATE *psf, G72x_PRIVATE *pg72x, const short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ count = pg72x->samplesperblock - pg72x->sample_curr ;
|
||||
|
||||
if (count > len - indx)
|
||||
count = len - indx ;
|
||||
|
||||
memcpy (&(pg72x->samples [pg72x->sample_curr]), &(ptr [indx]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pg72x->sample_curr += count ;
|
||||
total = indx ;
|
||||
|
||||
if (pg72x->sample_curr >= pg72x->samplesperblock)
|
||||
psf_g72x_encode_block (psf, pg72x) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_write_block */
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
int writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = g72x_write_block (psf, pg72x, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_write_s */
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* g72x_write_i */
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrintf (normfact * ptr [total + k]) ;
|
||||
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_write_f */
|
||||
|
||||
static sf_count_t
|
||||
g72x_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ((SF_BUFFER_LEN / psf->blockwidth) * psf->blockwidth) / sizeof (short) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrint (normfact * ptr [total + k]) ;
|
||||
count = g72x_write_block (psf, pg72x, sptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* g72x_write_d */
|
||||
|
||||
static int
|
||||
g72x_close (SF_PRIVATE *psf)
|
||||
{ G72x_PRIVATE *pg72x ;
|
||||
|
||||
pg72x = (G72x_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* If a block has been partially assembled, write it out
|
||||
** as the final block.
|
||||
*/
|
||||
|
||||
if (pg72x->sample_curr && pg72x->sample_curr < G72x_BLOCK_SIZE)
|
||||
psf_g72x_encode_block (psf, pg72x) ;
|
||||
|
||||
if (psf->write_header)
|
||||
psf->write_header (psf, SF_FALSE) ;
|
||||
} ;
|
||||
|
||||
/* Only free the pointer allocated by g72x_(reader|writer)_init. */
|
||||
free (pg72x->private) ;
|
||||
|
||||
return 0 ;
|
||||
} /* g72x_close */
|
||||
|
||||
621
project/jni/sndfile/src/gsm610.c
Normal file
621
project/jni/sndfile/src/gsm610.c
Normal file
@@ -0,0 +1,621 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "wav_w64.h"
|
||||
#include "GSM610/gsm.h"
|
||||
|
||||
#define GSM610_BLOCKSIZE 33
|
||||
#define GSM610_SAMPLES 160
|
||||
|
||||
typedef struct gsm610_tag
|
||||
{ int blocks ;
|
||||
int blockcount, samplecount ;
|
||||
int samplesperblock, blocksize ;
|
||||
|
||||
int (*decode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
|
||||
int (*encode_block) (SF_PRIVATE *psf, struct gsm610_tag *pgsm610) ;
|
||||
|
||||
short samples [WAV_W64_GSM610_SAMPLES] ;
|
||||
unsigned char block [WAV_W64_GSM610_BLOCKSIZE] ;
|
||||
|
||||
/* Damn I hate typedef-ed pointers; yes, gsm is a pointer type. */
|
||||
gsm gsm_data ;
|
||||
} GSM610_PRIVATE ;
|
||||
|
||||
static sf_count_t gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static int gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len) ;
|
||||
static int gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len) ;
|
||||
|
||||
static int gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
|
||||
static int gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
|
||||
|
||||
static int gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
|
||||
static int gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610) ;
|
||||
|
||||
static sf_count_t gsm610_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
|
||||
static int gsm610_close (SF_PRIVATE *psf) ;
|
||||
|
||||
/*============================================================================================
|
||||
** WAV GSM610 initialisation function.
|
||||
*/
|
||||
|
||||
int
|
||||
gsm610_init (SF_PRIVATE *psf)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
int true_flag = 1 ;
|
||||
|
||||
if (psf->codec_data != NULL)
|
||||
{ psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
psf->sf.seekable = SF_FALSE ;
|
||||
|
||||
if ((pgsm610 = calloc (1, sizeof (GSM610_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = pgsm610 ;
|
||||
|
||||
memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ;
|
||||
|
||||
/*============================================================
|
||||
|
||||
Need separate gsm_data structs for encode and decode.
|
||||
|
||||
============================================================*/
|
||||
|
||||
if ((pgsm610->gsm_data = gsm_create ()) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
switch (SF_CONTAINER (psf->sf.format))
|
||||
{ case SF_FORMAT_WAV :
|
||||
case SF_FORMAT_WAVEX :
|
||||
case SF_FORMAT_W64 :
|
||||
gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
|
||||
|
||||
pgsm610->encode_block = gsm610_wav_encode_block ;
|
||||
pgsm610->decode_block = gsm610_wav_decode_block ;
|
||||
|
||||
pgsm610->samplesperblock = WAV_W64_GSM610_SAMPLES ;
|
||||
pgsm610->blocksize = WAV_W64_GSM610_BLOCKSIZE ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_AIFF :
|
||||
case SF_FORMAT_RAW :
|
||||
pgsm610->encode_block = gsm610_encode_block ;
|
||||
pgsm610->decode_block = gsm610_decode_block ;
|
||||
|
||||
pgsm610->samplesperblock = GSM610_SAMPLES ;
|
||||
pgsm610->blocksize = GSM610_BLOCKSIZE ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_INTERNAL ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ if (psf->datalength % pgsm610->blocksize == 0)
|
||||
pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
|
||||
else if (psf->datalength % pgsm610->blocksize == 1 && pgsm610->blocksize == GSM610_BLOCKSIZE)
|
||||
{ /*
|
||||
** Weird AIFF specific case.
|
||||
** AIFF chunks must be at an even offset from the start of file and
|
||||
** GSM610_BLOCKSIZE is odd which can result in an odd length SSND
|
||||
** chunk. The SSND chunk then gets padded on write which means that
|
||||
** when it is read the datalength is too big by 1.
|
||||
*/
|
||||
pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
|
||||
}
|
||||
else
|
||||
{ psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ;
|
||||
pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
|
||||
} ;
|
||||
|
||||
psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
pgsm610->decode_block (psf, pgsm610) ; /* Read first block. */
|
||||
|
||||
psf->read_short = gsm610_read_s ;
|
||||
psf->read_int = gsm610_read_i ;
|
||||
psf->read_float = gsm610_read_f ;
|
||||
psf->read_double = gsm610_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ pgsm610->blockcount = 0 ;
|
||||
pgsm610->samplecount = 0 ;
|
||||
|
||||
psf->write_short = gsm610_write_s ;
|
||||
psf->write_int = gsm610_write_i ;
|
||||
psf->write_float = gsm610_write_f ;
|
||||
psf->write_double = gsm610_write_d ;
|
||||
} ;
|
||||
|
||||
psf->codec_close = gsm610_close ;
|
||||
|
||||
psf->seek = gsm610_seek ;
|
||||
|
||||
psf->filelength = psf_get_filelen (psf) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
return 0 ;
|
||||
} /* gsm610_init */
|
||||
|
||||
/*============================================================================================
|
||||
** GSM 6.10 Read Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
gsm610_wav_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
{ int k ;
|
||||
|
||||
pgsm610->blockcount ++ ;
|
||||
pgsm610->samplecount = 0 ;
|
||||
|
||||
if (pgsm610->blockcount > pgsm610->blocks)
|
||||
{ memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
|
||||
|
||||
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
|
||||
{ psf_log_printf (psf, "Error from WAV gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (gsm_decode (pgsm610->gsm_data, pgsm610->block + (WAV_W64_GSM610_BLOCKSIZE + 1) / 2, pgsm610->samples + WAV_W64_GSM610_SAMPLES / 2) < 0)
|
||||
{ psf_log_printf (psf, "Error from WAV gsm_decode() on frame : %d.5\n", pgsm610->blockcount) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* gsm610_wav_decode_block */
|
||||
|
||||
static int
|
||||
gsm610_decode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
{ int k ;
|
||||
|
||||
pgsm610->blockcount ++ ;
|
||||
pgsm610->samplecount = 0 ;
|
||||
|
||||
if (pgsm610->blockcount > pgsm610->blocks)
|
||||
{ memset (pgsm610->samples, 0, GSM610_SAMPLES * sizeof (short)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
|
||||
|
||||
if (gsm_decode (pgsm610->gsm_data, pgsm610->block, pgsm610->samples) < 0)
|
||||
{ psf_log_printf (psf, "Error from standard gsm_decode() on frame : %d\n", pgsm610->blockcount) ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* gsm610_decode_block */
|
||||
|
||||
static int
|
||||
gsm610_read_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ if (pgsm610->blockcount >= pgsm610->blocks && pgsm610->samplecount >= pgsm610->samplesperblock)
|
||||
{ memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
if (pgsm610->samplecount >= pgsm610->samplesperblock)
|
||||
pgsm610->decode_block (psf, pgsm610) ;
|
||||
|
||||
count = pgsm610->samplesperblock - pgsm610->samplecount ;
|
||||
count = (len - indx > count) ? count : len - indx ;
|
||||
|
||||
memcpy (&(ptr [indx]), &(pgsm610->samples [pgsm610->samplecount]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pgsm610->samplecount += count ;
|
||||
total = indx ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* gsm610_read_block */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
int readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ readcount = (len > 0x10000000) ? 0x1000000 : (int) len ;
|
||||
|
||||
count = gsm610_read_block (psf, pgsm610, ptr, readcount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* gsm610_read_s */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = sptr [k] << 16 ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* gsm610_read_i */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* gsm610_read_f */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = gsm610_read_block (psf, pgsm610, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * sptr [k] ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* gsm610_read_d */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_seek (SF_PRIVATE *psf, int UNUSED (mode), sf_count_t offset)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
int newblock, newsample ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->dataoffset < 0)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
if (offset == 0)
|
||||
{ int true_flag = 1 ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
pgsm610->blockcount = 0 ;
|
||||
|
||||
gsm_init (pgsm610->gsm_data) ;
|
||||
if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAV ||
|
||||
(SF_CONTAINER (psf->sf.format)) == SF_FORMAT_W64)
|
||||
gsm_option (pgsm610->gsm_data, GSM_OPT_WAV49, &true_flag) ;
|
||||
|
||||
pgsm610->decode_block (psf, pgsm610) ;
|
||||
pgsm610->samplecount = 0 ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (offset < 0 || offset > pgsm610->blocks * pgsm610->samplesperblock)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
newblock = offset / pgsm610->samplesperblock ;
|
||||
newsample = offset % pgsm610->samplesperblock ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ if (psf->read_current != newblock * pgsm610->samplesperblock + newsample)
|
||||
{ psf_fseek (psf, psf->dataoffset + newblock * pgsm610->samplesperblock, SEEK_SET) ;
|
||||
pgsm610->blockcount = newblock ;
|
||||
pgsm610->decode_block (psf, pgsm610) ;
|
||||
pgsm610->samplecount = newsample ;
|
||||
} ;
|
||||
|
||||
return newblock * pgsm610->samplesperblock + newsample ;
|
||||
} ;
|
||||
|
||||
/* What to do about write??? */
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} /* gsm610_seek */
|
||||
|
||||
/*==========================================================================================
|
||||
** GSM 6.10 Write Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
gsm610_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
{ int k ;
|
||||
|
||||
/* Encode the samples. */
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pgsm610->block, 1, GSM610_BLOCKSIZE, psf)) != GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, GSM610_BLOCKSIZE) ;
|
||||
|
||||
pgsm610->samplecount = 0 ;
|
||||
pgsm610->blockcount ++ ;
|
||||
|
||||
/* Set samples to zero for next block. */
|
||||
memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
|
||||
|
||||
return 1 ;
|
||||
} /* gsm610_encode_block */
|
||||
|
||||
static int
|
||||
gsm610_wav_encode_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610)
|
||||
{ int k ;
|
||||
|
||||
/* Encode the samples. */
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples, pgsm610->block) ;
|
||||
gsm_encode (pgsm610->gsm_data, pgsm610->samples+WAV_W64_GSM610_SAMPLES/2, pgsm610->block+WAV_W64_GSM610_BLOCKSIZE/2) ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
if ((k = psf_fwrite (pgsm610->block, 1, WAV_W64_GSM610_BLOCKSIZE, psf)) != WAV_W64_GSM610_BLOCKSIZE)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, WAV_W64_GSM610_BLOCKSIZE) ;
|
||||
|
||||
pgsm610->samplecount = 0 ;
|
||||
pgsm610->blockcount ++ ;
|
||||
|
||||
/* Set samples to zero for next block. */
|
||||
memset (pgsm610->samples, 0, WAV_W64_GSM610_SAMPLES * sizeof (short)) ;
|
||||
|
||||
return 1 ;
|
||||
} /* gsm610_wav_encode_block */
|
||||
|
||||
static int
|
||||
gsm610_write_block (SF_PRIVATE *psf, GSM610_PRIVATE *pgsm610, const short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ count = pgsm610->samplesperblock - pgsm610->samplecount ;
|
||||
|
||||
if (count > len - indx)
|
||||
count = len - indx ;
|
||||
|
||||
memcpy (&(pgsm610->samples [pgsm610->samplecount]), &(ptr [indx]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pgsm610->samplecount += count ;
|
||||
total = indx ;
|
||||
|
||||
if (pgsm610->samplecount >= pgsm610->samplesperblock)
|
||||
pgsm610->encode_block (psf, pgsm610) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* gsm610_write_block */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
int writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = gsm610_write_block (psf, pgsm610, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* gsm610_write_s */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* gsm610_write_i */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrintf (normfact * ptr [total + k]) ;
|
||||
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* gsm610_write_f */
|
||||
|
||||
static sf_count_t
|
||||
gsm610_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrint (normfact * ptr [total + k]) ;
|
||||
count = gsm610_write_block (psf, pgsm610, sptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* gsm610_write_d */
|
||||
|
||||
static int
|
||||
gsm610_close (SF_PRIVATE *psf)
|
||||
{ GSM610_PRIVATE *pgsm610 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
|
||||
pgsm610 = (GSM610_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* If a block has been partially assembled, write it out
|
||||
** as the final block.
|
||||
*/
|
||||
|
||||
if (pgsm610->samplecount && pgsm610->samplecount < pgsm610->samplesperblock)
|
||||
pgsm610->encode_block (psf, pgsm610) ;
|
||||
} ;
|
||||
|
||||
if (pgsm610->gsm_data)
|
||||
gsm_destroy (pgsm610->gsm_data) ;
|
||||
|
||||
return 0 ;
|
||||
} /* gsm610_close */
|
||||
|
||||
226
project/jni/sndfile/src/htk.c
Normal file
226
project/jni/sndfile/src/htk.c
Normal file
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define SFE_HTK_BAD_FILE_LEN 1666
|
||||
#define SFE_HTK_NOT_WAVEFORM 1667
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int htk_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int htk_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int htk_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
htk_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = 0 ;
|
||||
|
||||
if (psf->is_pipe)
|
||||
return SFE_HTK_NO_PIPE ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = htk_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_HTK)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (htk_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
psf->write_header = htk_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = htk_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* htk_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
htk_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
htk_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* htk_close */
|
||||
|
||||
static int
|
||||
htk_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ sf_count_t current ;
|
||||
int sample_count, sample_period ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
if (psf->filelength > 12)
|
||||
sample_count = (psf->filelength - 12) / 2 ;
|
||||
else
|
||||
sample_count = 0 ;
|
||||
|
||||
sample_period = 10000000 / psf->sf.samplerate ;
|
||||
|
||||
psf_binheader_writef (psf, "E444", sample_count, sample_period, 0x20000) ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* htk_write_header */
|
||||
|
||||
/*
|
||||
** Found the following info in a comment block within Bill Schottstaedt's
|
||||
** sndlib library.
|
||||
**
|
||||
** HTK format files consist of a contiguous sequence of samples preceded by a
|
||||
** header. Each sample is a vector of either 2-byte integers or 4-byte floats.
|
||||
** 2-byte integers are used for compressed forms as described below and for
|
||||
** vector quantised data as described later in section 5.11. HTK format data
|
||||
** files can also be used to store speech waveforms as described in section 5.8.
|
||||
**
|
||||
** The HTK file format header is 12 bytes long and contains the following data
|
||||
** nSamples -- number of samples in file (4-byte integer)
|
||||
** sampPeriod -- sample period in 100ns units (4-byte integer)
|
||||
** sampSize -- number of bytes per sample (2-byte integer)
|
||||
** parmKind -- a code indicating the sample kind (2-byte integer)
|
||||
**
|
||||
** The parameter kind consists of a 6 bit code representing the basic
|
||||
** parameter kind plus additional bits for each of the possible qualifiers.
|
||||
** The basic parameter kind codes are
|
||||
**
|
||||
** 0 WAVEFORM sampled waveform
|
||||
** 1 LPC linear prediction filter coefficients
|
||||
** 2 LPREFC linear prediction reflection coefficients
|
||||
** 3 LPCEPSTRA LPC cepstral coefficients
|
||||
** 4 LPDELCEP LPC cepstra plus delta coefficients
|
||||
** 5 IREFC LPC reflection coef in 16 bit integer format
|
||||
** 6 MFCC mel-frequency cepstral coefficients
|
||||
** 7 FBANK log mel-filter bank channel outputs
|
||||
** 8 MELSPEC linear mel-filter bank channel outputs
|
||||
** 9 USER user defined sample kind
|
||||
** 10 DISCRETE vector quantised data
|
||||
**
|
||||
** and the bit-encoding for the qualifiers (in octal) is
|
||||
** _E 000100 has energy
|
||||
** _N 000200 absolute energy suppressed
|
||||
** _D 000400 has delta coefficients
|
||||
** _A 001000 has acceleration coefficients
|
||||
** _C 002000 is compressed
|
||||
** _Z 004000 has zero mean static coef.
|
||||
** _K 010000 has CRC checksum
|
||||
** _O 020000 has 0'th cepstral coef.
|
||||
*/
|
||||
|
||||
static int
|
||||
htk_read_header (SF_PRIVATE *psf)
|
||||
{ int sample_count, sample_period, marker ;
|
||||
|
||||
psf_binheader_readf (psf, "pE444", 0, &sample_count, &sample_period, &marker) ;
|
||||
|
||||
if (2 * sample_count + 12 != psf->filelength)
|
||||
return SFE_HTK_BAD_FILE_LEN ;
|
||||
|
||||
if (marker != 0x20000)
|
||||
return SFE_HTK_NOT_WAVEFORM ;
|
||||
|
||||
psf->sf.channels = 1 ;
|
||||
|
||||
if (sample_period > 0)
|
||||
{ psf->sf.samplerate = 10000000 / sample_period ;
|
||||
psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n",
|
||||
sample_count, sample_period, psf->sf.samplerate) ;
|
||||
}
|
||||
else
|
||||
{ psf->sf.samplerate = 16000 ;
|
||||
psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d (should be > 0) => Guessed sample rate %d Hz\n",
|
||||
sample_count, sample_period, psf->sf.samplerate) ;
|
||||
} ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_HTK | SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
|
||||
/* HTK always has a 12 byte header. */
|
||||
psf->dataoffset = 12 ;
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
if (! psf->sf.frames && psf->blockwidth)
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
|
||||
return 0 ;
|
||||
} /* htk_read_header */
|
||||
|
||||
52
project/jni/sndfile/src/id3.c
Normal file
52
project/jni/sndfile/src/id3.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
** Copyright (C) 2010-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
int
|
||||
id3_skip (SF_PRIVATE * psf)
|
||||
{ unsigned char buf [10] ;
|
||||
|
||||
memset (buf, 0, sizeof (buf)) ;
|
||||
psf_binheader_readf (psf, "pb", 0, buf, 10) ;
|
||||
|
||||
if (buf [0] == 'I' && buf [1] == 'D' && buf [2] == '3')
|
||||
{ int offset = buf [6] & 0x7f ;
|
||||
offset = (offset << 7) | (buf [7] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [8] & 0x7f) ;
|
||||
offset = (offset << 7) | (buf [9] & 0x7f) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", make_size_t (offset)) ;
|
||||
|
||||
psf_log_printf (psf, "ID3 length : %d\n--------------------\n", offset) ;
|
||||
|
||||
psf->fileoffset = 10 + offset ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* id3_skip */
|
||||
946
project/jni/sndfile/src/ima_adpcm.c
Normal file
946
project/jni/sndfile/src/ima_adpcm.c
Normal file
@@ -0,0 +1,946 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
typedef struct IMA_ADPCM_PRIVATE_tag
|
||||
{ int (*decode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ;
|
||||
int (*encode_block) (SF_PRIVATE *psf, struct IMA_ADPCM_PRIVATE_tag *pima) ;
|
||||
|
||||
int channels, blocksize, samplesperblock, blocks ;
|
||||
int blockcount, samplecount ;
|
||||
int previous [2] ;
|
||||
int stepindx [2] ;
|
||||
unsigned char *block ;
|
||||
short *samples ;
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
short data [] ; /* ISO C99 struct flexible array. */
|
||||
#else
|
||||
short data [0] ; /* This is a hack and might not work. */
|
||||
#endif
|
||||
} IMA_ADPCM_PRIVATE ;
|
||||
|
||||
/*============================================================================================
|
||||
** Predefined IMA ADPCM data.
|
||||
*/
|
||||
|
||||
static int ima_indx_adjust [16] =
|
||||
{ -1, -1, -1, -1, /* +0 - +3, decrease the step size */
|
||||
2, 4, 6, 8, /* +4 - +7, increase the step size */
|
||||
-1, -1, -1, -1, /* -0 - -3, decrease the step size */
|
||||
2, 4, 6, 8, /* -4 - -7, increase the step size */
|
||||
} ;
|
||||
|
||||
static int ima_step_size [89] =
|
||||
{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
|
||||
253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
|
||||
1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
|
||||
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
|
||||
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
|
||||
32767
|
||||
} ;
|
||||
|
||||
static int ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;
|
||||
static int ima_writer_init (SF_PRIVATE *psf, int blockalign) ;
|
||||
|
||||
static int ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len) ;
|
||||
static int ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len) ;
|
||||
|
||||
static sf_count_t ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
|
||||
static int ima_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
|
||||
static int wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
|
||||
|
||||
/*-static int aiff_ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock) ;-*/
|
||||
static int aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
|
||||
static int aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima) ;
|
||||
|
||||
|
||||
static inline int
|
||||
clamp_ima_step_index (int indx)
|
||||
{ if (indx < 0)
|
||||
return 0 ;
|
||||
if (indx >= ARRAY_LEN (ima_step_size))
|
||||
return ARRAY_LEN (ima_step_size) - 1 ;
|
||||
|
||||
return indx ;
|
||||
} /* clamp_ima_step_index */
|
||||
|
||||
/*============================================================================================
|
||||
** IMA ADPCM Reader initialisation function.
|
||||
*/
|
||||
|
||||
int
|
||||
wav_w64_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
{ int error ;
|
||||
|
||||
if (psf->codec_data != NULL)
|
||||
{ psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
|
||||
return error ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
if ((error = ima_writer_init (psf, blockalign)))
|
||||
return error ;
|
||||
|
||||
psf->codec_close = ima_close ;
|
||||
psf->seek = ima_seek ;
|
||||
|
||||
return 0 ;
|
||||
} /* wav_w64_ima_init */
|
||||
|
||||
int
|
||||
aiff_ima_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
{ int error ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
if ((error = ima_reader_init (psf, blockalign, samplesperblock)))
|
||||
return error ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
if ((error = ima_writer_init (psf, blockalign)))
|
||||
return error ;
|
||||
|
||||
psf->codec_close = ima_close ;
|
||||
|
||||
return 0 ;
|
||||
} /* aiff_ima_init */
|
||||
|
||||
static int
|
||||
ima_close (SF_PRIVATE *psf)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* If a block has been partially assembled, write it out
|
||||
** as the final block.
|
||||
*/
|
||||
if (pima->samplecount && pima->samplecount < pima->samplesperblock)
|
||||
pima->encode_block (psf, pima) ;
|
||||
|
||||
psf->sf.frames = pima->samplesperblock * pima->blockcount / psf->sf.channels ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* ima_close */
|
||||
|
||||
/*============================================================================================
|
||||
** IMA ADPCM Read Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
ima_reader_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
int pimasize, count ;
|
||||
|
||||
if (psf->file.mode != SFM_READ)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign * psf->sf.channels + 3 * psf->sf.channels * samplesperblock ;
|
||||
|
||||
if (! (pima = calloc (1, pimasize)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = (void*) pima ;
|
||||
|
||||
pima->samples = pima->data ;
|
||||
pima->block = (unsigned char*) (pima->data + samplesperblock * psf->sf.channels) ;
|
||||
|
||||
pima->channels = psf->sf.channels ;
|
||||
pima->blocksize = blockalign ;
|
||||
pima->samplesperblock = samplesperblock ;
|
||||
|
||||
psf->filelength = psf_get_filelen (psf) ;
|
||||
psf->datalength = (psf->dataend) ? psf->dataend - psf->dataoffset :
|
||||
psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (pima->blocksize == 0)
|
||||
{ psf_log_printf (psf, "*** Error : pima->blocksize should not be zero.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->datalength % pima->blocksize)
|
||||
pima->blocks = psf->datalength / pima->blocksize + 1 ;
|
||||
else
|
||||
pima->blocks = psf->datalength / pima->blocksize ;
|
||||
|
||||
switch (SF_CONTAINER (psf->sf.format))
|
||||
{ case SF_FORMAT_WAV :
|
||||
case SF_FORMAT_W64 :
|
||||
count = 2 * (pima->blocksize - 4 * pima->channels) / pima->channels + 1 ;
|
||||
|
||||
if (pima->samplesperblock != count)
|
||||
{ psf_log_printf (psf, "*** Error : samplesperblock should be %d.\n", count) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
pima->decode_block = wav_w64_ima_decode_block ;
|
||||
|
||||
psf->sf.frames = pima->samplesperblock * pima->blocks ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_AIFF :
|
||||
psf_log_printf (psf, "still need to check block count\n") ;
|
||||
pima->decode_block = aiff_ima_decode_block ;
|
||||
psf->sf.frames = pima->samplesperblock * pima->blocks / pima->channels ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
pima->decode_block (psf, pima) ; /* Read first block. */
|
||||
|
||||
psf->read_short = ima_read_s ;
|
||||
psf->read_int = ima_read_i ;
|
||||
psf->read_float = ima_read_f ;
|
||||
psf->read_double = ima_read_d ;
|
||||
|
||||
return 0 ;
|
||||
} /* ima_reader_init */
|
||||
|
||||
static int
|
||||
aiff_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ unsigned char *blockdata ;
|
||||
int chan, k, diff, bytecode, predictor ;
|
||||
short step, stepindx, *sampledata ;
|
||||
|
||||
static int count = 0 ;
|
||||
count ++ ;
|
||||
|
||||
pima->blockcount += pima->channels ;
|
||||
pima->samplecount = 0 ;
|
||||
|
||||
if (pima->blockcount > pima->blocks)
|
||||
{ memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pima->block, 1, pima->blocksize * pima->channels, psf)) != pima->blocksize * pima->channels)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
|
||||
|
||||
/* Read and check the block header. */
|
||||
for (chan = 0 ; chan < pima->channels ; chan++)
|
||||
{ blockdata = pima->block + chan * 34 ;
|
||||
sampledata = pima->samples + chan ;
|
||||
|
||||
predictor = (blockdata [0] << 8) | (blockdata [1] & 0x80) ;
|
||||
|
||||
stepindx = blockdata [1] & 0x7F ;
|
||||
stepindx = clamp_ima_step_index (stepindx) ;
|
||||
|
||||
/*
|
||||
** Pull apart the packed 4 bit samples and store them in their
|
||||
** correct sample positions.
|
||||
*/
|
||||
for (k = 0 ; k < pima->blocksize - 2 ; k++)
|
||||
{ bytecode = blockdata [k + 2] ;
|
||||
sampledata [pima->channels * (2 * k + 0)] = bytecode & 0xF ;
|
||||
sampledata [pima->channels * (2 * k + 1)] = (bytecode >> 4) & 0xF ;
|
||||
} ;
|
||||
|
||||
/* Decode the encoded 4 bit samples. */
|
||||
for (k = 0 ; k < pima->samplesperblock ; k ++)
|
||||
{ step = ima_step_size [stepindx] ;
|
||||
|
||||
bytecode = pima->samples [pima->channels * k + chan] ;
|
||||
|
||||
stepindx += ima_indx_adjust [bytecode] ;
|
||||
stepindx = clamp_ima_step_index (stepindx) ;
|
||||
|
||||
diff = step >> 3 ;
|
||||
if (bytecode & 1) diff += step >> 2 ;
|
||||
if (bytecode & 2) diff += step >> 1 ;
|
||||
if (bytecode & 4) diff += step ;
|
||||
if (bytecode & 8) diff = -diff ;
|
||||
|
||||
predictor += diff ;
|
||||
if (predictor < -32768)
|
||||
predictor = -32768 ;
|
||||
else if (predictor > 32767)
|
||||
predictor = 32767 ;
|
||||
|
||||
pima->samples [pima->channels * k + chan] = predictor ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* aiff_ima_decode_block */
|
||||
|
||||
static int
|
||||
aiff_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ int chan, k, step, diff, vpdiff, blockindx, indx ;
|
||||
short bytecode, mask ;
|
||||
|
||||
/* Encode the block header. */
|
||||
for (chan = 0 ; chan < pima->channels ; chan ++)
|
||||
{ blockindx = chan * pima->blocksize ;
|
||||
|
||||
pima->block [blockindx] = (pima->samples [chan] >> 8) & 0xFF ;
|
||||
pima->block [blockindx + 1] = (pima->samples [chan] & 0x80) + (pima->stepindx [chan] & 0x7F) ;
|
||||
|
||||
pima->previous [chan] = pima->samples [chan] ;
|
||||
} ;
|
||||
|
||||
/* Encode second and later samples for every block as a 4 bit value. */
|
||||
for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
|
||||
{ chan = (pima->channels > 1) ? (k % 2) : 0 ;
|
||||
|
||||
diff = pima->samples [k] - pima->previous [chan] ;
|
||||
|
||||
bytecode = 0 ;
|
||||
step = ima_step_size [pima->stepindx [chan]] ;
|
||||
vpdiff = step >> 3 ;
|
||||
if (diff < 0)
|
||||
{ bytecode = 8 ;
|
||||
diff = -diff ;
|
||||
} ;
|
||||
mask = 4 ;
|
||||
while (mask)
|
||||
{ if (diff >= step)
|
||||
{ bytecode |= mask ;
|
||||
diff -= step ;
|
||||
vpdiff += step ;
|
||||
} ;
|
||||
step >>= 1 ;
|
||||
mask >>= 1 ;
|
||||
} ;
|
||||
|
||||
if (bytecode & 8)
|
||||
pima->previous [chan] -= vpdiff ;
|
||||
else
|
||||
pima->previous [chan] += vpdiff ;
|
||||
|
||||
if (pima->previous [chan] > 32767)
|
||||
pima->previous [chan] = 32767 ;
|
||||
else if (pima->previous [chan] < -32768)
|
||||
pima->previous [chan] = -32768 ;
|
||||
|
||||
pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
|
||||
|
||||
pima->stepindx [chan] = clamp_ima_step_index (pima->stepindx [chan]) ;
|
||||
pima->samples [k] = bytecode ;
|
||||
} ;
|
||||
|
||||
/* Pack the 4 bit encoded samples. */
|
||||
|
||||
for (chan = 0 ; chan < pima->channels ; chan ++)
|
||||
{ for (indx = pima->channels ; indx < pima->channels * pima->samplesperblock ; indx += 2 * pima->channels)
|
||||
{ blockindx = chan * pima->blocksize + 2 + indx / 2 ;
|
||||
|
||||
pima->block [blockindx] = pima->samples [indx] & 0x0F ;
|
||||
pima->block [blockindx] |= (pima->samples [indx + chan] << 4) & 0xF0 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
|
||||
if ((k = psf_fwrite (pima->block, 1, pima->channels * pima->blocksize, psf)) != pima->channels * pima->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->channels * pima->blocksize) ;
|
||||
|
||||
memset (pima->samples, 0, pima->channels * pima->samplesperblock * sizeof (short)) ;
|
||||
pima->samplecount = 0 ;
|
||||
pima->blockcount ++ ;
|
||||
|
||||
return 1 ;
|
||||
} /* aiff_ima_encode_block */
|
||||
|
||||
static int
|
||||
wav_w64_ima_decode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ int chan, k, predictor, blockindx, indx, indxstart, diff ;
|
||||
short step, bytecode, stepindx [2] ;
|
||||
|
||||
pima->blockcount ++ ;
|
||||
pima->samplecount = 0 ;
|
||||
|
||||
if (pima->blockcount > pima->blocks)
|
||||
{ memset (pima->samples, 0, pima->samplesperblock * pima->channels * sizeof (short)) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pima->blocksize) ;
|
||||
|
||||
/* Read and check the block header. */
|
||||
|
||||
for (chan = 0 ; chan < pima->channels ; chan++)
|
||||
{ predictor = pima->block [chan*4] | (pima->block [chan*4+1] << 8) ;
|
||||
if (predictor & 0x8000)
|
||||
predictor -= 0x10000 ;
|
||||
|
||||
stepindx [chan] = pima->block [chan*4+2] ;
|
||||
stepindx [chan] = clamp_ima_step_index (stepindx [chan]) ;
|
||||
|
||||
|
||||
if (pima->block [chan*4+3] != 0)
|
||||
psf_log_printf (psf, "IMA ADPCM synchronisation error.\n") ;
|
||||
|
||||
pima->samples [chan] = predictor ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Pull apart the packed 4 bit samples and store them in their
|
||||
** correct sample positions.
|
||||
*/
|
||||
|
||||
blockindx = 4 * pima->channels ;
|
||||
|
||||
indxstart = pima->channels ;
|
||||
while (blockindx < pima->blocksize)
|
||||
{ for (chan = 0 ; chan < pima->channels ; chan++)
|
||||
{ indx = indxstart + chan ;
|
||||
for (k = 0 ; k < 4 ; k++)
|
||||
{ bytecode = pima->block [blockindx++] ;
|
||||
pima->samples [indx] = bytecode & 0x0F ;
|
||||
indx += pima->channels ;
|
||||
pima->samples [indx] = (bytecode >> 4) & 0x0F ;
|
||||
indx += pima->channels ;
|
||||
} ;
|
||||
} ;
|
||||
indxstart += 8 * pima->channels ;
|
||||
} ;
|
||||
|
||||
/* Decode the encoded 4 bit samples. */
|
||||
|
||||
for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
|
||||
{ chan = (pima->channels > 1) ? (k % 2) : 0 ;
|
||||
|
||||
bytecode = pima->samples [k] & 0xF ;
|
||||
|
||||
step = ima_step_size [stepindx [chan]] ;
|
||||
predictor = pima->samples [k - pima->channels] ;
|
||||
|
||||
diff = step >> 3 ;
|
||||
if (bytecode & 1)
|
||||
diff += step >> 2 ;
|
||||
if (bytecode & 2)
|
||||
diff += step >> 1 ;
|
||||
if (bytecode & 4)
|
||||
diff += step ;
|
||||
if (bytecode & 8)
|
||||
diff = -diff ;
|
||||
|
||||
predictor += diff ;
|
||||
|
||||
if (predictor > 32767)
|
||||
predictor = 32767 ;
|
||||
else if (predictor < -32768)
|
||||
predictor = -32768 ;
|
||||
|
||||
stepindx [chan] += ima_indx_adjust [bytecode] ;
|
||||
stepindx [chan] = clamp_ima_step_index (stepindx [chan]) ;
|
||||
|
||||
pima->samples [k] = predictor ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* wav_w64_ima_decode_block */
|
||||
|
||||
static int
|
||||
wav_w64_ima_encode_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima)
|
||||
{ int chan, k, step, diff, vpdiff, blockindx, indx, indxstart ;
|
||||
short bytecode, mask ;
|
||||
|
||||
/* Encode the block header. */
|
||||
for (chan = 0 ; chan < pima->channels ; chan++)
|
||||
{ pima->block [chan*4] = pima->samples [chan] & 0xFF ;
|
||||
pima->block [chan*4+1] = (pima->samples [chan] >> 8) & 0xFF ;
|
||||
|
||||
pima->block [chan*4+2] = pima->stepindx [chan] ;
|
||||
pima->block [chan*4+3] = 0 ;
|
||||
|
||||
pima->previous [chan] = pima->samples [chan] ;
|
||||
} ;
|
||||
|
||||
/* Encode the samples as 4 bit. */
|
||||
|
||||
for (k = pima->channels ; k < (pima->samplesperblock * pima->channels) ; k ++)
|
||||
{ chan = (pima->channels > 1) ? (k % 2) : 0 ;
|
||||
|
||||
diff = pima->samples [k] - pima->previous [chan] ;
|
||||
|
||||
bytecode = 0 ;
|
||||
step = ima_step_size [pima->stepindx [chan]] ;
|
||||
vpdiff = step >> 3 ;
|
||||
if (diff < 0)
|
||||
{ bytecode = 8 ;
|
||||
diff = -diff ;
|
||||
} ;
|
||||
mask = 4 ;
|
||||
while (mask)
|
||||
{ if (diff >= step)
|
||||
{ bytecode |= mask ;
|
||||
diff -= step ;
|
||||
vpdiff += step ;
|
||||
} ;
|
||||
step >>= 1 ;
|
||||
mask >>= 1 ;
|
||||
} ;
|
||||
|
||||
if (bytecode & 8)
|
||||
pima->previous [chan] -= vpdiff ;
|
||||
else
|
||||
pima->previous [chan] += vpdiff ;
|
||||
|
||||
if (pima->previous [chan] > 32767)
|
||||
pima->previous [chan] = 32767 ;
|
||||
else if (pima->previous [chan] < -32768)
|
||||
pima->previous [chan] = -32768 ;
|
||||
|
||||
pima->stepindx [chan] += ima_indx_adjust [bytecode] ;
|
||||
pima->stepindx [chan] = clamp_ima_step_index (pima->stepindx [chan]) ;
|
||||
|
||||
pima->samples [k] = bytecode ;
|
||||
} ;
|
||||
|
||||
/* Pack the 4 bit encoded samples. */
|
||||
|
||||
blockindx = 4 * pima->channels ;
|
||||
|
||||
indxstart = pima->channels ;
|
||||
while (blockindx < pima->blocksize)
|
||||
{ for (chan = 0 ; chan < pima->channels ; chan++)
|
||||
{ indx = indxstart + chan ;
|
||||
for (k = 0 ; k < 4 ; k++)
|
||||
{ pima->block [blockindx] = pima->samples [indx] & 0x0F ;
|
||||
indx += pima->channels ;
|
||||
pima->block [blockindx] |= (pima->samples [indx] << 4) & 0xF0 ;
|
||||
indx += pima->channels ;
|
||||
blockindx ++ ;
|
||||
} ;
|
||||
} ;
|
||||
indxstart += 8 * pima->channels ;
|
||||
} ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
|
||||
if ((k = psf_fwrite (pima->block, 1, pima->blocksize, psf)) != pima->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pima->blocksize) ;
|
||||
|
||||
memset (pima->samples, 0, pima->samplesperblock * sizeof (short)) ;
|
||||
pima->samplecount = 0 ;
|
||||
pima->blockcount ++ ;
|
||||
|
||||
return 1 ;
|
||||
} /* wav_w64_ima_encode_block */
|
||||
|
||||
static int
|
||||
ima_read_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ if (pima->blockcount >= pima->blocks && pima->samplecount >= pima->samplesperblock)
|
||||
{ memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
if (pima->samplecount >= pima->samplesperblock)
|
||||
pima->decode_block (psf, pima) ;
|
||||
|
||||
count = (pima->samplesperblock - pima->samplecount) * pima->channels ;
|
||||
count = (len - indx > count) ? count : len - indx ;
|
||||
|
||||
memcpy (&(ptr [indx]), &(pima->samples [pima->samplecount * pima->channels]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pima->samplecount += count / pima->channels ;
|
||||
total = indx ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_read_block */
|
||||
|
||||
static sf_count_t
|
||||
ima_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
int readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = ima_read_block (psf, pima, ptr, readcount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_read_s */
|
||||
|
||||
static sf_count_t
|
||||
ima_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = ima_read_block (psf, pima, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = ((int) sptr [k]) << 16 ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_read_i */
|
||||
|
||||
static sf_count_t
|
||||
ima_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = ima_read_block (psf, pima, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (float) (sptr [k]) ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_read_f */
|
||||
|
||||
static sf_count_t
|
||||
ima_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
count = ima_read_block (psf, pima, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (sptr [k]) ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_read_d */
|
||||
|
||||
static sf_count_t
|
||||
ima_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
int newblock, newsample ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->datalength < 0 || psf->dataoffset < 0)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
if (offset == 0)
|
||||
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
pima->blockcount = 0 ;
|
||||
pima->decode_block (psf, pima) ;
|
||||
pima->samplecount = 0 ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (offset < 0 || offset > pima->blocks * pima->samplesperblock)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
newblock = offset / pima->samplesperblock ;
|
||||
newsample = offset % pima->samplesperblock ;
|
||||
|
||||
if (mode == SFM_READ)
|
||||
{ psf_fseek (psf, psf->dataoffset + newblock * pima->blocksize, SEEK_SET) ;
|
||||
pima->blockcount = newblock ;
|
||||
pima->decode_block (psf, pima) ;
|
||||
pima->samplecount = newsample ;
|
||||
}
|
||||
else
|
||||
{ /* What to do about write??? */
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
return newblock * pima->samplesperblock + newsample ;
|
||||
} /* ima_seek */
|
||||
|
||||
/*==========================================================================================
|
||||
** IMA ADPCM Write Functions.
|
||||
*/
|
||||
|
||||
static int
|
||||
ima_writer_init (SF_PRIVATE *psf, int blockalign)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
int samplesperblock ;
|
||||
unsigned int pimasize ;
|
||||
|
||||
if (psf->file.mode != SFM_WRITE)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
samplesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
|
||||
|
||||
pimasize = sizeof (IMA_ADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
|
||||
|
||||
if ((pima = calloc (1, pimasize)) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
psf->codec_data = (void*) pima ;
|
||||
|
||||
pima->channels = psf->sf.channels ;
|
||||
pima->blocksize = blockalign ;
|
||||
pima->samplesperblock = samplesperblock ;
|
||||
|
||||
pima->block = (unsigned char*) pima->data ;
|
||||
pima->samples = (short*) (pima->data + blockalign) ;
|
||||
|
||||
pima->samplecount = 0 ;
|
||||
|
||||
switch (SF_CONTAINER (psf->sf.format))
|
||||
{ case SF_FORMAT_WAV :
|
||||
case SF_FORMAT_W64 :
|
||||
pima->encode_block = wav_w64_ima_encode_block ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_AIFF :
|
||||
pima->encode_block = aiff_ima_encode_block ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "ima_reader_init: bad psf->sf.format\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->write_short = ima_write_s ;
|
||||
psf->write_int = ima_write_i ;
|
||||
psf->write_float = ima_write_f ;
|
||||
psf->write_double = ima_write_d ;
|
||||
|
||||
return 0 ;
|
||||
} /* ima_writer_init */
|
||||
|
||||
/*==========================================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
ima_write_block (SF_PRIVATE *psf, IMA_ADPCM_PRIVATE *pima, const short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ count = (pima->samplesperblock - pima->samplecount) * pima->channels ;
|
||||
|
||||
if (count > len - indx)
|
||||
count = len - indx ;
|
||||
|
||||
memcpy (&(pima->samples [pima->samplecount * pima->channels]), &(ptr [total]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pima->samplecount += count / pima->channels ;
|
||||
total = indx ;
|
||||
|
||||
if (pima->samplecount >= pima->samplesperblock)
|
||||
pima->encode_block (psf, pima) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_write_block */
|
||||
|
||||
static sf_count_t
|
||||
ima_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
int writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = ima_write_block (psf, pima, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_write_s */
|
||||
|
||||
static sf_count_t
|
||||
ima_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = ima_write_block (psf, pima, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_write_i */
|
||||
|
||||
static sf_count_t
|
||||
ima_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrintf (normfact * ptr [total + k]) ;
|
||||
count = ima_write_block (psf, pima, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_write_f */
|
||||
|
||||
static sf_count_t
|
||||
ima_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ IMA_ADPCM_PRIVATE *pima ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pima = (IMA_ADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : (int) len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrint (normfact * ptr [total + k]) ;
|
||||
count = ima_write_block (psf, pima, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* ima_write_d */
|
||||
|
||||
297
project/jni/sndfile/src/ima_oki_adpcm.c
Normal file
297
project/jni/sndfile/src/ima_oki_adpcm.c
Normal file
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (c) 2007 <robs@users.sourceforge.net>
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or (at
|
||||
** your option) any later version.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful, but
|
||||
** WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
** General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public License
|
||||
** along with this library. If not, write to the Free Software Foundation,
|
||||
** Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
|
||||
*/
|
||||
|
||||
/* ADPCM: IMA, OKI <==> 16-bit PCM. */
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* Set up for libsndfile environment: */
|
||||
#include "common.h"
|
||||
|
||||
#include "ima_oki_adpcm.h"
|
||||
|
||||
#define MIN_SAMPLE -0x8000
|
||||
#define MAX_SAMPLE 0x7fff
|
||||
|
||||
static int const ima_steps [] = /* ~16-bit precision */
|
||||
{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
|
||||
50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 173, 190, 209, 230,
|
||||
253, 279, 307, 337, 371, 408, 449, 494, 544, 598, 658, 724, 796, 876, 963,
|
||||
1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024, 3327,
|
||||
3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493, 10442,
|
||||
11487, 12635, 13899, 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
|
||||
32767
|
||||
} ;
|
||||
|
||||
static int const oki_steps [] = /* ~12-bit precision */
|
||||
{ 256, 272, 304, 336, 368, 400, 448, 496, 544, 592, 656, 720, 800, 880, 960,
|
||||
1056, 1168, 1280, 1408, 1552, 1712, 1888, 2080, 2288, 2512, 2768, 3040, 3344,
|
||||
3680, 4048, 4464, 4912, 5392, 5936, 6528, 7184, 7904, 8704, 9568, 10528,
|
||||
11584, 12736, 14016, 15408, 16960, 18656, 20512, 22576, 24832
|
||||
} ;
|
||||
|
||||
static int const step_changes [] = { -1, -1, -1, -1, 2, 4, 6, 8 } ;
|
||||
|
||||
void
|
||||
ima_oki_adpcm_init (IMA_OKI_ADPCM * state, IMA_OKI_ADPCM_TYPE type)
|
||||
{
|
||||
memset (state, 0, sizeof (*state)) ;
|
||||
|
||||
if (type == IMA_OKI_ADPCM_TYPE_IMA)
|
||||
{ state->max_step_index = ARRAY_LEN (ima_steps) - 1 ;
|
||||
state->steps = ima_steps ;
|
||||
state->mask = (~0) ;
|
||||
}
|
||||
else
|
||||
{ state->max_step_index = ARRAY_LEN (oki_steps) - 1 ;
|
||||
state->steps = oki_steps ;
|
||||
state->mask = (~0) << 4 ;
|
||||
} ;
|
||||
|
||||
} /* ima_oki_adpcm_init */
|
||||
|
||||
|
||||
int
|
||||
adpcm_decode (IMA_OKI_ADPCM * state, int code)
|
||||
{ int s ;
|
||||
|
||||
s = ((code & 7) << 1) | 1 ;
|
||||
s = ((state->steps [state->step_index] * s) >> 3) & state->mask ;
|
||||
|
||||
if (code & 8)
|
||||
s = -s ;
|
||||
s += state->last_output ;
|
||||
|
||||
if (s < MIN_SAMPLE || s > MAX_SAMPLE)
|
||||
{ int grace ;
|
||||
|
||||
grace = (state->steps [state->step_index] >> 3) & state->mask ;
|
||||
|
||||
if (s < MIN_SAMPLE - grace || s > MAX_SAMPLE + grace)
|
||||
state->errors ++ ;
|
||||
|
||||
s = s < MIN_SAMPLE ? MIN_SAMPLE : MAX_SAMPLE ;
|
||||
} ;
|
||||
|
||||
state->step_index += step_changes [code & 7] ;
|
||||
state->step_index = SF_MIN (SF_MAX (state->step_index, 0), state->max_step_index) ;
|
||||
state->last_output = s ;
|
||||
|
||||
return s ;
|
||||
} /* adpcm_decode */
|
||||
|
||||
int
|
||||
adpcm_encode (IMA_OKI_ADPCM * state, int sample)
|
||||
{ int delta, sign = 0, code ;
|
||||
|
||||
delta = sample - state->last_output ;
|
||||
|
||||
if (delta < 0)
|
||||
{ sign = 8 ;
|
||||
delta = -delta ;
|
||||
} ;
|
||||
|
||||
code = 4 * delta / state->steps [state->step_index] ;
|
||||
code = sign | SF_MIN (code, 7) ;
|
||||
adpcm_decode (state, code) ; /* Update encoder state */
|
||||
|
||||
return code ;
|
||||
} /* adpcm_encode */
|
||||
|
||||
|
||||
void
|
||||
ima_oki_adpcm_decode_block (IMA_OKI_ADPCM * state)
|
||||
{ unsigned char code ;
|
||||
int k ;
|
||||
|
||||
for (k = 0 ; k < state->code_count ; k++)
|
||||
{ code = state->codes [k] ;
|
||||
state->pcm [2 * k] = adpcm_decode (state, code >> 4) ;
|
||||
state->pcm [2 * k + 1] = adpcm_decode (state, code) ;
|
||||
} ;
|
||||
|
||||
state->pcm_count = 2 * k ;
|
||||
} /* ima_oki_adpcm_decode_block */
|
||||
|
||||
|
||||
void
|
||||
ima_oki_adpcm_encode_block (IMA_OKI_ADPCM * state)
|
||||
{ unsigned char code ;
|
||||
int k ;
|
||||
|
||||
/*
|
||||
** The codec expects an even number of input samples.
|
||||
**
|
||||
** Samples should always be passed in even length blocks. If the last block to
|
||||
** be encoded is odd length, extend that block by one zero valued sample.
|
||||
*/
|
||||
if (state->pcm_count % 2 == 1)
|
||||
state->pcm [state->pcm_count ++] = 0 ;
|
||||
|
||||
for (k = 0 ; k < state->pcm_count / 2 ; k++)
|
||||
{ code = adpcm_encode (state, state->pcm [2 * k]) << 4 ;
|
||||
code |= adpcm_encode (state, state->pcm [2 * k + 1]) ;
|
||||
state->codes [k] = code ;
|
||||
} ;
|
||||
|
||||
state->code_count = k ;
|
||||
} /* ima_oki_adpcm_encode_block */
|
||||
|
||||
|
||||
#ifdef TEST
|
||||
|
||||
static const unsigned char test_codes [] =
|
||||
{ 0x08, 0x08, 0x04, 0x7f, 0x72, 0xf7, 0x9f, 0x7c, 0xd7, 0xbc, 0x7a, 0xa7, 0xb8,
|
||||
0x4b, 0x0b, 0x38, 0xf6, 0x9d, 0x7a, 0xd7, 0xbc, 0x7a, 0xd7, 0xa8, 0x6c, 0x81,
|
||||
0x98, 0xe4, 0x0e, 0x7a, 0xd7, 0x9e, 0x7b, 0xc7, 0xab, 0x7a, 0x85, 0xc0, 0xb3,
|
||||
0x8f, 0x58, 0xd7, 0xad, 0x7a, 0xd7, 0xad, 0x7a, 0x87, 0xd0, 0x2b, 0x0e, 0x48,
|
||||
0xd7, 0xad, 0x78, 0xf7, 0xbc, 0x7a, 0xb7, 0xa8, 0x4b, 0x88, 0x18, 0xd5, 0x8d,
|
||||
0x6a, 0xa4, 0x98, 0x08, 0x00, 0x80, 0x88,
|
||||
} ;
|
||||
|
||||
static const short test_pcm [] =
|
||||
{ 32, 0, 32, 0, 32, 320, 880, -336, 2304, 4192, -992, 10128, 5360, -16352,
|
||||
30208, 2272, -31872, 14688, -7040, -32432, 14128, -1392, -15488, 22960,
|
||||
1232, -1584, 21488, -240, 2576, -15360, 960, -1152, -30032, 10320, 1008,
|
||||
-30032, 16528, 1008, -30032, 16528, -5200, -30592, 15968, 448, -30592,
|
||||
15968, 448, -2368, 30960, 3024, -80, 8384, 704, -1616, -29168, -1232, 1872,
|
||||
-32768, 13792, -1728, -32768, 13792, 4480, -32192, 14368, -7360, -32752,
|
||||
13808, -1712, -21456, 16992, 1472, -1344, 26848, -1088, 2016, -17728, 208,
|
||||
-2112, -32768, 1376, -1728, -32768, 13792, -1728, -32768, 13792, -1728,
|
||||
-32768, 13792, -1728, -32768, 13792, -1728, -4544, 32767, -1377, 1727,
|
||||
15823, -2113, 207, -27345, 591, -2513, -32768, 13792, -1728, -32768, 13792,
|
||||
10688, -31632, 14928, -6800, -32192, 14368, -1152, -20896, 17552, 2032,
|
||||
-784, 22288, 560, -2256, -4816, 2176, 64, -21120, 9920, 6816, -24224, 16128,
|
||||
608, -13488, 9584, 272, -2544, 16, -2304, -192, 1728, -16, 1568, 128, -1184,
|
||||
} ;
|
||||
|
||||
|
||||
static void
|
||||
test_oki_adpcm (void)
|
||||
{
|
||||
IMA_OKI_ADPCM adpcm ;
|
||||
unsigned char code ;
|
||||
int i, j ;
|
||||
|
||||
printf (" Testing encoder : ") ;
|
||||
fflush (stdout) ;
|
||||
|
||||
ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
|
||||
for (i = 0 ; i < ARRAY_LEN (test_codes) ; i++)
|
||||
for (j = 0, code = test_codes [i] ; j < 2 ; j++, code <<= 4)
|
||||
if (adpcm_decode (&adpcm, code >> 4) != test_pcm [2 * i + j])
|
||||
{ printf ("\n\nFail at i = %d, j = %d.\n\n", i, j) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
puts ("ok") ;
|
||||
|
||||
printf (" Testing decoder : ") ;
|
||||
fflush (stdout) ;
|
||||
|
||||
ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
|
||||
for (i = 0 ; i < ARRAY_LEN (test_pcm) ; i += j)
|
||||
{ code = adpcm_encode (&adpcm, test_pcm [i]) ;
|
||||
code = (code << 4) | adpcm_encode (&adpcm, test_pcm [i + 1]) ;
|
||||
if (code != test_codes [i / 2])
|
||||
{ printf ("\n\nFail at i = %d, %d should be %d\n\n", i, code, test_codes [i / 2]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
puts ("ok") ;
|
||||
} /* test_oki_adpcm */
|
||||
|
||||
static void
|
||||
test_oki_adpcm_block (void)
|
||||
{
|
||||
IMA_OKI_ADPCM adpcm ;
|
||||
int k ;
|
||||
|
||||
if (ARRAY_LEN (adpcm.pcm) < ARRAY_LEN (test_pcm))
|
||||
{ printf ("\n\nLine %d : ARRAY_LEN (adpcm->pcm) > ARRAY_LEN (test_pcm) (%d > %d).\n\n", __LINE__, ARRAY_LEN (adpcm.pcm), ARRAY_LEN (test_pcm)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
if (ARRAY_LEN (adpcm.codes) < ARRAY_LEN (test_codes))
|
||||
{ printf ("\n\nLine %d : ARRAY_LEN (adcodes->codes) > ARRAY_LEN (test_codes).n", __LINE__) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
printf (" Testing block encoder : ") ;
|
||||
fflush (stdout) ;
|
||||
|
||||
ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
|
||||
|
||||
memcpy (adpcm.pcm, test_pcm, sizeof (adpcm.pcm [0]) * ARRAY_LEN (test_pcm)) ;
|
||||
adpcm.pcm_count = ARRAY_LEN (test_pcm) ;
|
||||
adpcm.code_count = 13 ;
|
||||
|
||||
ima_oki_adpcm_encode_block (&adpcm) ;
|
||||
|
||||
if (adpcm.code_count * 2 != ARRAY_LEN (test_pcm))
|
||||
{ printf ("\n\nLine %d : %d * 2 != %d\n\n", __LINE__, adpcm.code_count * 2, ARRAY_LEN (test_pcm)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < ARRAY_LEN (test_codes) ; k++)
|
||||
if (adpcm.codes [k] != test_codes [k])
|
||||
{ printf ("\n\nLine %d : Fail at k = %d, %d should be %d\n\n", __LINE__, k, adpcm.codes [k], test_codes [k]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
puts ("ok") ;
|
||||
|
||||
printf (" Testing block decoder : ") ;
|
||||
fflush (stdout) ;
|
||||
|
||||
ima_oki_adpcm_init (&adpcm, IMA_OKI_ADPCM_TYPE_OKI) ;
|
||||
|
||||
memcpy (adpcm.codes, test_codes, sizeof (adpcm.codes [0]) * ARRAY_LEN (test_codes)) ;
|
||||
adpcm.code_count = ARRAY_LEN (test_codes) ;
|
||||
adpcm.pcm_count = 13 ;
|
||||
|
||||
ima_oki_adpcm_decode_block (&adpcm) ;
|
||||
|
||||
if (adpcm.pcm_count != 2 * ARRAY_LEN (test_codes))
|
||||
{ printf ("\n\nLine %d : %d * 2 != %d\n\n", __LINE__, adpcm.pcm_count, 2 * ARRAY_LEN (test_codes)) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < ARRAY_LEN (test_pcm) ; k++)
|
||||
if (adpcm.pcm [k] != test_pcm [k])
|
||||
{ printf ("\n\nLine %d : Fail at i = %d, %d should be %d.\n\n", __LINE__, k, adpcm.pcm [k], test_pcm [k]) ;
|
||||
exit (1) ;
|
||||
} ;
|
||||
|
||||
puts ("ok") ;
|
||||
} /* test_oki_adpcm_block */
|
||||
|
||||
int
|
||||
main (void)
|
||||
{
|
||||
test_oki_adpcm () ;
|
||||
test_oki_adpcm_block () ;
|
||||
|
||||
return 0 ;
|
||||
} /* main */
|
||||
|
||||
#endif
|
||||
54
project/jni/sndfile/src/ima_oki_adpcm.h
Normal file
54
project/jni/sndfile/src/ima_oki_adpcm.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
** Copyright (C) 2007-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (c) 2007 <robs@users.sourceforge.net>
|
||||
**
|
||||
** This library is free software; you can redistribute it and/or modify it
|
||||
** under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2 of the License, or (at
|
||||
** your option) any later version.
|
||||
**
|
||||
** This library is distributed in the hope that it will be useful, but
|
||||
** WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
|
||||
** General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser General Public License
|
||||
** along with this library. If not, write to the Free Software Foundation,
|
||||
** Fifth Floor, 51 Franklin Street, Boston, MA 02111-1301, USA.
|
||||
*/
|
||||
|
||||
/* ADPCM: IMA, OKI <==> 16-bit PCM. */
|
||||
|
||||
|
||||
#define IMA_OKI_ADPCM_CODE_LEN 256
|
||||
#define IMA_OKI_ADPCM_PCM_LEN (IMA_OKI_ADPCM_CODE_LEN *2)
|
||||
|
||||
typedef struct
|
||||
{
|
||||
/* private: */
|
||||
int mask ;
|
||||
int last_output ;
|
||||
int step_index ;
|
||||
int max_step_index ;
|
||||
int const * steps ;
|
||||
|
||||
/* public: */
|
||||
int errors ;
|
||||
int code_count, pcm_count ;
|
||||
|
||||
unsigned char codes [IMA_OKI_ADPCM_CODE_LEN] ;
|
||||
short pcm [IMA_OKI_ADPCM_PCM_LEN] ;
|
||||
} IMA_OKI_ADPCM ;
|
||||
|
||||
typedef enum
|
||||
{ IMA_OKI_ADPCM_TYPE_IMA,
|
||||
IMA_OKI_ADPCM_TYPE_OKI
|
||||
} IMA_OKI_ADPCM_TYPE ;
|
||||
|
||||
void ima_oki_adpcm_init (IMA_OKI_ADPCM * state, IMA_OKI_ADPCM_TYPE type) ;
|
||||
|
||||
int adpcm_decode (IMA_OKI_ADPCM * state, int /* 0..15 */ code) ;
|
||||
int adpcm_encode (IMA_OKI_ADPCM * state, int /* -32768..32767 */ sample) ;
|
||||
|
||||
void ima_oki_adpcm_decode_block (IMA_OKI_ADPCM * state) ;
|
||||
void ima_oki_adpcm_encode_block (IMA_OKI_ADPCM * state) ;
|
||||
300
project/jni/sndfile/src/interleave.c
Normal file
300
project/jni/sndfile/src/interleave.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfendian.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
|
||||
#define INTERLEAVE_CHANNELS 6
|
||||
|
||||
typedef struct
|
||||
{ double buffer [SF_BUFFER_LEN / sizeof (double)] ;
|
||||
|
||||
sf_count_t channel_len ;
|
||||
|
||||
sf_count_t (*read_short) (SF_PRIVATE*, short *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_int) (SF_PRIVATE*, int *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_float) (SF_PRIVATE*, float *ptr, sf_count_t len) ;
|
||||
sf_count_t (*read_double) (SF_PRIVATE*, double *ptr, sf_count_t len) ;
|
||||
|
||||
} INTERLEAVE_DATA ;
|
||||
|
||||
|
||||
|
||||
static sf_count_t interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t interleave_seek (SF_PRIVATE*, int mode, sf_count_t samples_from_start) ;
|
||||
|
||||
|
||||
|
||||
|
||||
int
|
||||
interleave_init (SF_PRIVATE *psf)
|
||||
{ INTERLEAVE_DATA *pdata ;
|
||||
|
||||
if (psf->file.mode != SFM_READ)
|
||||
return SFE_INTERLEAVE_MODE ;
|
||||
|
||||
if (psf->interleave)
|
||||
{ psf_log_printf (psf, "*** Weird, already have interleave.\n") ;
|
||||
return 666 ;
|
||||
} ;
|
||||
|
||||
/* Free this in sf_close() function. */
|
||||
if (! (pdata = malloc (sizeof (INTERLEAVE_DATA))))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
puts ("interleave_init") ;
|
||||
|
||||
psf->interleave = pdata ;
|
||||
|
||||
/* Save the existing methods. */
|
||||
pdata->read_short = psf->read_short ;
|
||||
pdata->read_int = psf->read_int ;
|
||||
pdata->read_float = psf->read_float ;
|
||||
pdata->read_double = psf->read_double ;
|
||||
|
||||
pdata->channel_len = psf->sf.frames * psf->bytewidth ;
|
||||
|
||||
/* Insert our new methods. */
|
||||
psf->read_short = interleave_read_short ;
|
||||
psf->read_int = interleave_read_int ;
|
||||
psf->read_float = interleave_read_float ;
|
||||
psf->read_double = interleave_read_double ;
|
||||
|
||||
psf->seek = interleave_seek ;
|
||||
|
||||
return 0 ;
|
||||
} /* pcm_interleave_init */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
interleave_read_short (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ INTERLEAVE_DATA *pdata ;
|
||||
sf_count_t offset, templen ;
|
||||
int chan, count, k ;
|
||||
short *inptr, *outptr ;
|
||||
|
||||
if (! (pdata = psf->interleave))
|
||||
return 0 ;
|
||||
|
||||
inptr = (short*) pdata->buffer ;
|
||||
|
||||
for (chan = 0 ; chan < psf->sf.channels ; chan++)
|
||||
{ outptr = ptr + chan ;
|
||||
|
||||
offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
|
||||
|
||||
if (psf_fseek (psf, offset, SEEK_SET) != offset)
|
||||
{ psf->error = SFE_INTERLEAVE_SEEK ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
templen = len / psf->sf.channels ;
|
||||
|
||||
while (templen > 0)
|
||||
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short))
|
||||
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (short) ;
|
||||
else
|
||||
count = (int) templen ;
|
||||
|
||||
if (pdata->read_short (psf, inptr, count) != count)
|
||||
{ psf->error = SFE_INTERLEAVE_READ ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < count ; k++)
|
||||
{ *outptr = inptr [k] ;
|
||||
outptr += psf->sf.channels ;
|
||||
} ;
|
||||
|
||||
templen -= count ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* interleave_read_short */
|
||||
|
||||
static sf_count_t
|
||||
interleave_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ INTERLEAVE_DATA *pdata ;
|
||||
sf_count_t offset, templen ;
|
||||
int chan, count, k ;
|
||||
int *inptr, *outptr ;
|
||||
|
||||
if (! (pdata = psf->interleave))
|
||||
return 0 ;
|
||||
|
||||
inptr = (int*) pdata->buffer ;
|
||||
|
||||
for (chan = 0 ; chan < psf->sf.channels ; chan++)
|
||||
{ outptr = ptr + chan ;
|
||||
|
||||
offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
|
||||
|
||||
if (psf_fseek (psf, offset, SEEK_SET) != offset)
|
||||
{ psf->error = SFE_INTERLEAVE_SEEK ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
templen = len / psf->sf.channels ;
|
||||
|
||||
while (templen > 0)
|
||||
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int))
|
||||
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (int) ;
|
||||
else
|
||||
count = (int) templen ;
|
||||
|
||||
if (pdata->read_int (psf, inptr, count) != count)
|
||||
{ psf->error = SFE_INTERLEAVE_READ ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < count ; k++)
|
||||
{ *outptr = inptr [k] ;
|
||||
outptr += psf->sf.channels ;
|
||||
} ;
|
||||
|
||||
templen -= count ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* interleave_read_int */
|
||||
|
||||
static sf_count_t
|
||||
interleave_read_float (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ INTERLEAVE_DATA *pdata ;
|
||||
sf_count_t offset, templen ;
|
||||
int chan, count, k ;
|
||||
float *inptr, *outptr ;
|
||||
|
||||
if (! (pdata = psf->interleave))
|
||||
return 0 ;
|
||||
|
||||
inptr = (float*) pdata->buffer ;
|
||||
|
||||
for (chan = 0 ; chan < psf->sf.channels ; chan++)
|
||||
{ outptr = ptr + chan ;
|
||||
|
||||
offset = psf->dataoffset + pdata->channel_len * chan + psf->read_current * psf->bytewidth ;
|
||||
|
||||
/*-printf ("chan : %d read_current : %6lld offset : %6lld\n", chan, psf->read_current, offset) ;-*/
|
||||
|
||||
if (psf_fseek (psf, offset, SEEK_SET) != offset)
|
||||
{ psf->error = SFE_INTERLEAVE_SEEK ;
|
||||
/*-puts ("interleave_seek error") ; exit (1) ;-*/
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
templen = len / psf->sf.channels ;
|
||||
|
||||
while (templen > 0)
|
||||
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float))
|
||||
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (float) ;
|
||||
else
|
||||
count = (int) templen ;
|
||||
|
||||
if (pdata->read_float (psf, inptr, count) != count)
|
||||
{ psf->error = SFE_INTERLEAVE_READ ;
|
||||
/*-puts ("interleave_read error") ; exit (1) ;-*/
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < count ; k++)
|
||||
{ *outptr = inptr [k] ;
|
||||
outptr += psf->sf.channels ;
|
||||
} ;
|
||||
|
||||
templen -= count ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* interleave_read_float */
|
||||
|
||||
static sf_count_t
|
||||
interleave_read_double (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ INTERLEAVE_DATA *pdata ;
|
||||
sf_count_t offset, templen ;
|
||||
int chan, count, k ;
|
||||
double *inptr, *outptr ;
|
||||
|
||||
if (! (pdata = psf->interleave))
|
||||
return 0 ;
|
||||
|
||||
inptr = (double*) pdata->buffer ;
|
||||
|
||||
for (chan = 0 ; chan < psf->sf.channels ; chan++)
|
||||
{ outptr = ptr + chan ;
|
||||
|
||||
offset = psf->dataoffset + chan * psf->bytewidth * psf->read_current ;
|
||||
|
||||
if (psf_fseek (psf, offset, SEEK_SET) != offset)
|
||||
{ psf->error = SFE_INTERLEAVE_SEEK ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
templen = len / psf->sf.channels ;
|
||||
|
||||
while (templen > 0)
|
||||
{ if (templen > SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double))
|
||||
count = SIGNED_SIZEOF (pdata->buffer) / SIGNED_SIZEOF (double) ;
|
||||
else
|
||||
count = (int) templen ;
|
||||
|
||||
if (pdata->read_double (psf, inptr, count) != count)
|
||||
{ psf->error = SFE_INTERLEAVE_READ ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
for (k = 0 ; k < count ; k++)
|
||||
{ *outptr = inptr [k] ;
|
||||
outptr += psf->sf.channels ;
|
||||
} ;
|
||||
|
||||
templen -= count ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return len ;
|
||||
} /* interleave_read_double */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static sf_count_t
|
||||
interleave_seek (SF_PRIVATE *psf, int mode, sf_count_t samples_from_start)
|
||||
{ psf = psf ; mode = mode ;
|
||||
|
||||
/*
|
||||
** Do nothing here. This is a place holder to prevent the default
|
||||
** seek function from being called.
|
||||
*/
|
||||
|
||||
return samples_from_start ;
|
||||
} /* interleave_seek */
|
||||
|
||||
322
project/jni/sndfile/src/ircam.c
Normal file
322
project/jni/sndfile/src/ircam.c
Normal file
@@ -0,0 +1,322 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
/* The IRCAM magic number is weird in that one byte in the number can have
|
||||
** values of 0x1, 0x2, 0x03 or 0x04. Hence the need for a marker and a mask.
|
||||
*/
|
||||
|
||||
#define IRCAM_BE_MASK (MAKE_MARKER (0xFF, 0xFF, 0x00, 0xFF))
|
||||
#define IRCAM_BE_MARKER (MAKE_MARKER (0x64, 0xA3, 0x00, 0x00))
|
||||
|
||||
#define IRCAM_LE_MASK (MAKE_MARKER (0xFF, 0x00, 0xFF, 0xFF))
|
||||
#define IRCAM_LE_MARKER (MAKE_MARKER (0x00, 0x00, 0xA3, 0x64))
|
||||
|
||||
#define IRCAM_02B_MARKER (MAKE_MARKER (0x64, 0xA3, 0x02, 0x00))
|
||||
#define IRCAM_03L_MARKER (MAKE_MARKER (0x64, 0xA3, 0x03, 0x00))
|
||||
|
||||
#define IRCAM_DATA_OFFSET (1024)
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ IRCAM_PCM_16 = 0x00002,
|
||||
IRCAM_FLOAT = 0x00004,
|
||||
IRCAM_ALAW = 0x10001,
|
||||
IRCAM_ULAW = 0x20001,
|
||||
IRCAM_PCM_32 = 0x40004
|
||||
} ;
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int ircam_close (SF_PRIVATE *psf) ;
|
||||
static int ircam_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int ircam_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
static int get_encoding (int subformat) ;
|
||||
|
||||
static const char* get_encoding_str (int encoding) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
ircam_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = SFE_NO_ERROR ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = ircam_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_IRCAM)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)
|
||||
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf->dataoffset = IRCAM_DATA_OFFSET ;
|
||||
|
||||
if ((error = ircam_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
|
||||
psf->write_header = ircam_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = ircam_close ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_ULAW : /* 8-bit Ulaw encoding. */
|
||||
error = ulaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW : /* 8-bit Alaw encoding. */
|
||||
error = alaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT : /* 32-bit linear PCM. */
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* ircam_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
ircam_read_header (SF_PRIVATE *psf)
|
||||
{ unsigned int marker, encoding ;
|
||||
float samplerate ;
|
||||
int error = SFE_NO_ERROR ;
|
||||
|
||||
psf_binheader_readf (psf, "epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ;
|
||||
|
||||
if (((marker & IRCAM_BE_MASK) != IRCAM_BE_MARKER) && ((marker & IRCAM_LE_MASK) != IRCAM_LE_MARKER))
|
||||
{ psf_log_printf (psf, "marker: 0x%X\n", marker) ;
|
||||
return SFE_IRCAM_NO_MARKER ;
|
||||
} ;
|
||||
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
if (psf->sf.channels > 256)
|
||||
{ psf_binheader_readf (psf, "Epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ;
|
||||
|
||||
/* Sanity checking for endian-ness detection. */
|
||||
if (psf->sf.channels > 256)
|
||||
{ psf_log_printf (psf, "marker: 0x%X\n", marker) ;
|
||||
return SFE_IRCAM_BAD_CHANNELS ;
|
||||
} ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "marker: 0x%X\n", marker) ;
|
||||
|
||||
psf->sf.samplerate = (int) samplerate ;
|
||||
|
||||
psf_log_printf (psf, " Sample Rate : %d\n"
|
||||
" Channels : %d\n"
|
||||
" Encoding : %X => %s\n", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ;
|
||||
|
||||
switch (encoding)
|
||||
{ case IRCAM_PCM_16 :
|
||||
psf->bytewidth = 2 ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_16 ;
|
||||
break ;
|
||||
|
||||
case IRCAM_PCM_32 :
|
||||
psf->bytewidth = 4 ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_32 ;
|
||||
break ;
|
||||
|
||||
case IRCAM_FLOAT :
|
||||
psf->bytewidth = 4 ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_FLOAT ;
|
||||
break ;
|
||||
|
||||
case IRCAM_ALAW :
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ALAW ;
|
||||
break ;
|
||||
|
||||
case IRCAM_ULAW :
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ULAW ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
error = SFE_IRCAM_UNKNOWN_FORMAT ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
psf->sf.format |= SF_ENDIAN_BIG ;
|
||||
else
|
||||
psf->sf.format |= SF_ENDIAN_LITTLE ;
|
||||
|
||||
if (error)
|
||||
return error ;
|
||||
|
||||
psf->dataoffset = IRCAM_DATA_OFFSET ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->sf.frames == 0 && psf->blockwidth)
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
|
||||
psf_log_printf (psf, " Samples : %d\n", psf->sf.frames) ;
|
||||
|
||||
psf_binheader_readf (psf, "p", IRCAM_DATA_OFFSET) ;
|
||||
|
||||
return 0 ;
|
||||
} /* ircam_read_header */
|
||||
|
||||
static int
|
||||
ircam_close (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "close\n") ;
|
||||
|
||||
return 0 ;
|
||||
} /* ircam_close */
|
||||
|
||||
static int
|
||||
ircam_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
|
||||
{ int encoding ;
|
||||
float samplerate ;
|
||||
sf_count_t current ;
|
||||
|
||||
if (psf->pipeoffset > 0)
|
||||
return 0 ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
/* This also sets psf->endian. */
|
||||
encoding = get_encoding (SF_CODEC (psf->sf.format)) ;
|
||||
|
||||
if (encoding == 0)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
samplerate = psf->sf.samplerate ;
|
||||
|
||||
switch (psf->endian)
|
||||
{ case SF_ENDIAN_BIG :
|
||||
psf_binheader_writef (psf, "Emf", IRCAM_02B_MARKER, samplerate) ;
|
||||
psf_binheader_writef (psf, "E44", psf->sf.channels, encoding) ;
|
||||
break ;
|
||||
|
||||
case SF_ENDIAN_LITTLE :
|
||||
psf_binheader_writef (psf, "emf", IRCAM_03L_MARKER, samplerate) ;
|
||||
psf_binheader_writef (psf, "e44", psf->sf.channels, encoding) ;
|
||||
break ;
|
||||
|
||||
default : return SFE_BAD_OPEN_FORMAT ;
|
||||
} ;
|
||||
|
||||
psf_binheader_writef (psf, "z", (size_t) (IRCAM_DATA_OFFSET - psf->headindex)) ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* ircam_write_header */
|
||||
|
||||
static int
|
||||
get_encoding (int subformat)
|
||||
{ switch (subformat)
|
||||
{ case SF_FORMAT_PCM_16 : return IRCAM_PCM_16 ;
|
||||
case SF_FORMAT_PCM_32 : return IRCAM_PCM_32 ;
|
||||
|
||||
case SF_FORMAT_FLOAT : return IRCAM_FLOAT ;
|
||||
|
||||
case SF_FORMAT_ULAW : return IRCAM_ULAW ;
|
||||
case SF_FORMAT_ALAW : return IRCAM_ALAW ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* get_encoding */
|
||||
|
||||
static const char*
|
||||
get_encoding_str (int encoding)
|
||||
{ switch (encoding)
|
||||
{ case IRCAM_PCM_16 : return "16 bit PCM" ;
|
||||
case IRCAM_FLOAT : return "32 bit float" ;
|
||||
case IRCAM_ALAW : return "A law" ;
|
||||
case IRCAM_ULAW : return "u law" ;
|
||||
case IRCAM_PCM_32 : return "32 bit PCM" ;
|
||||
} ;
|
||||
return "Unknown encoding" ;
|
||||
} /* get_encoding_str */
|
||||
|
||||
45
project/jni/sndfile/src/macbinary3.c
Normal file
45
project/jni/sndfile/src/macbinary3.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (OS_IS_MACOSX == 1)
|
||||
|
||||
int
|
||||
macbinary3_open (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* macbinary3_open */
|
||||
|
||||
#else
|
||||
|
||||
int
|
||||
macbinary3_open (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* macbinary3_open */
|
||||
|
||||
#endif /* OS_IS_MACOSX */
|
||||
|
||||
51
project/jni/sndfile/src/macos.c
Normal file
51
project/jni/sndfile/src/macos.c
Normal file
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
** Copyright (C) 2003-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ')
|
||||
|
||||
int
|
||||
macos_guess_file_type (SF_PRIVATE * psf, const char *filename)
|
||||
{ static char rsrc_name [1024] ;
|
||||
struct stat statbuf ;
|
||||
|
||||
snprintf (rsrc_name, sizeof (rsrc_name), "%s/rsrc", filename) ;
|
||||
|
||||
/* If there is no resource fork, just return. */
|
||||
if (stat (rsrc_name, &statbuf) != 0)
|
||||
{ psf_log_printf (psf, "No resource fork.\n") ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (statbuf.st_size == 0)
|
||||
{ psf_log_printf (psf, "Have zero size resource fork.\n") ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* macos_guess_file_type */
|
||||
|
||||
389
project/jni/sndfile/src/mat4.c
Normal file
389
project/jni/sndfile/src/mat4.c
Normal file
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Information on how to decode and encode this file was obtained in a PDF
|
||||
** file which I found on http://www.wotsit.org/.
|
||||
** Also did a lot of testing with GNU Octave but do not have access to
|
||||
** Matlab (tm) and so could not test it there.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define MAT4_BE_DOUBLE (MAKE_MARKER (0, 0, 0x03, 0xE8))
|
||||
#define MAT4_LE_DOUBLE (MAKE_MARKER (0, 0, 0, 0))
|
||||
|
||||
#define MAT4_BE_FLOAT (MAKE_MARKER (0, 0, 0x03, 0xF2))
|
||||
#define MAT4_LE_FLOAT (MAKE_MARKER (0x0A, 0, 0, 0))
|
||||
|
||||
#define MAT4_BE_PCM_32 (MAKE_MARKER (0, 0, 0x03, 0xFC))
|
||||
#define MAT4_LE_PCM_32 (MAKE_MARKER (0x14, 0, 0, 0))
|
||||
|
||||
#define MAT4_BE_PCM_16 (MAKE_MARKER (0, 0, 0x04, 0x06))
|
||||
#define MAT4_LE_PCM_16 (MAKE_MARKER (0x1E, 0, 0, 0))
|
||||
|
||||
/* Can't see any reason to ever implement this. */
|
||||
#define MAT4_BE_PCM_U8 (MAKE_MARKER (0, 0, 0x04, 0x1A))
|
||||
#define MAT4_LE_PCM_U8 (MAKE_MARKER (0x32, 0, 0, 0))
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int mat4_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int mat4_format_to_encoding (int format, int endian) ;
|
||||
|
||||
static int mat4_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int mat4_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
static const char * mat4_marker_to_str (int marker) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
mat4_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = mat4_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_MAT4)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if ((error = mat4_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
|
||||
psf->write_header = mat4_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = mat4_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
if (error)
|
||||
return error ;
|
||||
|
||||
return error ;
|
||||
} /* mat4_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
mat4_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
mat4_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* mat4_close */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
mat4_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ sf_count_t current ;
|
||||
int encoding ;
|
||||
double samplerate ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
encoding = mat4_format_to_encoding (SF_CODEC (psf->sf.format), psf->endian) ;
|
||||
|
||||
if (encoding == -1)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
/* Need sample rate as a double for writing to the header. */
|
||||
samplerate = psf->sf.samplerate ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
{ psf_binheader_writef (psf, "Em444", MAT4_BE_DOUBLE, 1, 1, 0) ;
|
||||
psf_binheader_writef (psf, "E4bd", 11, "samplerate", make_size_t (11), samplerate) ;
|
||||
psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
|
||||
psf_binheader_writef (psf, "E4b", 9, "wavedata", make_size_t (9)) ;
|
||||
}
|
||||
else if (psf->endian == SF_ENDIAN_LITTLE)
|
||||
{ psf_binheader_writef (psf, "em444", MAT4_LE_DOUBLE, 1, 1, 0) ;
|
||||
psf_binheader_writef (psf, "e4bd", 11, "samplerate", make_size_t (11), samplerate) ;
|
||||
psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
|
||||
psf_binheader_writef (psf, "e4b", 9, "wavedata", make_size_t (9)) ;
|
||||
}
|
||||
else
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* mat4_write_header */
|
||||
|
||||
static int
|
||||
mat4_read_header (SF_PRIVATE *psf)
|
||||
{ int marker, rows, cols, imag ;
|
||||
unsigned namesize ;
|
||||
double value ;
|
||||
const char *marker_str ;
|
||||
char name [64] ;
|
||||
|
||||
psf_binheader_readf (psf, "pm", 0, &marker) ;
|
||||
|
||||
/* MAT4 file must start with a double for the samplerate. */
|
||||
if (marker == MAT4_BE_DOUBLE)
|
||||
{ psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ;
|
||||
marker_str = "big endian double" ;
|
||||
}
|
||||
else if (marker == MAT4_LE_DOUBLE)
|
||||
{ psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ;
|
||||
marker_str = "little endian double" ;
|
||||
}
|
||||
else
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
psf_log_printf (psf, "GNU Octave 2.0 / MATLAB v4.2 format\nMarker : %s\n", marker_str) ;
|
||||
|
||||
psf_binheader_readf (psf, "444", &rows, &cols, &imag) ;
|
||||
|
||||
psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ;
|
||||
|
||||
psf_binheader_readf (psf, "4", &namesize) ;
|
||||
|
||||
if (namesize >= SIGNED_SIZEOF (name))
|
||||
return SFE_MAT4_BAD_NAME ;
|
||||
|
||||
psf_binheader_readf (psf, "b", name, namesize) ;
|
||||
name [namesize] = 0 ;
|
||||
|
||||
psf_log_printf (psf, " Name : %s\n", name) ;
|
||||
|
||||
psf_binheader_readf (psf, "d", &value) ;
|
||||
|
||||
snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " Value : %f\n", value) ;
|
||||
psf_log_printf (psf, psf->u.cbuf) ;
|
||||
|
||||
if ((rows != 1) || (cols != 1))
|
||||
return SFE_MAT4_NO_SAMPLERATE ;
|
||||
|
||||
psf->sf.samplerate = lrint (value) ;
|
||||
|
||||
/* Now write out the audio data. */
|
||||
|
||||
psf_binheader_readf (psf, "m", &marker) ;
|
||||
|
||||
psf_log_printf (psf, "Marker : %s\n", mat4_marker_to_str (marker)) ;
|
||||
|
||||
psf_binheader_readf (psf, "444", &rows, &cols, &imag) ;
|
||||
|
||||
psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ;
|
||||
|
||||
psf_binheader_readf (psf, "4", &namesize) ;
|
||||
|
||||
if (namesize >= SIGNED_SIZEOF (name))
|
||||
return SFE_MAT4_BAD_NAME ;
|
||||
|
||||
psf_binheader_readf (psf, "b", name, namesize) ;
|
||||
name [namesize] = 0 ;
|
||||
|
||||
psf_log_printf (psf, " Name : %s\n", name) ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
|
||||
if (rows == 0 && cols == 0)
|
||||
{ psf_log_printf (psf, "*** Error : zero channel count.\n") ;
|
||||
return SFE_CHANNEL_COUNT_ZERO ;
|
||||
} ;
|
||||
|
||||
psf->sf.channels = rows ;
|
||||
psf->sf.frames = cols ;
|
||||
|
||||
psf->sf.format = psf->endian | SF_FORMAT_MAT4 ;
|
||||
switch (marker)
|
||||
{ case MAT4_BE_DOUBLE :
|
||||
case MAT4_LE_DOUBLE :
|
||||
psf->sf.format |= SF_FORMAT_DOUBLE ;
|
||||
psf->bytewidth = 8 ;
|
||||
break ;
|
||||
|
||||
case MAT4_BE_FLOAT :
|
||||
case MAT4_LE_FLOAT :
|
||||
psf->sf.format |= SF_FORMAT_FLOAT ;
|
||||
psf->bytewidth = 4 ;
|
||||
break ;
|
||||
|
||||
case MAT4_BE_PCM_32 :
|
||||
case MAT4_LE_PCM_32 :
|
||||
psf->sf.format |= SF_FORMAT_PCM_32 ;
|
||||
psf->bytewidth = 4 ;
|
||||
break ;
|
||||
|
||||
case MAT4_BE_PCM_16 :
|
||||
case MAT4_LE_PCM_16 :
|
||||
psf->sf.format |= SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "*** Error : Bad marker %08X\n", marker) ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
if ((psf->filelength - psf->dataoffset) < psf->sf.channels * psf->sf.frames * psf->bytewidth)
|
||||
{ psf_log_printf (psf, "*** File seems to be truncated. %D <--> %D\n",
|
||||
psf->filelength - psf->dataoffset, psf->sf.channels * psf->sf.frames * psf->bytewidth) ;
|
||||
}
|
||||
else if ((psf->filelength - psf->dataoffset) > psf->sf.channels * psf->sf.frames * psf->bytewidth)
|
||||
psf->dataend = psf->dataoffset + rows * cols * psf->bytewidth ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset - psf->dataend ;
|
||||
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
return 0 ;
|
||||
} /* mat4_read_header */
|
||||
|
||||
static int
|
||||
mat4_format_to_encoding (int format, int endian)
|
||||
{
|
||||
switch (format | endian)
|
||||
{ case (SF_FORMAT_PCM_16 | SF_ENDIAN_BIG) :
|
||||
return MAT4_BE_PCM_16 ;
|
||||
|
||||
case (SF_FORMAT_PCM_16 | SF_ENDIAN_LITTLE) :
|
||||
return MAT4_LE_PCM_16 ;
|
||||
|
||||
case (SF_FORMAT_PCM_32 | SF_ENDIAN_BIG) :
|
||||
return MAT4_BE_PCM_32 ;
|
||||
|
||||
case (SF_FORMAT_PCM_32 | SF_ENDIAN_LITTLE) :
|
||||
return MAT4_LE_PCM_32 ;
|
||||
|
||||
case (SF_FORMAT_FLOAT | SF_ENDIAN_BIG) :
|
||||
return MAT4_BE_FLOAT ;
|
||||
|
||||
case (SF_FORMAT_FLOAT | SF_ENDIAN_LITTLE) :
|
||||
return MAT4_LE_FLOAT ;
|
||||
|
||||
case (SF_FORMAT_DOUBLE | SF_ENDIAN_BIG) :
|
||||
return MAT4_BE_DOUBLE ;
|
||||
|
||||
case (SF_FORMAT_DOUBLE | SF_ENDIAN_LITTLE) :
|
||||
return MAT4_LE_DOUBLE ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return -1 ;
|
||||
} /* mat4_format_to_encoding */
|
||||
|
||||
static const char *
|
||||
mat4_marker_to_str (int marker)
|
||||
{ static char str [32] ;
|
||||
|
||||
switch (marker)
|
||||
{
|
||||
case MAT4_BE_PCM_16 : return "big endian 16 bit PCM" ;
|
||||
case MAT4_LE_PCM_16 : return "little endian 16 bit PCM" ;
|
||||
|
||||
case MAT4_BE_PCM_32 : return "big endian 32 bit PCM" ;
|
||||
case MAT4_LE_PCM_32 : return "little endian 32 bit PCM" ;
|
||||
|
||||
|
||||
case MAT4_BE_FLOAT : return "big endian float" ;
|
||||
case MAT4_LE_FLOAT : return "big endian float" ;
|
||||
|
||||
case MAT4_BE_DOUBLE : return "big endian double" ;
|
||||
case MAT4_LE_DOUBLE : return "little endian double" ;
|
||||
} ;
|
||||
|
||||
/* This is a little unsafe but is really only for debugging. */
|
||||
str [sizeof (str) - 1] = 0 ;
|
||||
snprintf (str, sizeof (str) - 1, "%08X", marker) ;
|
||||
return str ;
|
||||
} /* mat4_marker_to_str */
|
||||
|
||||
501
project/jni/sndfile/src/mat5.c
Normal file
501
project/jni/sndfile/src/mat5.c
Normal file
@@ -0,0 +1,501 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Information on how to decode and encode this file was obtained in a PDF
|
||||
** file which I found on http://www.wotsit.org/.
|
||||
** Also did a lot of testing with GNU Octave but do not have access to
|
||||
** Matlab (tm) and so could not test it there.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define MATL_MARKER (MAKE_MARKER ('M', 'A', 'T', 'L'))
|
||||
|
||||
#define IM_MARKER (('I' << 8) + 'M')
|
||||
#define MI_MARKER (('M' << 8) + 'I')
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Enums and typedefs.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ MAT5_TYPE_SCHAR = 0x1,
|
||||
MAT5_TYPE_UCHAR = 0x2,
|
||||
MAT5_TYPE_INT16 = 0x3,
|
||||
MAT5_TYPE_UINT16 = 0x4,
|
||||
MAT5_TYPE_INT32 = 0x5,
|
||||
MAT5_TYPE_UINT32 = 0x6,
|
||||
MAT5_TYPE_FLOAT = 0x7,
|
||||
MAT5_TYPE_DOUBLE = 0x9,
|
||||
MAT5_TYPE_ARRAY = 0xE,
|
||||
|
||||
MAT5_TYPE_COMP_USHORT = 0x00020004,
|
||||
MAT5_TYPE_COMP_UINT = 0x00040006
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t size ;
|
||||
int rows, cols ;
|
||||
char name [32] ;
|
||||
} MAT5_MATRIX ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int mat5_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int mat5_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int mat5_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
mat5_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = mat5_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_MAT5)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (CPU_IS_LITTLE_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
else if (CPU_IS_BIG_ENDIAN && (psf->endian == SF_ENDIAN_CPU || psf->endian == 0))
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if ((error = mat5_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
|
||||
psf->write_header = mat5_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = mat5_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* mat5_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
mat5_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
mat5_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* mat5_close */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
mat5_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ static const char *filename = "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", " ;
|
||||
static const char *sr_name = "samplerate\0\0\0\0\0\0\0\0\0\0\0" ;
|
||||
static const char *wd_name = "wavedata\0" ;
|
||||
sf_count_t current, datasize ;
|
||||
int encoding ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf_fseek (psf, 0, SEEK_END) ;
|
||||
psf->filelength = psf_ftell (psf) ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
encoding = MAT5_TYPE_UCHAR ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
encoding = MAT5_TYPE_INT16 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_32 :
|
||||
encoding = MAT5_TYPE_INT32 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
encoding = MAT5_TYPE_FLOAT ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
encoding = MAT5_TYPE_DOUBLE ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
} ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
psf_get_date_str (psf->u.cbuf, sizeof (psf->u.scbuf)) ;
|
||||
psf_binheader_writef (psf, "bb", filename, strlen (filename), psf->u.cbuf, strlen (psf->u.cbuf) + 1) ;
|
||||
|
||||
memset (psf->u.scbuf, ' ', 124 - psf->headindex) ;
|
||||
psf_binheader_writef (psf, "b", psf->u.scbuf, make_size_t (124 - psf->headindex)) ;
|
||||
|
||||
psf->rwf_endian = psf->endian ;
|
||||
|
||||
if (psf->rwf_endian == SF_ENDIAN_BIG)
|
||||
psf_binheader_writef (psf, "2b", 0x0100, "MI", make_size_t (2)) ;
|
||||
else
|
||||
psf_binheader_writef (psf, "2b", 0x0100, "IM", make_size_t (2)) ;
|
||||
|
||||
psf_binheader_writef (psf, "444444", MAT5_TYPE_ARRAY, 64, MAT5_TYPE_UINT32, 8, 6, 0) ;
|
||||
psf_binheader_writef (psf, "4444", MAT5_TYPE_INT32, 8, 1, 1) ;
|
||||
psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (sr_name), sr_name, make_size_t (16)) ;
|
||||
|
||||
if (psf->sf.samplerate > 0xFFFF)
|
||||
psf_binheader_writef (psf, "44", MAT5_TYPE_COMP_UINT, psf->sf.samplerate) ;
|
||||
else
|
||||
{ unsigned short samplerate = psf->sf.samplerate ;
|
||||
|
||||
psf_binheader_writef (psf, "422", MAT5_TYPE_COMP_USHORT, samplerate, 0) ;
|
||||
} ;
|
||||
|
||||
datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
psf_binheader_writef (psf, "t484444", MAT5_TYPE_ARRAY, datasize + 64, MAT5_TYPE_UINT32, 8, 6, 0) ;
|
||||
psf_binheader_writef (psf, "t4448", MAT5_TYPE_INT32, 8, psf->sf.channels, psf->sf.frames) ;
|
||||
psf_binheader_writef (psf, "44b", MAT5_TYPE_SCHAR, strlen (wd_name), wd_name, strlen (wd_name)) ;
|
||||
|
||||
datasize = psf->sf.frames * psf->sf.channels * psf->bytewidth ;
|
||||
if (datasize > 0x7FFFFFFF)
|
||||
datasize = 0x7FFFFFFF ;
|
||||
|
||||
psf_binheader_writef (psf, "t48", encoding, datasize) ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* mat5_write_header */
|
||||
|
||||
static int
|
||||
mat5_read_header (SF_PRIVATE *psf)
|
||||
{ char name [32] ;
|
||||
short version, endian ;
|
||||
int type, flags1, flags2, rows, cols ;
|
||||
unsigned size ;
|
||||
|
||||
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 124) ;
|
||||
|
||||
psf->u.scbuf [125] = 0 ;
|
||||
|
||||
if (strlen (psf->u.cbuf) >= 124)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
if (strstr (psf->u.cbuf, "MATLAB 5.0 MAT-file") == psf->u.cbuf)
|
||||
psf_log_printf (psf, "%s\n", psf->u.scbuf) ;
|
||||
|
||||
|
||||
psf_binheader_readf (psf, "E22", &version, &endian) ;
|
||||
|
||||
if (endian == MI_MARKER)
|
||||
{ psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ;
|
||||
if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_SHORT (version) ;
|
||||
}
|
||||
else if (endian == IM_MARKER)
|
||||
{ psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ;
|
||||
if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_SHORT (version) ;
|
||||
}
|
||||
else
|
||||
return SFE_MAT5_BAD_ENDIAN ;
|
||||
|
||||
if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) ||
|
||||
(CPU_IS_BIG_ENDIAN && endian == MI_MARKER))
|
||||
version = ENDSWAP_SHORT (version) ;
|
||||
|
||||
psf_log_printf (psf, "Version : 0x%04X\n", version) ;
|
||||
psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian,
|
||||
(psf->endian == SF_ENDIAN_LITTLE) ? "Little" : "Big") ;
|
||||
|
||||
/*========================================================*/
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, "Block\n Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
if (type != MAT5_TYPE_ARRAY)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
if (type != MAT5_TYPE_UINT32)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &flags1, &flags2) ;
|
||||
psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
if (type != MAT5_TYPE_INT32)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &rows, &cols) ;
|
||||
psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ;
|
||||
|
||||
if (rows != 1 || cols != 1)
|
||||
return SFE_MAT5_SAMPLE_RATE ;
|
||||
|
||||
psf_binheader_readf (psf, "4", &type) ;
|
||||
|
||||
if (type == MAT5_TYPE_SCHAR)
|
||||
{ psf_binheader_readf (psf, "4", &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
if (size > SIGNED_SIZEOF (name) - 1)
|
||||
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
} ;
|
||||
|
||||
psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ;
|
||||
name [size] = 0 ;
|
||||
}
|
||||
else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR)
|
||||
{ size = type >> 16 ;
|
||||
if (size > 4)
|
||||
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " Type : %X\n", type) ;
|
||||
psf_binheader_readf (psf, "4", &name) ;
|
||||
name [size] = 0 ;
|
||||
}
|
||||
else
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_log_printf (psf, " Name : %s\n", name) ;
|
||||
|
||||
/*-----------------------------------------*/
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
|
||||
switch (type)
|
||||
{ case MAT5_TYPE_DOUBLE :
|
||||
{ double samplerate ;
|
||||
|
||||
psf_binheader_readf (psf, "d", &samplerate) ;
|
||||
snprintf (name, sizeof (name), "%f\n", samplerate) ;
|
||||
psf_log_printf (psf, " Val : %s\n", name) ;
|
||||
|
||||
psf->sf.samplerate = lrint (samplerate) ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
case MAT5_TYPE_COMP_USHORT :
|
||||
{ unsigned short samplerate ;
|
||||
|
||||
psf_binheader_readf (psf, "j2j", -4, &samplerate, 2) ;
|
||||
psf_log_printf (psf, " Val : %u\n", samplerate) ;
|
||||
psf->sf.samplerate = samplerate ;
|
||||
}
|
||||
break ;
|
||||
|
||||
case MAT5_TYPE_COMP_UINT :
|
||||
psf_log_printf (psf, " Val : %u\n", size) ;
|
||||
psf->sf.samplerate = size ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, " Type : %X Size : %d ***\n", type, size) ;
|
||||
return SFE_MAT5_SAMPLE_RATE ;
|
||||
} ;
|
||||
|
||||
/*-----------------------------------------*/
|
||||
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
if (type != MAT5_TYPE_ARRAY)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
if (type != MAT5_TYPE_UINT32)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &flags1, &flags2) ;
|
||||
psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
if (type != MAT5_TYPE_INT32)
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &rows, &cols) ;
|
||||
psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ;
|
||||
|
||||
psf_binheader_readf (psf, "4", &type) ;
|
||||
|
||||
if (type == MAT5_TYPE_SCHAR)
|
||||
{ psf_binheader_readf (psf, "4", &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
if (size > SIGNED_SIZEOF (name) - 1)
|
||||
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
} ;
|
||||
|
||||
psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ;
|
||||
name [size] = 0 ;
|
||||
}
|
||||
else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR)
|
||||
{ size = type >> 16 ;
|
||||
if (size > 4)
|
||||
{ psf_log_printf (psf, "Error : Bad name length.\n") ;
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " Type : %X\n", type) ;
|
||||
psf_binheader_readf (psf, "4", &name) ;
|
||||
name [size] = 0 ;
|
||||
}
|
||||
else
|
||||
return SFE_MAT5_NO_BLOCK ;
|
||||
|
||||
psf_log_printf (psf, " Name : %s\n", name) ;
|
||||
|
||||
psf_binheader_readf (psf, "44", &type, &size) ;
|
||||
psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ;
|
||||
|
||||
/*++++++++++++++++++++++++++++++++++++++++++++++++++*/
|
||||
|
||||
if (rows == 0 && cols == 0)
|
||||
{ psf_log_printf (psf, "*** Error : zero channel count.\n") ;
|
||||
return SFE_CHANNEL_COUNT_ZERO ;
|
||||
} ;
|
||||
|
||||
psf->sf.channels = rows ;
|
||||
psf->sf.frames = cols ;
|
||||
|
||||
psf->sf.format = psf->endian | SF_FORMAT_MAT5 ;
|
||||
|
||||
switch (type)
|
||||
{ case MAT5_TYPE_DOUBLE :
|
||||
psf_log_printf (psf, "Data type : double\n") ;
|
||||
psf->sf.format |= SF_FORMAT_DOUBLE ;
|
||||
psf->bytewidth = 8 ;
|
||||
break ;
|
||||
|
||||
case MAT5_TYPE_FLOAT :
|
||||
psf_log_printf (psf, "Data type : float\n") ;
|
||||
psf->sf.format |= SF_FORMAT_FLOAT ;
|
||||
psf->bytewidth = 4 ;
|
||||
break ;
|
||||
|
||||
case MAT5_TYPE_INT32 :
|
||||
psf_log_printf (psf, "Data type : 32 bit PCM\n") ;
|
||||
psf->sf.format |= SF_FORMAT_PCM_32 ;
|
||||
psf->bytewidth = 4 ;
|
||||
break ;
|
||||
|
||||
case MAT5_TYPE_INT16 :
|
||||
psf_log_printf (psf, "Data type : 16 bit PCM\n") ;
|
||||
psf->sf.format |= SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
break ;
|
||||
|
||||
case MAT5_TYPE_UCHAR :
|
||||
psf_log_printf (psf, "Data type : unsigned 8 bit PCM\n") ;
|
||||
psf->sf.format |= SF_FORMAT_PCM_U8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "*** Error : Bad marker %08X\n", type) ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
return 0 ;
|
||||
} /* mat5_read_header */
|
||||
|
||||
204
project/jni/sndfile/src/mpc2k.c
Normal file
204
project/jni/sndfile/src/mpc2k.c
Normal file
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
** Info from Olivier Tristan <o.tristan@ultimatesoundbank.com>
|
||||
**
|
||||
** HEADER
|
||||
** 2 magic bytes: 1 and 4.
|
||||
** 17 char for the name of the sample.
|
||||
** 3 bytes: level, tune and channels (0 for channels is mono while 1 is stereo)
|
||||
** 4 uint32: sampleStart, loopEnd, sampleFrames and loopLength
|
||||
** 1 byte: loopMode (0 no loop, 1 forward looping)
|
||||
** 1 byte: number of beat in loop
|
||||
** 1 uint16: sampleRate
|
||||
**
|
||||
** DATA
|
||||
** Data are always non compressed 16 bits interleaved
|
||||
*/
|
||||
|
||||
#define HEADER_LENGTH 42 /* Sum of above data fields. */
|
||||
#define HEADER_NAME_LEN 17 /* Length of name string. */
|
||||
|
||||
#define SFE_MPC_NO_MARKER 666
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int mpc2k_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int mpc2k_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int mpc2k_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
mpc2k_open (SF_PRIVATE *psf)
|
||||
{ int error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = mpc2k_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_MPC2K)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (mpc2k_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
psf->write_header = mpc2k_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = mpc2k_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
error = pcm_init (psf) ;
|
||||
|
||||
return error ;
|
||||
} /* mpc2k_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
mpc2k_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
mpc2k_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* mpc2k_close */
|
||||
|
||||
static int
|
||||
mpc2k_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ char sample_name [HEADER_NAME_LEN + 1] ;
|
||||
sf_count_t current ;
|
||||
|
||||
if (psf->pipeoffset > 0)
|
||||
return 0 ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->dataoffset = HEADER_LENGTH ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
/*
|
||||
** Only attempt to seek if we are not writng to a pipe. If we are
|
||||
** writing to a pipe we shouldn't be here anyway.
|
||||
*/
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
snprintf (sample_name, sizeof (sample_name), "%s ", psf->file.name.c) ;
|
||||
|
||||
psf_binheader_writef (psf, "e11b", 1, 4, sample_name, make_size_t (HEADER_NAME_LEN)) ;
|
||||
psf_binheader_writef (psf, "e111", 100, 0, (psf->sf.channels - 1) & 1) ;
|
||||
psf_binheader_writef (psf, "et4888", 0, psf->sf.frames, psf->sf.frames, psf->sf.frames) ;
|
||||
psf_binheader_writef (psf, "e112", 0, 1, (uint16_t) psf->sf.samplerate) ;
|
||||
|
||||
/* Always 16 bit little endian data. */
|
||||
psf->bytewidth = 2 ;
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* mpc2k_write_header */
|
||||
|
||||
static int
|
||||
mpc2k_read_header (SF_PRIVATE *psf)
|
||||
{ char sample_name [HEADER_NAME_LEN + 1] ;
|
||||
unsigned char bytes [4] ;
|
||||
uint32_t sample_start, loop_end, sample_frames, loop_length ;
|
||||
uint16_t sample_rate ;
|
||||
|
||||
psf_binheader_readf (psf, "pebb", 0, bytes, 2, sample_name, make_size_t (HEADER_NAME_LEN)) ;
|
||||
|
||||
if (bytes [0] != 1 || bytes [1] != 4)
|
||||
return SFE_MPC_NO_MARKER ;
|
||||
|
||||
sample_name [HEADER_NAME_LEN] = 0 ;
|
||||
|
||||
psf_log_printf (psf, "MPC2000\n Name : %s\n", sample_name) ;
|
||||
|
||||
psf_binheader_readf (psf, "eb4444", bytes, 3, &sample_start, &loop_end, &sample_frames, &loop_length) ;
|
||||
|
||||
psf->sf.channels = bytes [2] ? 2 : 1 ;
|
||||
|
||||
psf_log_printf (psf, " Level : %d\n Tune : %d\n Stereo : %s\n", bytes [0], bytes [1], bytes [2] ? "Yes" : "No") ;
|
||||
|
||||
psf_log_printf (psf, " Sample start : %d\n Loop end : %d\n Frames : %d\n Length : %d\n", sample_start, loop_end, sample_frames, loop_length) ;
|
||||
|
||||
psf_binheader_readf (psf, "eb2", bytes, 2, &sample_rate) ;
|
||||
|
||||
psf_log_printf (psf, " Loop mode : %s\n Beats : %d\n Sample rate : %d\nEnd\n", bytes [0] ? "None" : "Fwd", bytes [1], sample_rate) ;
|
||||
|
||||
psf->sf.samplerate = sample_rate ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_MPC2K | SF_FORMAT_PCM_16 ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
|
||||
/* Always 16 bit little endian data. */
|
||||
psf->bytewidth = 2 ;
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
|
||||
return 0 ;
|
||||
} /* mpc2k_read_header */
|
||||
|
||||
834
project/jni/sndfile/src/ms_adpcm.c
Normal file
834
project/jni/sndfile/src/ms_adpcm.c
Normal file
@@ -0,0 +1,834 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "wav_w64.h"
|
||||
|
||||
/* These required here because we write the header in this file. */
|
||||
|
||||
#define RIFF_MARKER (MAKE_MARKER ('R', 'I', 'F', 'F'))
|
||||
#define WAVE_MARKER (MAKE_MARKER ('W', 'A', 'V', 'E'))
|
||||
#define fmt_MARKER (MAKE_MARKER ('f', 'm', 't', ' '))
|
||||
#define fact_MARKER (MAKE_MARKER ('f', 'a', 'c', 't'))
|
||||
#define data_MARKER (MAKE_MARKER ('d', 'a', 't', 'a'))
|
||||
|
||||
#define WAVE_FORMAT_MS_ADPCM 0x0002
|
||||
|
||||
typedef struct
|
||||
{ int channels, blocksize, samplesperblock, blocks, dataremaining ;
|
||||
int blockcount ;
|
||||
sf_count_t samplecount ;
|
||||
short *samples ;
|
||||
unsigned char *block ;
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
short dummydata [] ; /* ISO C99 struct flexible array. */
|
||||
#else
|
||||
short dummydata [0] ; /* This is a hack an might not work. */
|
||||
#endif
|
||||
} MSADPCM_PRIVATE ;
|
||||
|
||||
/*============================================================================================
|
||||
** MS ADPCM static data and functions.
|
||||
*/
|
||||
|
||||
static int AdaptationTable [] =
|
||||
{ 230, 230, 230, 230, 307, 409, 512, 614,
|
||||
768, 614, 512, 409, 307, 230, 230, 230
|
||||
} ;
|
||||
|
||||
/* TODO : The first 7 coef's are are always hardcode and must
|
||||
appear in the actual WAVE file. They should be read in
|
||||
in case a sound program added extras to the list. */
|
||||
|
||||
static int AdaptCoeff1 [MSADPCM_ADAPT_COEFF_COUNT] =
|
||||
{ 256, 512, 0, 192, 240, 460, 392
|
||||
} ;
|
||||
|
||||
static int AdaptCoeff2 [MSADPCM_ADAPT_COEFF_COUNT] =
|
||||
{ 0, -256, 0, 64, 0, -208, -232
|
||||
} ;
|
||||
|
||||
/*============================================================================================
|
||||
** MS ADPCM Block Layout.
|
||||
** ======================
|
||||
** Block is usually 256, 512 or 1024 bytes depending on sample rate.
|
||||
** For a mono file, the block is laid out as follows:
|
||||
** byte purpose
|
||||
** 0 block predictor [0..6]
|
||||
** 1,2 initial idelta (positive)
|
||||
** 3,4 sample 1
|
||||
** 5,6 sample 0
|
||||
** 7..n packed bytecodes
|
||||
**
|
||||
** For a stereo file, the block is laid out as follows:
|
||||
** byte purpose
|
||||
** 0 block predictor [0..6] for left channel
|
||||
** 1 block predictor [0..6] for right channel
|
||||
** 2,3 initial idelta (positive) for left channel
|
||||
** 4,5 initial idelta (positive) for right channel
|
||||
** 6,7 sample 1 for left channel
|
||||
** 8,9 sample 1 for right channel
|
||||
** 10,11 sample 0 for left channel
|
||||
** 12,13 sample 0 for right channel
|
||||
** 14..n packed bytecodes
|
||||
*/
|
||||
|
||||
/*============================================================================================
|
||||
** Static functions.
|
||||
*/
|
||||
|
||||
static int msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ;
|
||||
static sf_count_t msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len) ;
|
||||
|
||||
static int msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms) ;
|
||||
static sf_count_t msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, const short *ptr, int len) ;
|
||||
|
||||
static sf_count_t msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
static int msadpcm_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static void choose_predictor (unsigned int channels, short *data, int *bpred, int *idelta) ;
|
||||
|
||||
/*============================================================================================
|
||||
** MS ADPCM Read Functions.
|
||||
*/
|
||||
|
||||
int
|
||||
wav_w64_msadpcm_init (SF_PRIVATE *psf, int blockalign, int samplesperblock)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
unsigned int pmssize ;
|
||||
int count ;
|
||||
|
||||
if (psf->codec_data != NULL)
|
||||
{ psf_log_printf (psf, "*** psf->codec_data is not NULL.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
samplesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
|
||||
|
||||
pmssize = sizeof (MSADPCM_PRIVATE) + blockalign + 3 * psf->sf.channels * samplesperblock ;
|
||||
|
||||
if (! (psf->codec_data = calloc (1, pmssize)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
pms->samples = pms->dummydata ;
|
||||
pms->block = (unsigned char*) (pms->dummydata + psf->sf.channels * samplesperblock) ;
|
||||
|
||||
pms->channels = psf->sf.channels ;
|
||||
pms->blocksize = blockalign ;
|
||||
pms->samplesperblock = samplesperblock ;
|
||||
|
||||
if (pms->blocksize == 0)
|
||||
{ psf_log_printf (psf, "*** Error : pms->blocksize should not be zero.\n") ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ pms->dataremaining = psf->datalength ;
|
||||
|
||||
if (psf->datalength % pms->blocksize)
|
||||
pms->blocks = psf->datalength / pms->blocksize + 1 ;
|
||||
else
|
||||
pms->blocks = psf->datalength / pms->blocksize ;
|
||||
|
||||
count = 2 * (pms->blocksize - 6 * pms->channels) / pms->channels ;
|
||||
if (pms->samplesperblock != count)
|
||||
{ psf_log_printf (psf, "*** Error : samplesperblock should be %d.\n", count) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->sf.frames = (psf->datalength / pms->blocksize) * pms->samplesperblock ;
|
||||
|
||||
psf_log_printf (psf, " bpred idelta\n") ;
|
||||
|
||||
msadpcm_decode_block (psf, pms) ;
|
||||
|
||||
psf->read_short = msadpcm_read_s ;
|
||||
psf->read_int = msadpcm_read_i ;
|
||||
psf->read_float = msadpcm_read_f ;
|
||||
psf->read_double = msadpcm_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ pms->samples = pms->dummydata ;
|
||||
|
||||
pms->samplecount = 0 ;
|
||||
|
||||
psf->write_short = msadpcm_write_s ;
|
||||
psf->write_int = msadpcm_write_i ;
|
||||
psf->write_float = msadpcm_write_f ;
|
||||
psf->write_double = msadpcm_write_d ;
|
||||
} ;
|
||||
|
||||
psf->codec_close = msadpcm_close ;
|
||||
psf->seek = msadpcm_seek ;
|
||||
|
||||
return 0 ;
|
||||
} /* wav_w64_msadpcm_init */
|
||||
|
||||
static int
|
||||
msadpcm_decode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
{ int chan, k, blockindx, sampleindx ;
|
||||
short bytecode, bpred [2], chan_idelta [2] ;
|
||||
|
||||
int predict ;
|
||||
int current ;
|
||||
int idelta ;
|
||||
|
||||
pms->blockcount ++ ;
|
||||
pms->samplecount = 0 ;
|
||||
|
||||
if (pms->blockcount > pms->blocks)
|
||||
{ memset (pms->samples, 0, pms->samplesperblock * pms->channels) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
if ((k = psf_fread (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pms->blocksize) ;
|
||||
|
||||
/* Read and check the block header. */
|
||||
|
||||
if (pms->channels == 1)
|
||||
{ bpred [0] = pms->block [0] ;
|
||||
|
||||
if (bpred [0] >= 7)
|
||||
psf_log_printf (psf, "MS ADPCM synchronisation error (%d).\n", bpred [0]) ;
|
||||
|
||||
chan_idelta [0] = pms->block [1] | (pms->block [2] << 8) ;
|
||||
chan_idelta [1] = 0 ;
|
||||
|
||||
psf_log_printf (psf, "(%d) (%d)\n", bpred [0], chan_idelta [0]) ;
|
||||
|
||||
pms->samples [1] = pms->block [3] | (pms->block [4] << 8) ;
|
||||
pms->samples [0] = pms->block [5] | (pms->block [6] << 8) ;
|
||||
blockindx = 7 ;
|
||||
}
|
||||
else
|
||||
{ bpred [0] = pms->block [0] ;
|
||||
bpred [1] = pms->block [1] ;
|
||||
|
||||
if (bpred [0] >= 7 || bpred [1] >= 7)
|
||||
psf_log_printf (psf, "MS ADPCM synchronisation error (%d %d).\n", bpred [0], bpred [1]) ;
|
||||
|
||||
chan_idelta [0] = pms->block [2] | (pms->block [3] << 8) ;
|
||||
chan_idelta [1] = pms->block [4] | (pms->block [5] << 8) ;
|
||||
|
||||
psf_log_printf (psf, "(%d, %d) (%d, %d)\n", bpred [0], bpred [1], chan_idelta [0], chan_idelta [1]) ;
|
||||
|
||||
pms->samples [2] = pms->block [6] | (pms->block [7] << 8) ;
|
||||
pms->samples [3] = pms->block [8] | (pms->block [9] << 8) ;
|
||||
|
||||
pms->samples [0] = pms->block [10] | (pms->block [11] << 8) ;
|
||||
pms->samples [1] = pms->block [12] | (pms->block [13] << 8) ;
|
||||
|
||||
blockindx = 14 ;
|
||||
} ;
|
||||
|
||||
/*--------------------------------------------------------
|
||||
This was left over from a time when calculations were done
|
||||
as ints rather than shorts. Keep this around as a reminder
|
||||
in case I ever find a file which decodes incorrectly.
|
||||
|
||||
if (chan_idelta [0] & 0x8000)
|
||||
chan_idelta [0] -= 0x10000 ;
|
||||
if (chan_idelta [1] & 0x8000)
|
||||
chan_idelta [1] -= 0x10000 ;
|
||||
--------------------------------------------------------*/
|
||||
|
||||
/* Pull apart the packed 4 bit samples and store them in their
|
||||
** correct sample positions.
|
||||
*/
|
||||
|
||||
sampleindx = 2 * pms->channels ;
|
||||
while (blockindx < pms->blocksize)
|
||||
{ bytecode = pms->block [blockindx++] ;
|
||||
pms->samples [sampleindx++] = (bytecode >> 4) & 0x0F ;
|
||||
pms->samples [sampleindx++] = bytecode & 0x0F ;
|
||||
} ;
|
||||
|
||||
/* Decode the encoded 4 bit samples. */
|
||||
|
||||
for (k = 2 * pms->channels ; k < (pms->samplesperblock * pms->channels) ; k ++)
|
||||
{ chan = (pms->channels > 1) ? (k % 2) : 0 ;
|
||||
|
||||
bytecode = pms->samples [k] & 0xF ;
|
||||
|
||||
/* Compute next Adaptive Scale Factor (ASF) */
|
||||
idelta = chan_idelta [chan] ;
|
||||
chan_idelta [chan] = (AdaptationTable [bytecode] * idelta) >> 8 ; /* => / 256 => FIXED_POINT_ADAPTATION_BASE == 256 */
|
||||
if (chan_idelta [chan] < 16)
|
||||
chan_idelta [chan] = 16 ;
|
||||
if (bytecode & 0x8)
|
||||
bytecode -= 0x10 ;
|
||||
|
||||
predict = ((pms->samples [k - pms->channels] * AdaptCoeff1 [bpred [chan]])
|
||||
+ (pms->samples [k - 2 * pms->channels] * AdaptCoeff2 [bpred [chan]])) >> 8 ; /* => / 256 => FIXED_POINT_COEFF_BASE == 256 */
|
||||
current = (bytecode * idelta) + predict ;
|
||||
|
||||
if (current > 32767)
|
||||
current = 32767 ;
|
||||
else if (current < -32768)
|
||||
current = -32768 ;
|
||||
|
||||
pms->samples [k] = current ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* msadpcm_decode_block */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_read_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ if (pms->blockcount >= pms->blocks && pms->samplecount >= pms->samplesperblock)
|
||||
{ memset (&(ptr [indx]), 0, (size_t) ((len - indx) * sizeof (short))) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
if (pms->samplecount >= pms->samplesperblock)
|
||||
msadpcm_decode_block (psf, pms) ;
|
||||
|
||||
count = (pms->samplesperblock - pms->samplecount) * pms->channels ;
|
||||
count = (len - indx > count) ? count : len - indx ;
|
||||
|
||||
memcpy (&(ptr [indx]), &(pms->samples [pms->samplecount * pms->channels]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pms->samplecount += count / pms->channels ;
|
||||
total = indx ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* msadpcm_read_block */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
int readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = msadpcm_read_block (psf, pms, ptr, readcount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* msadpcm_read_s */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = sptr [k] << 16 ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* msadpcm_read_i */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? 1.0 / ((float) 0x8000) : 1.0 ;
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (float) (sptr [k]) ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* msadpcm_read_f */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, readcount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? 1.0 / ((double) 0x8000) : 1.0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = msadpcm_read_block (psf, pms, sptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * (double) (sptr [k]) ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
if (count != readcount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* msadpcm_read_d */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
int newblock, newsample ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->datalength < 0 || psf->dataoffset < 0)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
if (offset == 0)
|
||||
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
pms->blockcount = 0 ;
|
||||
msadpcm_decode_block (psf, pms) ;
|
||||
pms->samplecount = 0 ;
|
||||
return 0 ;
|
||||
} ;
|
||||
|
||||
if (offset < 0 || offset > pms->blocks * pms->samplesperblock)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
newblock = offset / pms->samplesperblock ;
|
||||
newsample = offset % pms->samplesperblock ;
|
||||
|
||||
if (mode == SFM_READ)
|
||||
{ psf_fseek (psf, psf->dataoffset + newblock * pms->blocksize, SEEK_SET) ;
|
||||
pms->blockcount = newblock ;
|
||||
msadpcm_decode_block (psf, pms) ;
|
||||
pms->samplecount = newsample ;
|
||||
}
|
||||
else
|
||||
{ /* What to do about write??? */
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
return newblock * pms->samplesperblock + newsample ;
|
||||
} /* msadpcm_seek */
|
||||
|
||||
/*==========================================================================================
|
||||
** MS ADPCM Write Functions.
|
||||
*/
|
||||
|
||||
void
|
||||
msadpcm_write_adapt_coeffs (SF_PRIVATE *psf)
|
||||
{ int k ;
|
||||
|
||||
for (k = 0 ; k < MSADPCM_ADAPT_COEFF_COUNT ; k++)
|
||||
psf_binheader_writef (psf, "22", AdaptCoeff1 [k], AdaptCoeff2 [k]) ;
|
||||
} /* msadpcm_write_adapt_coeffs */
|
||||
|
||||
/*==========================================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
msadpcm_encode_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms)
|
||||
{ unsigned int blockindx ;
|
||||
unsigned char byte ;
|
||||
int chan, k, predict, bpred [2], idelta [2], errordelta, newsamp ;
|
||||
|
||||
choose_predictor (pms->channels, pms->samples, bpred, idelta) ;
|
||||
|
||||
/* Write the block header. */
|
||||
|
||||
if (pms->channels == 1)
|
||||
{ pms->block [0] = bpred [0] ;
|
||||
pms->block [1] = idelta [0] & 0xFF ;
|
||||
pms->block [2] = idelta [0] >> 8 ;
|
||||
pms->block [3] = pms->samples [1] & 0xFF ;
|
||||
pms->block [4] = pms->samples [1] >> 8 ;
|
||||
pms->block [5] = pms->samples [0] & 0xFF ;
|
||||
pms->block [6] = pms->samples [0] >> 8 ;
|
||||
|
||||
blockindx = 7 ;
|
||||
byte = 0 ;
|
||||
|
||||
/* Encode the samples as 4 bit. */
|
||||
|
||||
for (k = 2 ; k < pms->samplesperblock ; k++)
|
||||
{ predict = (pms->samples [k-1] * AdaptCoeff1 [bpred [0]] + pms->samples [k-2] * AdaptCoeff2 [bpred [0]]) >> 8 ;
|
||||
errordelta = (pms->samples [k] - predict) / idelta [0] ;
|
||||
if (errordelta < -8)
|
||||
errordelta = -8 ;
|
||||
else if (errordelta > 7)
|
||||
errordelta = 7 ;
|
||||
newsamp = predict + (idelta [0] * errordelta) ;
|
||||
if (newsamp > 32767)
|
||||
newsamp = 32767 ;
|
||||
else if (newsamp < -32768)
|
||||
newsamp = -32768 ;
|
||||
if (errordelta < 0)
|
||||
errordelta += 0x10 ;
|
||||
|
||||
byte = (byte << 4) | (errordelta & 0xF) ;
|
||||
if (k % 2)
|
||||
{ pms->block [blockindx++] = byte ;
|
||||
byte = 0 ;
|
||||
} ;
|
||||
|
||||
idelta [0] = (idelta [0] * AdaptationTable [errordelta]) >> 8 ;
|
||||
if (idelta [0] < 16)
|
||||
idelta [0] = 16 ;
|
||||
pms->samples [k] = newsamp ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
{ /* Stereo file. */
|
||||
pms->block [0] = bpred [0] ;
|
||||
pms->block [1] = bpred [1] ;
|
||||
|
||||
pms->block [2] = idelta [0] & 0xFF ;
|
||||
pms->block [3] = idelta [0] >> 8 ;
|
||||
pms->block [4] = idelta [1] & 0xFF ;
|
||||
pms->block [5] = idelta [1] >> 8 ;
|
||||
|
||||
pms->block [6] = pms->samples [2] & 0xFF ;
|
||||
pms->block [7] = pms->samples [2] >> 8 ;
|
||||
pms->block [8] = pms->samples [3] & 0xFF ;
|
||||
pms->block [9] = pms->samples [3] >> 8 ;
|
||||
|
||||
pms->block [10] = pms->samples [0] & 0xFF ;
|
||||
pms->block [11] = pms->samples [0] >> 8 ;
|
||||
pms->block [12] = pms->samples [1] & 0xFF ;
|
||||
pms->block [13] = pms->samples [1] >> 8 ;
|
||||
|
||||
blockindx = 14 ;
|
||||
byte = 0 ;
|
||||
chan = 1 ;
|
||||
|
||||
for (k = 4 ; k < 2 * pms->samplesperblock ; k++)
|
||||
{ chan = k & 1 ;
|
||||
|
||||
predict = (pms->samples [k-2] * AdaptCoeff1 [bpred [chan]] + pms->samples [k-4] * AdaptCoeff2 [bpred [chan]]) >> 8 ;
|
||||
errordelta = (pms->samples [k] - predict) / idelta [chan] ;
|
||||
|
||||
|
||||
if (errordelta < -8)
|
||||
errordelta = -8 ;
|
||||
else if (errordelta > 7)
|
||||
errordelta = 7 ;
|
||||
newsamp = predict + (idelta [chan] * errordelta) ;
|
||||
if (newsamp > 32767)
|
||||
newsamp = 32767 ;
|
||||
else if (newsamp < -32768)
|
||||
newsamp = -32768 ;
|
||||
if (errordelta < 0)
|
||||
errordelta += 0x10 ;
|
||||
|
||||
byte = (byte << 4) | (errordelta & 0xF) ;
|
||||
|
||||
if (chan)
|
||||
{ pms->block [blockindx++] = byte ;
|
||||
byte = 0 ;
|
||||
} ;
|
||||
|
||||
idelta [chan] = (idelta [chan] * AdaptationTable [errordelta]) >> 8 ;
|
||||
if (idelta [chan] < 16)
|
||||
idelta [chan] = 16 ;
|
||||
pms->samples [k] = newsamp ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
/* Write the block to disk. */
|
||||
|
||||
if ((k = psf_fwrite (pms->block, 1, pms->blocksize, psf)) != pms->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, pms->blocksize) ;
|
||||
|
||||
memset (pms->samples, 0, pms->samplesperblock * sizeof (short)) ;
|
||||
|
||||
pms->blockcount ++ ;
|
||||
pms->samplecount = 0 ;
|
||||
|
||||
return 1 ;
|
||||
} /* msadpcm_encode_block */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_write_block (SF_PRIVATE *psf, MSADPCM_PRIVATE *pms, const short *ptr, int len)
|
||||
{ int count, total = 0, indx = 0 ;
|
||||
|
||||
while (indx < len)
|
||||
{ count = (pms->samplesperblock - pms->samplecount) * pms->channels ;
|
||||
|
||||
if (count > len - indx)
|
||||
count = len - indx ;
|
||||
|
||||
memcpy (&(pms->samples [pms->samplecount * pms->channels]), &(ptr [total]), count * sizeof (short)) ;
|
||||
indx += count ;
|
||||
pms->samplecount += count / pms->channels ;
|
||||
total = indx ;
|
||||
|
||||
if (pms->samplecount >= pms->samplesperblock)
|
||||
msadpcm_encode_block (psf, pms) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* msadpcm_write_block */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
int writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = msadpcm_write_block (psf, pms, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* msadpcm_write_s */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = ptr [total + k] >> 16 ;
|
||||
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* msadpcm_write_i */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrintf (normfact * ptr [total + k]) ;
|
||||
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* msadpcm_write_f */
|
||||
|
||||
static sf_count_t
|
||||
msadpcm_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
short *sptr ;
|
||||
int k, bufferlen, writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFF) : 1.0 ;
|
||||
|
||||
if (! psf->codec_data)
|
||||
return 0 ;
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
sptr = psf->u.sbuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
sptr [k] = lrint (normfact * ptr [total + k]) ;
|
||||
count = msadpcm_write_block (psf, pms, sptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* msadpcm_write_d */
|
||||
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
msadpcm_close (SF_PRIVATE *psf)
|
||||
{ MSADPCM_PRIVATE *pms ;
|
||||
|
||||
pms = (MSADPCM_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* Now we know static int for certain the length of the file we can
|
||||
** re-write the header.
|
||||
*/
|
||||
|
||||
if (pms->samplecount && pms->samplecount < pms->samplesperblock)
|
||||
msadpcm_encode_block (psf, pms) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* msadpcm_close */
|
||||
|
||||
/*========================================================================================
|
||||
** Static functions.
|
||||
*/
|
||||
|
||||
/*----------------------------------------------------------------------------------------
|
||||
** Choosing the block predictor.
|
||||
** Each block requires a predictor and an idelta for each channel.
|
||||
** The predictor is in the range [0..6] which is an indx into the two AdaptCoeff tables.
|
||||
** The predictor is chosen by trying all of the possible predictors on a small set of
|
||||
** samples at the beginning of the block. The predictor with the smallest average
|
||||
** abs (idelta) is chosen as the best predictor for this block.
|
||||
** The value of idelta is chosen to to give a 4 bit code value of +/- 4 (approx. half the
|
||||
** max. code value). If the average abs (idelta) is zero, the sixth predictor is chosen.
|
||||
** If the value of idelta is less then 16 it is set to 16.
|
||||
**
|
||||
** Microsoft uses an IDELTA_COUNT (number of sample pairs used to choose best predictor)
|
||||
** value of 3. The best possible results would be obtained by using all the samples to
|
||||
** choose the predictor.
|
||||
*/
|
||||
|
||||
#define IDELTA_COUNT 3
|
||||
|
||||
static void
|
||||
choose_predictor (unsigned int channels, short *data, int *block_pred, int *idelta)
|
||||
{ unsigned int chan, k, bpred, idelta_sum, best_bpred, best_idelta ;
|
||||
|
||||
for (chan = 0 ; chan < channels ; chan++)
|
||||
{ best_bpred = best_idelta = 0 ;
|
||||
|
||||
for (bpred = 0 ; bpred < 7 ; bpred++)
|
||||
{ idelta_sum = 0 ;
|
||||
for (k = 2 ; k < 2 + IDELTA_COUNT ; k++)
|
||||
idelta_sum += abs (data [k * channels] - ((data [(k - 1) * channels] * AdaptCoeff1 [bpred] + data [(k - 2) * channels] * AdaptCoeff2 [bpred]) >> 8)) ;
|
||||
idelta_sum /= (4 * IDELTA_COUNT) ;
|
||||
|
||||
if (bpred == 0 || idelta_sum < best_idelta)
|
||||
{ best_bpred = bpred ;
|
||||
best_idelta = idelta_sum ;
|
||||
} ;
|
||||
|
||||
if (! idelta_sum)
|
||||
{ best_bpred = bpred ;
|
||||
best_idelta = 16 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
} ; /* for bpred ... */
|
||||
if (best_idelta < 16)
|
||||
best_idelta = 16 ;
|
||||
|
||||
block_pred [chan] = best_bpred ;
|
||||
idelta [chan] = best_idelta ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* choose_predictor */
|
||||
|
||||
377
project/jni/sndfile/src/nist.c
Normal file
377
project/jni/sndfile/src/nist.c
Normal file
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Some of the information used to read NIST files was gleaned from
|
||||
** reading the code of Bill Schottstaedt's sndlib library
|
||||
** ftp://ccrma-ftp.stanford.edu/pub/Lisp/sndlib.tar.gz
|
||||
** However, no code from that package was used.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#define NIST_HEADER_LENGTH 1024
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int nist_close (SF_PRIVATE *psf) ;
|
||||
static int nist_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int nist_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
int
|
||||
nist_open (SF_PRIVATE *psf)
|
||||
{ int error ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = nist_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_NIST)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
if (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU)
|
||||
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
psf->sf.frames = 0 ;
|
||||
|
||||
if ((error = nist_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
|
||||
psf->write_header = nist_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = nist_close ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
error = ulaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
error = alaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : error = SFE_UNIMPLEMENTED ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* nist_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static char bad_header [] =
|
||||
{ 'N', 'I', 'S', 'T', '_', '1', 'A', 0x0d, 0x0a,
|
||||
' ', ' ', ' ', '1', '0', '2', '4', 0x0d, 0x0a,
|
||||
0
|
||||
} ;
|
||||
|
||||
static int
|
||||
nist_read_header (SF_PRIVATE *psf)
|
||||
{ char *psf_header ;
|
||||
int bitwidth = 0, count, encoding ;
|
||||
unsigned bytes = 0 ;
|
||||
char str [64], *cptr ;
|
||||
long samples ;
|
||||
|
||||
psf_header = psf->u.cbuf ;
|
||||
|
||||
if (sizeof (psf->header) <= NIST_HEADER_LENGTH)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
/* Go to start of file and read in the whole header. */
|
||||
psf_binheader_readf (psf, "pb", 0, psf_header, NIST_HEADER_LENGTH) ;
|
||||
|
||||
/* Header is a string, so make sure it is null terminated. */
|
||||
psf_header [NIST_HEADER_LENGTH] = 0 ;
|
||||
|
||||
/* Now trim the header after the end marker. */
|
||||
if ((cptr = strstr (psf_header, "end_head")))
|
||||
{ cptr += strlen ("end_head") + 1 ;
|
||||
cptr [0] = 0 ;
|
||||
} ;
|
||||
|
||||
if (strstr (psf_header, bad_header) == psf_header)
|
||||
return SFE_NIST_CRLF_CONVERISON ;
|
||||
|
||||
/* Make sure its a NIST file. */
|
||||
if (strstr (psf_header, "NIST_1A\n") != psf_header)
|
||||
{ psf_log_printf (psf, "Not a NIST file.\n") ;
|
||||
return SFE_NIST_BAD_HEADER ;
|
||||
} ;
|
||||
|
||||
if (sscanf (psf_header, "NIST_1A\n%d\n", &count) == 1)
|
||||
psf->dataoffset = count ;
|
||||
else
|
||||
{ psf_log_printf (psf, "*** Suspicious header length.\n") ;
|
||||
psf->dataoffset = NIST_HEADER_LENGTH ;
|
||||
} ;
|
||||
|
||||
/* Determine sample encoding, start by assuming PCM. */
|
||||
encoding = SF_FORMAT_PCM_U8 ;
|
||||
if ((cptr = strstr (psf_header, "sample_coding -s")))
|
||||
{ sscanf (cptr, "sample_coding -s%d %63s", &count, str) ;
|
||||
|
||||
if (strcmp (str, "pcm") == 0)
|
||||
{ /* Correct this later when we find out the bitwidth. */
|
||||
encoding = SF_FORMAT_PCM_U8 ;
|
||||
}
|
||||
else if (strcmp (str, "alaw") == 0)
|
||||
encoding = SF_FORMAT_ALAW ;
|
||||
else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0))
|
||||
encoding = SF_FORMAT_ULAW ;
|
||||
else
|
||||
{ psf_log_printf (psf, "*** Unknown encoding : %s\n", str) ;
|
||||
encoding = 0 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if ((cptr = strstr (psf_header, "channel_count -i ")) != NULL)
|
||||
sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ;
|
||||
|
||||
if ((cptr = strstr (psf_header, "sample_rate -i ")) != NULL)
|
||||
sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ;
|
||||
|
||||
if ((cptr = strstr (psf_header, "sample_count -i ")) != NULL)
|
||||
{ sscanf (cptr, "sample_count -i %ld", &samples) ;
|
||||
psf->sf.frames = samples ;
|
||||
} ;
|
||||
|
||||
if ((cptr = strstr (psf_header, "sample_n_bytes -i ")) != NULL)
|
||||
sscanf (cptr, "sample_n_bytes -i %d", &(psf->bytewidth)) ;
|
||||
|
||||
/* Default endian-ness (for 8 bit, u-law, A-law. */
|
||||
psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ;
|
||||
|
||||
/* This is where we figure out endian-ness. */
|
||||
if ((cptr = strstr (psf_header, "sample_byte_format -s"))
|
||||
&& sscanf (cptr, "sample_byte_format -s%u %8s", &bytes, str) == 2)
|
||||
{
|
||||
if (bytes != strlen (str))
|
||||
psf_log_printf (psf, "Weird sample_byte_format : strlen '%s' != %d\n", str, bytes) ;
|
||||
|
||||
if (bytes > 1)
|
||||
{ if (psf->bytewidth == 0)
|
||||
psf->bytewidth = bytes ;
|
||||
else if (psf->bytewidth - bytes != 0)
|
||||
{ psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ;
|
||||
return SFE_NIST_BAD_ENCODING ;
|
||||
} ;
|
||||
|
||||
if (strcmp (str, "01") == 0)
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
else if (strcmp (str, "10") == 0)
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
else
|
||||
{ psf_log_printf (psf, "Weird endian-ness : %s\n", str) ;
|
||||
return SFE_NIST_BAD_ENCODING ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
psf->sf.format |= psf->endian ;
|
||||
} ;
|
||||
|
||||
if ((cptr = strstr (psf_header, "sample_sig_bits -i ")))
|
||||
sscanf (cptr, "sample_sig_bits -i %d", &bitwidth) ;
|
||||
|
||||
if (strstr (psf_header, "channels_interleaved -s5 FALSE"))
|
||||
{ psf_log_printf (psf, "Non-interleaved data unsupported.\n", str) ;
|
||||
return SFE_NIST_BAD_ENCODING ;
|
||||
} ;
|
||||
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
if (encoding == SF_FORMAT_PCM_U8)
|
||||
{ switch (psf->bytewidth)
|
||||
{ case 1 :
|
||||
psf->sf.format |= SF_FORMAT_PCM_S8 ;
|
||||
break ;
|
||||
|
||||
case 2 :
|
||||
psf->sf.format |= SF_FORMAT_PCM_16 ;
|
||||
break ;
|
||||
|
||||
case 3 :
|
||||
psf->sf.format |= SF_FORMAT_PCM_24 ;
|
||||
break ;
|
||||
|
||||
case 4 :
|
||||
psf->sf.format |= SF_FORMAT_PCM_32 ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
}
|
||||
else if (encoding != 0)
|
||||
psf->sf.format |= encoding ;
|
||||
else
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
/* Sanitize psf->sf.format. */
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_ULAW :
|
||||
case SF_FORMAT_ALAW :
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
/* Blank out endian bits. */
|
||||
psf->sf.format = SF_FORMAT_NIST | SF_CODEC (psf->sf.format) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* nist_read_header */
|
||||
|
||||
static int
|
||||
nist_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
nist_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* nist_close */
|
||||
|
||||
/*=========================================================================
|
||||
*/
|
||||
|
||||
static int
|
||||
nist_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ const char *end_str ;
|
||||
long samples ;
|
||||
sf_count_t current ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
if (psf->bytewidth > 0)
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
end_str = "10" ;
|
||||
else if (psf->endian == SF_ENDIAN_LITTLE)
|
||||
end_str = "01" ;
|
||||
else
|
||||
end_str = "error" ;
|
||||
|
||||
/* Clear the whole header. */
|
||||
memset (psf->header, 0, sizeof (psf->header)) ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
psf_asciiheader_printf (psf, "NIST_1A\n 1024\n") ;
|
||||
psf_asciiheader_printf (psf, "channel_count -i %d\n", psf->sf.channels) ;
|
||||
psf_asciiheader_printf (psf, "sample_rate -i %d\n", psf->sf.samplerate) ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n") ;
|
||||
psf_asciiheader_printf (psf, "sample_n_bytes -i 1\n"
|
||||
"sample_sig_bits -i 8\n") ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
psf_asciiheader_printf (psf, "sample_n_bytes -i %d\n", psf->bytewidth) ;
|
||||
psf_asciiheader_printf (psf, "sample_sig_bits -i %d\n", psf->bytewidth * 8) ;
|
||||
psf_asciiheader_printf (psf, "sample_coding -s3 pcm\n"
|
||||
"sample_byte_format -s%d %s\n", psf->bytewidth, end_str) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
psf_asciiheader_printf (psf, "sample_coding -s4 alaw\n") ;
|
||||
psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
psf_asciiheader_printf (psf, "sample_coding -s4 ulaw\n") ;
|
||||
psf_asciiheader_printf (psf, "sample_n_bytes -s1 1\n") ;
|
||||
break ;
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = NIST_HEADER_LENGTH ;
|
||||
|
||||
/* Fix this */
|
||||
samples = psf->sf.frames ;
|
||||
psf_asciiheader_printf (psf, "sample_count -i %ld\n", samples) ;
|
||||
psf_asciiheader_printf (psf, "end_head\n") ;
|
||||
|
||||
/* Zero fill to dataoffset. */
|
||||
psf_binheader_writef (psf, "z", (size_t) (NIST_HEADER_LENGTH - psf->headindex)) ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* nist_write_header */
|
||||
|
||||
250
project/jni/sndfile/src/ogg.c
Normal file
250
project/jni/sndfile/src/ogg.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2007 John ffitch
|
||||
**
|
||||
** This program is free software ; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation ; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if HAVE_EXTERNAL_LIBS
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
static int ogg_close (SF_PRIVATE *psf) ;
|
||||
static int ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE * odata) ;
|
||||
static int ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og) ;
|
||||
|
||||
int
|
||||
ogg_open (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = calloc (1, sizeof (OGG_PRIVATE)) ;
|
||||
sf_count_t pos = psf_ftell (psf) ;
|
||||
int error = 0 ;
|
||||
|
||||
psf->container_data = odata ;
|
||||
psf->container_close = ogg_close ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
if ((error = ogg_stream_classify (psf, odata)) != 0)
|
||||
return error ;
|
||||
|
||||
/* Reset everything to an initial state. */
|
||||
ogg_sync_clear (&odata->osync) ;
|
||||
ogg_stream_clear (&odata->ostream) ;
|
||||
psf_fseek (psf, pos, SEEK_SET) ;
|
||||
|
||||
switch (psf->sf.format)
|
||||
{ case SF_FORMAT_OGG | SF_FORMAT_VORBIS :
|
||||
return ogg_vorbis_open (psf) ;
|
||||
|
||||
case SF_FORMAT_OGGFLAC :
|
||||
free (psf->container_data) ;
|
||||
psf->container_data = NULL ;
|
||||
psf->container_close = NULL ;
|
||||
return flac_open (psf) ;
|
||||
|
||||
#if ENABLE_EXPERIMENTAL_CODE
|
||||
case SF_FORMAT_OGG | SF_FORMAT_SPEEX :
|
||||
return ogg_speex_open (psf) ;
|
||||
|
||||
case SF_FORMAT_OGG | SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_OGG | SF_FORMAT_PCM_24 :
|
||||
return ogg_pcm_open (psf) ;
|
||||
#endif
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "%s : mode should be SFM_READ or SFM_WRITE.\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} /* ogg_open */
|
||||
|
||||
|
||||
static int
|
||||
ogg_close (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
|
||||
ogg_sync_clear (&odata->osync) ;
|
||||
ogg_stream_clear (&odata->ostream) ;
|
||||
|
||||
return 0 ;
|
||||
} /* ogg_close */
|
||||
|
||||
static int
|
||||
ogg_stream_classify (SF_PRIVATE *psf, OGG_PRIVATE* odata)
|
||||
{ char *buffer ;
|
||||
int bytes, nn ;
|
||||
|
||||
/* Call this here so it only gets called once, so no memory is leaked. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
|
||||
odata->eos = 0 ;
|
||||
|
||||
/* Weird stuff happens if these aren't called. */
|
||||
ogg_stream_reset (&odata->ostream) ;
|
||||
ogg_sync_reset (&odata->osync) ;
|
||||
|
||||
/*
|
||||
** Grab some data at the head of the stream. We want the first page
|
||||
** (which is guaranteed to be small and only contain the Vorbis
|
||||
** stream initial header) We need the first page to get the stream
|
||||
** serialno.
|
||||
*/
|
||||
|
||||
/* Expose the buffer */
|
||||
buffer = ogg_sync_buffer (&odata->osync, 4096L) ;
|
||||
|
||||
/* Grab the part of the header that has already been read. */
|
||||
memcpy (buffer, psf->header, psf->headindex) ;
|
||||
bytes = psf->headindex ;
|
||||
|
||||
/* Submit a 4k block to libvorbis' Ogg layer */
|
||||
bytes += psf_fread (buffer + psf->headindex, 1, 4096 - psf->headindex, psf) ;
|
||||
ogg_sync_wrote (&odata->osync, bytes) ;
|
||||
|
||||
/* Get the first page. */
|
||||
if ((nn = ogg_sync_pageout (&odata->osync, &odata->opage)) != 1)
|
||||
{
|
||||
/* Have we simply run out of data? If so, we're done. */
|
||||
if (bytes < 4096)
|
||||
return 0 ;
|
||||
|
||||
/* Error case. Must not be Vorbis data */
|
||||
psf_log_printf (psf, "Input does not appear to be an Ogg bitstream.\n") ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Get the serial number and set up the rest of decode.
|
||||
** Serialno first ; use it to set up a logical stream.
|
||||
*/
|
||||
ogg_stream_clear (&odata->ostream) ;
|
||||
ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
|
||||
|
||||
if (ogg_stream_pagein (&odata->ostream, &odata->opage) < 0)
|
||||
{ /* Error ; stream version mismatch perhaps. */
|
||||
psf_log_printf (psf, "Error reading first page of Ogg bitstream data\n") ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
if (ogg_stream_packetout (&odata->ostream, &odata->opacket) != 1)
|
||||
{ /* No page? must not be vorbis. */
|
||||
psf_log_printf (psf, "Error reading initial header packet.\n") ;
|
||||
return SFE_MALFORMED_FILE ;
|
||||
} ;
|
||||
|
||||
odata->codec = ogg_page_classify (psf, &odata->opage) ;
|
||||
|
||||
switch (odata->codec)
|
||||
{ case OGG_VORBIS :
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_VORBIS ;
|
||||
return 0 ;
|
||||
|
||||
case OGG_FLAC :
|
||||
case OGG_FLAC0 :
|
||||
psf->sf.format = SF_FORMAT_OGGFLAC ;
|
||||
return 0 ;
|
||||
|
||||
case OGG_SPEEX :
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
|
||||
return 0 ;
|
||||
|
||||
case OGG_PCM :
|
||||
psf_log_printf (psf, "Detected Ogg/PCM data. This is not supported yet.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "This Ogg bitstream contains some uknown data type.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_stream_classify */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
static struct
|
||||
{ const char *str, *name ;
|
||||
int len, codec ;
|
||||
} codec_lookup [] =
|
||||
{ { "Annodex", "Annodex", 8, OGG_ANNODEX },
|
||||
{ "AnxData", "AnxData", 7, OGG_ANXDATA },
|
||||
{ "\177FLAC", "Flac1", 5, OGG_FLAC },
|
||||
{ "fLaC", "Flac0", 4, OGG_FLAC0 },
|
||||
{ "PCM ", "PCM", 8, OGG_PCM },
|
||||
{ "Speex", "Speex", 5, OGG_SPEEX },
|
||||
{ "\001vorbis", "Vorbis", 7, OGG_VORBIS },
|
||||
} ;
|
||||
|
||||
static int
|
||||
ogg_page_classify (SF_PRIVATE * psf, const ogg_page * og)
|
||||
{ int k, len ;
|
||||
|
||||
for (k = 0 ; k < ARRAY_LEN (codec_lookup) ; k++)
|
||||
{ if (codec_lookup [k].len > og->body_len)
|
||||
continue ;
|
||||
|
||||
if (memcmp (og->body, codec_lookup [k].str, codec_lookup [k].len) == 0)
|
||||
{ psf_log_printf (psf, "Ogg stream data : %s\n", codec_lookup [k].name) ;
|
||||
psf_log_printf (psf, "Stream serialno : %010D\n", (int64_t) ogg_page_serialno (og)) ;
|
||||
return codec_lookup [k].codec ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
len = og->body_len < 8 ? og->body_len : 8 ;
|
||||
|
||||
psf_log_printf (psf, "Ogg_stream data : '") ;
|
||||
for (k = 0 ; k < len ; k++)
|
||||
psf_log_printf (psf, "%c", isprint (og->body [k]) ? og->body [k] : '.') ;
|
||||
psf_log_printf (psf, "' ") ;
|
||||
for (k = 0 ; k < len ; k++)
|
||||
psf_log_printf (psf, " %02x", og->body [k] & 0xff) ;
|
||||
psf_log_printf (psf, "\n") ;
|
||||
|
||||
return 0 ;
|
||||
} /* ogg_page_classify */
|
||||
|
||||
#else /* HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
ogg_open (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Vorbis support.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_open */
|
||||
|
||||
#endif
|
||||
52
project/jni/sndfile/src/ogg.h
Normal file
52
project/jni/sndfile/src/ogg.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software ; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation ; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 SF_SRC_OGG_H
|
||||
|
||||
enum
|
||||
{ OGG_ANNODEX = 300,
|
||||
OGG_ANXDATA,
|
||||
OGG_FLAC,
|
||||
OGG_FLAC0,
|
||||
OGG_PCM,
|
||||
OGG_SPEEX,
|
||||
OGG_VORBIS,
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ /* Sync and verify incoming physical bitstream */
|
||||
ogg_sync_state osync ;
|
||||
/* Take physical pages, weld into a logical stream of packets */
|
||||
ogg_stream_state ostream ;
|
||||
/* One Ogg bitstream page. Vorbis packets are inside */
|
||||
ogg_page opage ;
|
||||
/* One raw packet of data for decode */
|
||||
ogg_packet opacket ;
|
||||
int eos ;
|
||||
int codec ;
|
||||
} OGG_PRIVATE ;
|
||||
|
||||
|
||||
#define readint(buf, base) (((buf [base + 3] << 24) & 0xff000000) | \
|
||||
((buf [base + 2] <<16) & 0xff0000) | \
|
||||
((buf [base + 1] << 8) & 0xff00) | \
|
||||
(buf [base] & 0xff))
|
||||
|
||||
|
||||
|
||||
#endif /* SF_SRC_OGG_H */
|
||||
164
project/jni/sndfile/src/ogg_pcm.c
Normal file
164
project/jni/sndfile/src/ogg_pcm.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software ; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation ; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS)
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
typedef struct
|
||||
{ int32_t serialno ;
|
||||
|
||||
|
||||
void * state ;
|
||||
} OPCM_PRIVATE ;
|
||||
|
||||
static int opcm_read_header (SF_PRIVATE * psf) ;
|
||||
static int opcm_close (SF_PRIVATE *psf) ;
|
||||
|
||||
int
|
||||
ogg_pcm_open (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
OPCM_PRIVATE* opcm = calloc (1, sizeof (OPCM_PRIVATE)) ;
|
||||
int error = 0 ;
|
||||
|
||||
if (odata == NULL)
|
||||
{ psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->codec_data = opcm ;
|
||||
if (opcm == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ /* Call this here so it only gets called once, so no memory is leaked. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
|
||||
if ((error = opcm_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
#if 0
|
||||
psf->read_short = opcm_read_s ;
|
||||
psf->read_int = opcm_read_i ;
|
||||
psf->read_float = opcm_read_f ;
|
||||
psf->read_double = opcm_read_d ;
|
||||
psf->sf.frames = opcm_length (psf) ;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
psf->codec_close = opcm_close ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{
|
||||
#if 0
|
||||
/* Set the default opcm quality here. */
|
||||
vdata->quality = 0.4 ;
|
||||
|
||||
psf->write_header = opcm_write_header ;
|
||||
psf->write_short = opcm_write_s ;
|
||||
psf->write_int = opcm_write_i ;
|
||||
psf->write_float = opcm_write_f ;
|
||||
psf->write_double = opcm_write_d ;
|
||||
#endif
|
||||
|
||||
psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
|
||||
psf->str_flags = SF_STR_ALLOW_START ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
#if 0
|
||||
psf->seek = opcm_seek ;
|
||||
psf->command = opcm_command ;
|
||||
#endif
|
||||
|
||||
/* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
psf->datalength = 1 ;
|
||||
psf->dataoffset = 0 ;
|
||||
/* End FIXME. */
|
||||
|
||||
return error ;
|
||||
} /* ogg_pcm_open */
|
||||
|
||||
static int
|
||||
opcm_read_header (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* opcm_read_header */
|
||||
|
||||
static int
|
||||
opcm_close (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
|
||||
|
||||
return 0 ;
|
||||
} /* opcm_close */
|
||||
|
||||
|
||||
|
||||
/*
|
||||
encoded_speex_frames = (frames_per_packet * Packets)
|
||||
= 1 * 272
|
||||
= 272
|
||||
|
||||
audio_samples = encoded_speex_frames * frame_size
|
||||
= 272 * 640
|
||||
= 174080
|
||||
|
||||
duration = audio_samples / rate
|
||||
= 174080 / 44100
|
||||
= 3.947
|
||||
*/
|
||||
|
||||
#else /* ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
ogg_pcm_open (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Speex support.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_pcm_open */
|
||||
|
||||
#endif
|
||||
425
project/jni/sndfile/src/ogg_speex.c
Normal file
425
project/jni/sndfile/src/ogg_speex.c
Normal file
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software ; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation ; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
|
||||
#if HAVE_UNISTD_H
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS)
|
||||
|
||||
#include <ogg/ogg.h>
|
||||
|
||||
#include <speex/speex.h>
|
||||
#include <speex/speex_stereo.h>
|
||||
#include <speex/speex_header.h>
|
||||
#include <speex/speex_callbacks.h>
|
||||
|
||||
#include "ogg.h"
|
||||
|
||||
#define OGG_SPX_READ_SIZE 200
|
||||
|
||||
typedef struct
|
||||
{ SpeexBits bits ;
|
||||
|
||||
int32_t serialno ;
|
||||
|
||||
int frame_size, granule_frame_size, nframes ;
|
||||
int force_mode ;
|
||||
|
||||
SpeexStereoState stereo ;
|
||||
SpeexHeader header ;
|
||||
|
||||
void * state ;
|
||||
} SPX_PRIVATE ;
|
||||
|
||||
static int spx_read_header (SF_PRIVATE * psf) ;
|
||||
static int spx_close (SF_PRIVATE *psf) ;
|
||||
static void *spx_header_read (SF_PRIVATE * psf, ogg_packet *op, spx_int32_t enh_enabled, int force_mode) ;
|
||||
static void spx_print_comments (const char *comments, int length) ;
|
||||
|
||||
int
|
||||
ogg_speex_open (SF_PRIVATE *psf)
|
||||
{ OGG_PRIVATE* odata = psf->container_data ;
|
||||
SPX_PRIVATE* spx = calloc (1, sizeof (SPX_PRIVATE)) ;
|
||||
int error = 0 ;
|
||||
|
||||
if (odata == NULL)
|
||||
{ psf_log_printf (psf, "%s : odata is NULL???\n", __func__) ;
|
||||
return SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->codec_data = spx ;
|
||||
if (spx == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
return SFE_BAD_MODE_RW ;
|
||||
|
||||
if (psf->file.mode == SFM_READ)
|
||||
{ /* Call this here so it only gets called once, so no memory is leaked. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
|
||||
if ((error = spx_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
#if 0
|
||||
psf->read_short = spx_read_s ;
|
||||
psf->read_int = spx_read_i ;
|
||||
psf->read_float = spx_read_f ;
|
||||
psf->read_double = spx_read_d ;
|
||||
psf->sf.frames = spx_length (psf) ;
|
||||
#endif
|
||||
} ;
|
||||
|
||||
psf->codec_close = spx_close ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{
|
||||
#if 0
|
||||
/* Set the default spx quality here. */
|
||||
vdata->quality = 0.4 ;
|
||||
|
||||
psf->write_header = spx_write_header ;
|
||||
psf->write_short = spx_write_s ;
|
||||
psf->write_int = spx_write_i ;
|
||||
psf->write_float = spx_write_f ;
|
||||
psf->write_double = spx_write_d ;
|
||||
#endif
|
||||
|
||||
psf->sf.frames = SF_COUNT_MAX ; /* Unknown really */
|
||||
psf->str_flags = SF_STR_ALLOW_START ;
|
||||
} ;
|
||||
|
||||
psf->bytewidth = 1 ;
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
#if 0
|
||||
psf->seek = spx_seek ;
|
||||
psf->command = spx_command ;
|
||||
#endif
|
||||
|
||||
/* FIXME, FIXME, FIXME : Hack these here for now and correct later. */
|
||||
psf->sf.format = SF_FORMAT_OGG | SF_FORMAT_SPEEX ;
|
||||
psf->sf.sections = 1 ;
|
||||
|
||||
psf->datalength = 1 ;
|
||||
psf->dataoffset = 0 ;
|
||||
/* End FIXME. */
|
||||
|
||||
return error ;
|
||||
} /* ogg_speex_open */
|
||||
|
||||
#define le_short (x) (x)
|
||||
|
||||
static int
|
||||
spx_read_header (SF_PRIVATE * psf)
|
||||
{ static SpeexStereoState STEREO_INIT = SPEEX_STEREO_STATE_INIT ;
|
||||
|
||||
OGG_PRIVATE* odata = psf->container_data ;
|
||||
SPX_PRIVATE* spx = psf->codec_data ;
|
||||
|
||||
ogg_int64_t page_granule = 0 ;
|
||||
int stream_init = 0 ;
|
||||
int page_nb_packets = 0 ;
|
||||
int packet_count = 0 ;
|
||||
int enh_enabled = 1 ;
|
||||
int force_mode = -1 ;
|
||||
char * data ;
|
||||
int nb_read ;
|
||||
int lookahead ;
|
||||
|
||||
printf ("%s %d\n", __func__, __LINE__) ;
|
||||
|
||||
psf_log_printf (psf, "Speex header\n") ;
|
||||
odata->eos = 0 ;
|
||||
|
||||
/* Reset ogg stuff which has already been used in src/ogg.c. */
|
||||
ogg_stream_reset (&odata->ostream) ;
|
||||
ogg_sync_reset (&odata->osync) ;
|
||||
|
||||
/* Seek to start of stream. */
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
/* Initialize. */
|
||||
ogg_sync_init (&odata->osync) ;
|
||||
speex_bits_init (&spx->bits) ;
|
||||
|
||||
/* Set defaults. */
|
||||
psf->sf.channels = -1 ;
|
||||
psf->sf.samplerate = 0 ;
|
||||
spx->stereo = STEREO_INIT ;
|
||||
|
||||
/* Get a pointer to the ogg buffer and read data into it. */
|
||||
data = ogg_sync_buffer (&odata->osync, OGG_SPX_READ_SIZE) ;
|
||||
nb_read = psf_fread (data, 1, OGG_SPX_READ_SIZE, psf) ;
|
||||
ogg_sync_wrote (&odata->osync, nb_read) ;
|
||||
|
||||
/* Now we chew on Ogg packets. */
|
||||
while (ogg_sync_pageout (&odata->osync, &odata->opage) == 1)
|
||||
{ if (stream_init == 0)
|
||||
{ ogg_stream_init (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
|
||||
stream_init = 1 ;
|
||||
} ;
|
||||
|
||||
if (ogg_page_serialno (&odata->opage) != odata->ostream.serialno)
|
||||
{ /* so all streams are read. */
|
||||
ogg_stream_reset_serialno (&odata->ostream, ogg_page_serialno (&odata->opage)) ;
|
||||
} ;
|
||||
|
||||
/*Add page to the bitstream*/
|
||||
ogg_stream_pagein (&odata->ostream, &odata->opage) ;
|
||||
page_granule = ogg_page_granulepos (&odata->opage) ;
|
||||
page_nb_packets = ogg_page_packets (&odata->opage) ;
|
||||
|
||||
/*Extract all available packets*/
|
||||
while (odata->eos == 0 && ogg_stream_packetout (&odata->ostream, &odata->opacket) == 1)
|
||||
{ if (odata->opacket.bytes >= 8 && memcmp (odata->opacket.packet, "Speex ", 8) == 0)
|
||||
{ spx->serialno = odata->ostream.serialno ;
|
||||
} ;
|
||||
|
||||
if (spx->serialno == -1 || odata->ostream.serialno != spx->serialno)
|
||||
break ;
|
||||
|
||||
if (packet_count == 0)
|
||||
{ spx->state = spx_header_read (psf, &odata->opacket, enh_enabled, force_mode) ;
|
||||
if (! spx->state)
|
||||
break ;
|
||||
|
||||
speex_decoder_ctl (spx->state, SPEEX_GET_LOOKAHEAD, &lookahead) ;
|
||||
if (spx->nframes == 0)
|
||||
spx->nframes = 1 ;
|
||||
}
|
||||
else if (packet_count == 1)
|
||||
{ spx_print_comments ((const char*) odata->opacket.packet, odata->opacket.bytes) ;
|
||||
}
|
||||
else if (packet_count < 2 + spx->header.extra_headers)
|
||||
{ /* Ignore extra headers */
|
||||
}
|
||||
packet_count ++ ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "End\n") ;
|
||||
|
||||
psf_log_printf (psf, "packet_count %d\n", packet_count) ;
|
||||
psf_log_printf (psf, "page_nb_packets %d\n", page_nb_packets) ;
|
||||
psf_log_printf (psf, "page_granule %lld\n", page_granule) ;
|
||||
|
||||
return 0 ;
|
||||
} /* spx_read_header */
|
||||
|
||||
static int
|
||||
spx_close (SF_PRIVATE *psf)
|
||||
{ SPX_PRIVATE* spx = psf->codec_data ;
|
||||
|
||||
if (spx->state)
|
||||
speex_decoder_destroy (spx->state) ;
|
||||
|
||||
if (spx)
|
||||
speex_bits_destroy (&spx->bits) ;
|
||||
|
||||
return 0 ;
|
||||
} /* spx_close */
|
||||
|
||||
|
||||
|
||||
static void *
|
||||
spx_header_read (SF_PRIVATE * psf, ogg_packet *op, spx_int32_t enh_enabled, int force_mode)
|
||||
{ SPX_PRIVATE* spx = psf->codec_data ;
|
||||
void *st ;
|
||||
const SpeexMode *mode ;
|
||||
SpeexHeader *tmp_header ;
|
||||
int modeID ;
|
||||
SpeexCallback callback ;
|
||||
|
||||
tmp_header = speex_packet_to_header ((char*) op->packet, op->bytes) ;
|
||||
if (tmp_header == NULL)
|
||||
{ psf_log_printf (psf, "Cannot read Speex header\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
memcpy (&spx->header, tmp_header, sizeof (spx->header)) ;
|
||||
free (tmp_header) ;
|
||||
tmp_header = NULL ;
|
||||
|
||||
if (spx->header.mode >= SPEEX_NB_MODES || spx->header.mode < 0)
|
||||
{ psf_log_printf (psf, "Mode number %d does not (yet/any longer) exist in this version\n", spx->header.mode) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
modeID = spx->header.mode ;
|
||||
if (force_mode != -1)
|
||||
modeID = force_mode ;
|
||||
|
||||
mode = speex_lib_get_mode (modeID) ;
|
||||
|
||||
if (spx->header.speex_version_id > 1)
|
||||
{ psf_log_printf (psf, "This file was encoded with Speex bit-stream version %d, which I don't know how to decode\n", spx->header.speex_version_id) ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
if (mode->bitstream_version < spx->header.mode_bitstream_version)
|
||||
{ psf_log_printf (psf, "The file was encoded with a newer version of Speex. You need to upgrade in order to play it.\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
if (mode->bitstream_version > spx->header.mode_bitstream_version)
|
||||
{ psf_log_printf (psf, "The file was encoded with an older version of Speex. You would need to downgrade the version in order to play it.\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
st = speex_decoder_init (mode) ;
|
||||
if (!st)
|
||||
{ psf_log_printf (psf, "Decoder initialization failed.\n") ;
|
||||
return NULL ;
|
||||
} ;
|
||||
|
||||
speex_decoder_ctl (st, SPEEX_SET_ENH, &enh_enabled) ;
|
||||
speex_decoder_ctl (st, SPEEX_GET_FRAME_SIZE, &spx->frame_size) ;
|
||||
spx->granule_frame_size = spx->frame_size ;
|
||||
|
||||
if (!psf->sf.samplerate)
|
||||
psf->sf.samplerate = spx->header.rate ;
|
||||
/* Adjust rate if --force-* options are used */
|
||||
if (force_mode!=-1)
|
||||
{ if (spx->header.mode < force_mode)
|
||||
{ psf->sf.samplerate <<= (force_mode - spx->header.mode) ;
|
||||
spx->granule_frame_size >>= (force_mode - spx->header.mode) ;
|
||||
} ;
|
||||
if (spx->header.mode > force_mode)
|
||||
{ psf->sf.samplerate >>= (spx->header.mode - force_mode) ;
|
||||
spx->granule_frame_size <<= (spx->header.mode - force_mode) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
speex_decoder_ctl (st, SPEEX_SET_SAMPLING_RATE, &psf->sf.samplerate) ;
|
||||
|
||||
spx->nframes = spx->header.frames_per_packet ;
|
||||
|
||||
if (psf->sf.channels == -1)
|
||||
psf->sf.channels = spx->header.nb_channels ;
|
||||
|
||||
if (! (psf->sf.channels == 1))
|
||||
{ psf->sf.channels = 2 ;
|
||||
callback.callback_id = SPEEX_INBAND_STEREO ;
|
||||
callback.func = speex_std_stereo_request_handler ;
|
||||
callback.data = &spx->stereo ;
|
||||
speex_decoder_ctl (st, SPEEX_SET_HANDLER, &callback) ;
|
||||
} ;
|
||||
|
||||
spx->header.speex_version [sizeof (spx->header.speex_version) - 1] = 0 ;
|
||||
|
||||
psf_log_printf (psf, " Encoder ver : %s\n Frames/packet : %d\n",
|
||||
spx->header.speex_version, spx->header.frames_per_packet) ;
|
||||
|
||||
if (spx->header.bitrate > 0)
|
||||
psf_log_printf (psf, " Bit rate : %d\n", spx->header.bitrate) ;
|
||||
|
||||
psf_log_printf (psf, " Sample rate : %d\n Mode : %s\n VBR : %s\n Channels : %d\n",
|
||||
psf->sf.samplerate, mode->modeName, (spx->header.vbr ? "yes" : "no"), psf->sf.channels) ;
|
||||
|
||||
psf_log_printf (psf, " Extra headers : %d\n", spx->header.extra_headers) ;
|
||||
|
||||
return st ;
|
||||
} /* spx_header_read */
|
||||
|
||||
|
||||
static void
|
||||
spx_print_comments (const char *c, int length)
|
||||
{
|
||||
const char *end ;
|
||||
int len, i, nb_fields ;
|
||||
|
||||
printf ("%s %d\n", __func__, __LINE__) ;
|
||||
if (length<8)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
end = c + length ;
|
||||
len = readint (c, 0) ;
|
||||
c += 4 ;
|
||||
if (len < 0 || c + len > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
(void) fwrite (c, 1, len, stderr) ;
|
||||
c += len ;
|
||||
fprintf (stderr, "\n") ;
|
||||
if (c + 4 > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
nb_fields = readint (c, 0) ;
|
||||
c += 4 ;
|
||||
for (i = 0 ; i < nb_fields ; i++)
|
||||
{ if (c+4>end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
} ;
|
||||
len = readint (c, 0) ;
|
||||
c += 4 ;
|
||||
if (len < 0 || c + len > end)
|
||||
{ fprintf (stderr, "Invalid/corrupted comments\n") ;
|
||||
return ;
|
||||
}
|
||||
(void) fwrite (c, 1, len, stderr) ;
|
||||
c += len ;
|
||||
fprintf (stderr, "\n") ;
|
||||
} ;
|
||||
return ;
|
||||
} /* spx_print_comments */
|
||||
|
||||
|
||||
/*
|
||||
encoded_speex_frames = (frames_per_packet * Packets)
|
||||
= 1 * 272
|
||||
= 272
|
||||
|
||||
audio_samples = encoded_speex_frames * frame_size
|
||||
= 272 * 640
|
||||
= 174080
|
||||
|
||||
duration = audio_samples / rate
|
||||
= 174080 / 44100
|
||||
= 3.947
|
||||
*/
|
||||
|
||||
#else /* ENABLE_EXPERIMENTAL_CODE && HAVE_EXTERNAL_LIBS */
|
||||
|
||||
int
|
||||
ogg_speex_open (SF_PRIVATE *psf)
|
||||
{
|
||||
psf_log_printf (psf, "This version of libsndfile was compiled without Ogg/Speex support.\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} /* ogg_speex_open */
|
||||
|
||||
#endif
|
||||
1142
project/jni/sndfile/src/ogg_vorbis.c
Normal file
1142
project/jni/sndfile/src/ogg_vorbis.c
Normal file
File diff suppressed because it is too large
Load Diff
832
project/jni/sndfile/src/paf.c
Normal file
832
project/jni/sndfile/src/paf.c
Normal file
@@ -0,0 +1,832 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define FAP_MARKER (MAKE_MARKER ('f', 'a', 'p', ' '))
|
||||
#define PAF_MARKER (MAKE_MARKER (' ', 'p', 'a', 'f'))
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Other defines.
|
||||
*/
|
||||
|
||||
#define PAF_HEADER_LENGTH 2048
|
||||
|
||||
#define PAF24_SAMPLES_PER_BLOCK 10
|
||||
#define PAF24_BLOCK_SIZE 32
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int version ;
|
||||
int endianness ;
|
||||
int samplerate ;
|
||||
int format ;
|
||||
int channels ;
|
||||
int source ;
|
||||
} PAF_FMT ;
|
||||
|
||||
typedef struct
|
||||
{ int max_blocks, channels, samplesperblock, blocksize ;
|
||||
int read_block, write_block, read_count, write_count ;
|
||||
sf_count_t sample_count ;
|
||||
int *samples ;
|
||||
unsigned char *block ;
|
||||
#if HAVE_FLEXIBLE_ARRAY
|
||||
int data [] ; /* ISO C99 struct flexible array. */
|
||||
#else
|
||||
int data [1] ; /* This is a hack and may not work. */
|
||||
#endif
|
||||
} PAF24_PRIVATE ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int paf24_init (SF_PRIVATE *psf) ;
|
||||
|
||||
static int paf_read_header (SF_PRIVATE *psf) ;
|
||||
static int paf_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
|
||||
static sf_count_t paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len) ;
|
||||
static sf_count_t paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len) ;
|
||||
static sf_count_t paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len) ;
|
||||
static sf_count_t paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
|
||||
enum
|
||||
{ PAF_PCM_16 = 0,
|
||||
PAF_PCM_24 = 1,
|
||||
PAF_PCM_S8 = 2
|
||||
} ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
paf_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error, endian ;
|
||||
|
||||
psf->dataoffset = PAF_HEADER_LENGTH ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = paf_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_PAF)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
endian = SF_ENDIAN (psf->sf.format) ;
|
||||
|
||||
/* PAF is by default big endian. */
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && (endian == SF_ENDIAN_CPU)))
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
if ((error = paf_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
|
||||
psf->write_header = paf_write_header ;
|
||||
} ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
psf->bytewidth = 1 ;
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
psf->bytewidth = 2 ;
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_24 :
|
||||
/* No bytewidth because of whacky 24 bit encoding. */
|
||||
error = paf24_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : return SFE_PAF_UNKNOWN_FORMAT ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* paf_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
paf_read_header (SF_PRIVATE *psf)
|
||||
{ PAF_FMT paf_fmt ;
|
||||
int marker ;
|
||||
|
||||
if (psf->filelength < PAF_HEADER_LENGTH)
|
||||
return SFE_PAF_SHORT_HEADER ;
|
||||
|
||||
memset (&paf_fmt, 0, sizeof (paf_fmt)) ;
|
||||
psf_binheader_readf (psf, "pm", 0, &marker) ;
|
||||
|
||||
psf_log_printf (psf, "Signature : '%M'\n", marker) ;
|
||||
|
||||
if (marker == PAF_MARKER)
|
||||
{ psf_binheader_readf (psf, "E444444", &(paf_fmt.version), &(paf_fmt.endianness),
|
||||
&(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ;
|
||||
}
|
||||
else if (marker == FAP_MARKER)
|
||||
{ psf_binheader_readf (psf, "e444444", &(paf_fmt.version), &(paf_fmt.endianness),
|
||||
&(paf_fmt.samplerate), &(paf_fmt.format), &(paf_fmt.channels), &(paf_fmt.source)) ;
|
||||
}
|
||||
else
|
||||
return SFE_PAF_NO_MARKER ;
|
||||
|
||||
psf_log_printf (psf, "Version : %d\n", paf_fmt.version) ;
|
||||
|
||||
if (paf_fmt.version != 0)
|
||||
{ psf_log_printf (psf, "*** Bad version number. should be zero.\n") ;
|
||||
return SFE_PAF_VERSION ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "Sample Rate : %d\n", paf_fmt.samplerate) ;
|
||||
psf_log_printf (psf, "Channels : %d\n", paf_fmt.channels) ;
|
||||
|
||||
psf_log_printf (psf, "Endianness : %d => ", paf_fmt.endianness) ;
|
||||
if (paf_fmt.endianness)
|
||||
{ psf_log_printf (psf, "Little\n", paf_fmt.endianness) ;
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
}
|
||||
else
|
||||
{ psf_log_printf (psf, "Big\n", paf_fmt.endianness) ;
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
} ;
|
||||
|
||||
if (paf_fmt.channels > SF_MAX_CHANNELS)
|
||||
return SFE_PAF_BAD_CHANNELS ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
psf_binheader_readf (psf, "p", (int) psf->dataoffset) ;
|
||||
|
||||
psf->sf.samplerate = paf_fmt.samplerate ;
|
||||
psf->sf.channels = paf_fmt.channels ;
|
||||
|
||||
/* Only fill in type major. */
|
||||
psf->sf.format = SF_FORMAT_PAF ;
|
||||
|
||||
psf_log_printf (psf, "Format : %d => ", paf_fmt.format) ;
|
||||
|
||||
/* PAF is by default big endian. */
|
||||
psf->sf.format |= paf_fmt.endianness ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ;
|
||||
|
||||
switch (paf_fmt.format)
|
||||
{ case PAF_PCM_S8 :
|
||||
psf_log_printf (psf, "8 bit linear PCM\n") ;
|
||||
psf->bytewidth = 1 ;
|
||||
|
||||
psf->sf.format |= SF_FORMAT_PCM_S8 ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
break ;
|
||||
|
||||
case PAF_PCM_16 :
|
||||
psf_log_printf (psf, "16 bit linear PCM\n") ;
|
||||
psf->bytewidth = 2 ;
|
||||
|
||||
psf->sf.format |= SF_FORMAT_PCM_16 ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
break ;
|
||||
|
||||
case PAF_PCM_24 :
|
||||
psf_log_printf (psf, "24 bit linear PCM\n") ;
|
||||
psf->bytewidth = 3 ;
|
||||
|
||||
psf->sf.format |= SF_FORMAT_PCM_24 ;
|
||||
|
||||
psf->blockwidth = 0 ;
|
||||
psf->sf.frames = PAF24_SAMPLES_PER_BLOCK * psf->datalength /
|
||||
(PAF24_BLOCK_SIZE * psf->sf.channels) ;
|
||||
break ;
|
||||
|
||||
default : psf_log_printf (psf, "Unknown\n") ;
|
||||
return SFE_PAF_UNKNOWN_FORMAT ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "Source : %d => ", paf_fmt.source) ;
|
||||
|
||||
switch (paf_fmt.source)
|
||||
{ case 1 : psf_log_printf (psf, "Analog Recording\n") ;
|
||||
break ;
|
||||
case 2 : psf_log_printf (psf, "Digital Transfer\n") ;
|
||||
break ;
|
||||
case 3 : psf_log_printf (psf, "Multi-track Mixdown\n") ;
|
||||
break ;
|
||||
case 5 : psf_log_printf (psf, "Audio Resulting From DSP Processing\n") ;
|
||||
break ;
|
||||
default : psf_log_printf (psf, "Unknown\n") ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* paf_read_header */
|
||||
|
||||
static int
|
||||
paf_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
|
||||
{ int paf_format ;
|
||||
|
||||
/* PAF header already written so no need to re-write. */
|
||||
if (psf_ftell (psf) >= PAF_HEADER_LENGTH)
|
||||
return 0 ;
|
||||
|
||||
psf->dataoffset = PAF_HEADER_LENGTH ;
|
||||
|
||||
switch (SF_CODEC (psf->sf.format))
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
paf_format = PAF_PCM_S8 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
paf_format = PAF_PCM_16 ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_24 :
|
||||
paf_format = PAF_PCM_24 ;
|
||||
break ;
|
||||
|
||||
default : return SFE_PAF_UNKNOWN_FORMAT ;
|
||||
} ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
{ /* Marker, version, endianness, samplerate */
|
||||
psf_binheader_writef (psf, "Em444", PAF_MARKER, 0, 0, psf->sf.samplerate) ;
|
||||
/* format, channels, source */
|
||||
psf_binheader_writef (psf, "E444", paf_format, psf->sf.channels, 0) ;
|
||||
}
|
||||
else if (psf->endian == SF_ENDIAN_LITTLE)
|
||||
{ /* Marker, version, endianness, samplerate */
|
||||
psf_binheader_writef (psf, "em444", FAP_MARKER, 0, 1, psf->sf.samplerate) ;
|
||||
/* format, channels, source */
|
||||
psf_binheader_writef (psf, "e444", paf_format, psf->sf.channels, 0) ;
|
||||
} ;
|
||||
|
||||
/* Zero fill to dataoffset. */
|
||||
psf_binheader_writef (psf, "z", (size_t) (psf->dataoffset - psf->headindex)) ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* paf_write_header */
|
||||
|
||||
/*===============================================================================
|
||||
** 24 bit PAF files have a really weird encoding.
|
||||
** For a mono file, 10 samples (each being 3 bytes) are packed into a 32 byte
|
||||
** block. The 8 ints in this 32 byte block are then endian swapped (as ints)
|
||||
** if necessary before being written to disk.
|
||||
** For a stereo file, blocks of 10 samples from the same channel are encoded
|
||||
** into 32 bytes as for the mono case. The 32 byte blocks are then interleaved
|
||||
** on disk.
|
||||
** Reading has to reverse the above process :-).
|
||||
** Weird!!!
|
||||
**
|
||||
** The code below attempts to gain efficiency while maintaining readability.
|
||||
*/
|
||||
|
||||
static int paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ;
|
||||
static int paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24) ;
|
||||
static int paf24_close (SF_PRIVATE *psf) ;
|
||||
|
||||
|
||||
static int
|
||||
paf24_init (SF_PRIVATE *psf)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int paf24size ;
|
||||
|
||||
paf24size = sizeof (PAF24_PRIVATE) + psf->sf.channels *
|
||||
(PAF24_BLOCK_SIZE + PAF24_SAMPLES_PER_BLOCK * sizeof (int)) ;
|
||||
|
||||
/*
|
||||
** Not exatly sure why this needs to be here but the tests
|
||||
** fail without it.
|
||||
*/
|
||||
psf->last_op = 0 ;
|
||||
|
||||
if (! (psf->codec_data = calloc (1, paf24size)))
|
||||
return SFE_MALLOC_FAILED ;
|
||||
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
ppaf24->channels = psf->sf.channels ;
|
||||
ppaf24->samples = ppaf24->data ;
|
||||
ppaf24->block = (unsigned char*) (ppaf24->data + PAF24_SAMPLES_PER_BLOCK * ppaf24->channels) ;
|
||||
|
||||
ppaf24->blocksize = PAF24_BLOCK_SIZE * ppaf24->channels ;
|
||||
ppaf24->samplesperblock = PAF24_SAMPLES_PER_BLOCK ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || psf->file.mode == SFM_RDWR)
|
||||
{ paf24_read_block (psf, ppaf24) ; /* Read first block. */
|
||||
|
||||
psf->read_short = paf24_read_s ;
|
||||
psf->read_int = paf24_read_i ;
|
||||
psf->read_float = paf24_read_f ;
|
||||
psf->read_double = paf24_read_d ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ psf->write_short = paf24_write_s ;
|
||||
psf->write_int = paf24_write_i ;
|
||||
psf->write_float = paf24_write_f ;
|
||||
psf->write_double = paf24_write_d ;
|
||||
} ;
|
||||
|
||||
psf->seek = paf24_seek ;
|
||||
psf->container_close = paf24_close ;
|
||||
|
||||
psf->filelength = psf_get_filelen (psf) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->datalength % PAF24_BLOCK_SIZE)
|
||||
{ if (psf->file.mode == SFM_READ)
|
||||
psf_log_printf (psf, "*** Warning : file seems to be truncated.\n") ;
|
||||
ppaf24->max_blocks = psf->datalength / ppaf24->blocksize + 1 ;
|
||||
}
|
||||
else
|
||||
ppaf24->max_blocks = psf->datalength / ppaf24->blocksize ;
|
||||
|
||||
ppaf24->read_block = 0 ;
|
||||
if (psf->file.mode == SFM_RDWR)
|
||||
ppaf24->write_block = ppaf24->max_blocks ;
|
||||
else
|
||||
ppaf24->write_block = 0 ;
|
||||
|
||||
psf->sf.frames = ppaf24->samplesperblock * ppaf24->max_blocks ;
|
||||
ppaf24->sample_count = psf->sf.frames ;
|
||||
|
||||
return 0 ;
|
||||
} /* paf24_init */
|
||||
|
||||
static sf_count_t
|
||||
paf24_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int newblock, newsample ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
{ psf->error = SFE_INTERNAL ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (mode == SFM_READ && ppaf24->write_count > 0)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
|
||||
newblock = offset / ppaf24->samplesperblock ;
|
||||
newsample = offset % ppaf24->samplesperblock ;
|
||||
|
||||
switch (mode)
|
||||
{ case SFM_READ :
|
||||
if (psf->last_op == SFM_WRITE && ppaf24->write_count)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ;
|
||||
ppaf24->read_block = newblock ;
|
||||
paf24_read_block (psf, ppaf24) ;
|
||||
ppaf24->read_count = newsample ;
|
||||
break ;
|
||||
|
||||
case SFM_WRITE :
|
||||
if (offset > ppaf24->sample_count)
|
||||
{ psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
if (psf->last_op == SFM_WRITE && ppaf24->write_count)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset + newblock * ppaf24->blocksize, SEEK_SET) ;
|
||||
ppaf24->write_block = newblock ;
|
||||
paf24_read_block (psf, ppaf24) ;
|
||||
ppaf24->write_count = newsample ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf->error = SFE_BAD_SEEK ;
|
||||
return PSF_SEEK_ERROR ;
|
||||
} ;
|
||||
|
||||
return newblock * ppaf24->samplesperblock + newsample ;
|
||||
} /* paf24_seek */
|
||||
|
||||
static int
|
||||
paf24_close (SF_PRIVATE *psf)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (ppaf24->write_count > 0)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* paf24_close */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
*/
|
||||
static int
|
||||
paf24_read_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
|
||||
{ int k, channel ;
|
||||
unsigned char *cptr ;
|
||||
|
||||
ppaf24->read_block ++ ;
|
||||
ppaf24->read_count = 0 ;
|
||||
|
||||
if (ppaf24->read_block * ppaf24->samplesperblock > ppaf24->sample_count)
|
||||
{ memset (ppaf24->samples, 0, ppaf24->samplesperblock * ppaf24->channels) ;
|
||||
return 1 ;
|
||||
} ;
|
||||
|
||||
/* Read the block. */
|
||||
if ((k = psf_fread (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, ppaf24->blocksize) ;
|
||||
|
||||
|
||||
if (CPU_IS_LITTLE_ENDIAN)
|
||||
{ /* Do endian swapping if necessary. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
|
||||
/* Unpack block. */
|
||||
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
|
||||
} ;
|
||||
}
|
||||
else
|
||||
{ /* Do endian swapping if necessary. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
|
||||
/* Unpack block. */
|
||||
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
ppaf24->samples [k] = (cptr [0] << 8) | (cptr [1] << 16) | (cptr [2] << 24) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* paf24_read_block */
|
||||
|
||||
static int
|
||||
paf24_read (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, int *ptr, int len)
|
||||
{ int count, total = 0 ;
|
||||
|
||||
while (total < len)
|
||||
{ if (ppaf24->read_block * ppaf24->samplesperblock >= ppaf24->sample_count)
|
||||
{ memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ;
|
||||
return total ;
|
||||
} ;
|
||||
|
||||
if (ppaf24->read_count >= ppaf24->samplesperblock)
|
||||
paf24_read_block (psf, ppaf24) ;
|
||||
|
||||
count = (ppaf24->samplesperblock - ppaf24->read_count) * ppaf24->channels ;
|
||||
count = (len - total > count) ? count : len - total ;
|
||||
|
||||
memcpy (&(ptr [total]), &(ppaf24->samples [ppaf24->read_count * ppaf24->channels]), count * sizeof (int)) ;
|
||||
total += count ;
|
||||
ppaf24->read_count += count / ppaf24->channels ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* paf24_read */
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = paf24_read (psf, ppaf24, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = iptr [k] >> 16 ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* paf24_read_s */
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int total ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
total = paf24_read (psf, ppaf24, ptr, len) ;
|
||||
|
||||
return total ;
|
||||
} /* paf24_read_i */
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = paf24_read (psf, ppaf24, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * iptr [k] ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* paf24_read_f */
|
||||
|
||||
static sf_count_t
|
||||
paf24_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 / 0x80000000) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = paf24_read (psf, ppaf24, iptr, readcount) ;
|
||||
for (k = 0 ; k < readcount ; k++)
|
||||
ptr [total + k] = normfact * iptr [k] ;
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* paf24_read_d */
|
||||
|
||||
/*---------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
paf24_write_block (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24)
|
||||
{ int k, nextsample, channel ;
|
||||
unsigned char *cptr ;
|
||||
|
||||
/* First pack block. */
|
||||
|
||||
if (CPU_IS_LITTLE_ENDIAN)
|
||||
{ for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
nextsample = ppaf24->samples [k] >> 8 ;
|
||||
cptr [0] = nextsample ;
|
||||
cptr [1] = nextsample >> 8 ;
|
||||
cptr [2] = nextsample >> 16 ;
|
||||
} ;
|
||||
|
||||
/* Do endian swapping if necessary. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
}
|
||||
else if (CPU_IS_BIG_ENDIAN)
|
||||
{ /* This is correct. */
|
||||
for (k = 0 ; k < PAF24_SAMPLES_PER_BLOCK * ppaf24->channels ; k++)
|
||||
{ channel = k % ppaf24->channels ;
|
||||
cptr = ppaf24->block + PAF24_BLOCK_SIZE * channel + 3 * (k / ppaf24->channels) ;
|
||||
nextsample = ppaf24->samples [k] >> 8 ;
|
||||
cptr [0] = nextsample ;
|
||||
cptr [1] = nextsample >> 8 ;
|
||||
cptr [2] = nextsample >> 16 ;
|
||||
} ;
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
endswap_int_array (ppaf24->data, 8 * ppaf24->channels) ;
|
||||
} ;
|
||||
|
||||
/* Write block to disk. */
|
||||
if ((k = psf_fwrite (ppaf24->block, 1, ppaf24->blocksize, psf)) != ppaf24->blocksize)
|
||||
psf_log_printf (psf, "*** Warning : short write (%d != %d).\n", k, ppaf24->blocksize) ;
|
||||
|
||||
if (ppaf24->sample_count < ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count)
|
||||
ppaf24->sample_count = ppaf24->write_block * ppaf24->samplesperblock + ppaf24->write_count ;
|
||||
|
||||
if (ppaf24->write_count == ppaf24->samplesperblock)
|
||||
{ ppaf24->write_block ++ ;
|
||||
ppaf24->write_count = 0 ;
|
||||
} ;
|
||||
|
||||
return 1 ;
|
||||
} /* paf24_write_block */
|
||||
|
||||
static int
|
||||
paf24_write (SF_PRIVATE *psf, PAF24_PRIVATE *ppaf24, const int *ptr, int len)
|
||||
{ int count, total = 0 ;
|
||||
|
||||
while (total < len)
|
||||
{ count = (ppaf24->samplesperblock - ppaf24->write_count) * ppaf24->channels ;
|
||||
|
||||
if (count > len - total)
|
||||
count = len - total ;
|
||||
|
||||
memcpy (&(ppaf24->samples [ppaf24->write_count * ppaf24->channels]), &(ptr [total]), count * sizeof (int)) ;
|
||||
total += count ;
|
||||
ppaf24->write_count += count / ppaf24->channels ;
|
||||
|
||||
if (ppaf24->write_count >= ppaf24->samplesperblock)
|
||||
paf24_write_block (psf, ppaf24) ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* paf24_write */
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_s (SF_PRIVATE *psf, const short *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = ptr [total + k] << 16 ;
|
||||
count = paf24_write (psf, ppaf24, iptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
return total ;
|
||||
} /* paf24_write_s */
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_i (SF_PRIVATE *psf, const int *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int writecount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
while (len > 0)
|
||||
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
|
||||
|
||||
count = paf24_write (psf, ppaf24, ptr, writecount) ;
|
||||
|
||||
total += count ;
|
||||
len -= count ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* paf24_write_i */
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_f (SF_PRIVATE *psf, const float *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_float == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = lrintf (normfact * ptr [total + k]) ;
|
||||
count = paf24_write (psf, ppaf24, iptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* paf24_write_f */
|
||||
|
||||
static sf_count_t
|
||||
paf24_write_d (SF_PRIVATE *psf, const double *ptr, sf_count_t len)
|
||||
{ PAF24_PRIVATE *ppaf24 ;
|
||||
int *iptr ;
|
||||
int k, bufferlen, writecount = 0, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (psf->codec_data == NULL)
|
||||
return 0 ;
|
||||
ppaf24 = (PAF24_PRIVATE*) psf->codec_data ;
|
||||
|
||||
normfact = (psf->norm_double == SF_TRUE) ? (1.0 * 0x7FFFFFFF) : (1.0 / 0x100) ;
|
||||
|
||||
iptr = psf->u.ibuf ;
|
||||
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
|
||||
while (len > 0)
|
||||
{ writecount = (len >= bufferlen) ? bufferlen : len ;
|
||||
for (k = 0 ; k < writecount ; k++)
|
||||
iptr [k] = lrint (normfact * ptr [total+k]) ;
|
||||
count = paf24_write (psf, ppaf24, iptr, writecount) ;
|
||||
total += count ;
|
||||
len -= writecount ;
|
||||
if (count != writecount)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* paf24_write_d */
|
||||
|
||||
2901
project/jni/sndfile/src/pcm.c
Normal file
2901
project/jni/sndfile/src/pcm.c
Normal file
File diff suppressed because it is too large
Load Diff
188
project/jni/sndfile/src/pvf.c
Normal file
188
project/jni/sndfile/src/pvf.c
Normal file
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define PVF1_MARKER (MAKE_MARKER ('P', 'V', 'F', '1'))
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int pvf_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int pvf_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int pvf_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
pvf_open (SF_PRIVATE *psf)
|
||||
{ int subformat ;
|
||||
int error = 0 ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = pvf_read_header (psf)))
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_PVF)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (pvf_write_header (psf, SF_FALSE))
|
||||
return psf->error ;
|
||||
|
||||
psf->write_header = pvf_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = pvf_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_32 : /* 32-bit linear PCM. */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
default : break ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* pvf_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
pvf_close (SF_PRIVATE * UNUSED (psf))
|
||||
{
|
||||
return 0 ;
|
||||
} /* pvf_close */
|
||||
|
||||
static int
|
||||
pvf_write_header (SF_PRIVATE *psf, int UNUSED (calc_length))
|
||||
{ sf_count_t current ;
|
||||
|
||||
if (psf->pipeoffset > 0)
|
||||
return 0 ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
|
||||
if (psf->is_pipe == SF_FALSE)
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
snprintf ((char*) psf->header, sizeof (psf->header), "PVF1\n%d %d %d\n",
|
||||
psf->sf.channels, psf->sf.samplerate, psf->bytewidth * 8) ;
|
||||
|
||||
psf->headindex = strlen ((char*) psf->header) ;
|
||||
|
||||
/* Header construction complete so write it out. */
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* pvf_write_header */
|
||||
|
||||
static int
|
||||
pvf_read_header (SF_PRIVATE *psf)
|
||||
{ char buffer [32] ;
|
||||
int marker, channels, samplerate, bitwidth ;
|
||||
|
||||
psf_binheader_readf (psf, "pmj", 0, &marker, 1) ;
|
||||
psf_log_printf (psf, "%M\n", marker) ;
|
||||
|
||||
if (marker != PVF1_MARKER)
|
||||
return SFE_PVF_NO_PVF1 ;
|
||||
|
||||
/* Grab characters up until a newline which is replaced by an EOS. */
|
||||
psf_binheader_readf (psf, "G", buffer, sizeof (buffer)) ;
|
||||
|
||||
if (sscanf (buffer, "%d %d %d", &channels, &samplerate, &bitwidth) != 3)
|
||||
return SFE_PVF_BAD_HEADER ;
|
||||
|
||||
psf_log_printf (psf, " Channels : %d\n Sample rate : %d\n Bit width : %d\n",
|
||||
channels, samplerate, bitwidth) ;
|
||||
|
||||
psf->sf.channels = channels ;
|
||||
psf->sf.samplerate = samplerate ;
|
||||
|
||||
switch (bitwidth)
|
||||
{ case 8 :
|
||||
psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_S8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
break ;
|
||||
|
||||
case 16 :
|
||||
psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
break ;
|
||||
case 32 :
|
||||
psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_32 ;
|
||||
psf->bytewidth = 4 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_PVF_BAD_BITWIDTH ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
psf_log_printf (psf, " Data Offset : %D\n", psf->dataoffset) ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
if (! psf->sf.frames && psf->blockwidth)
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
|
||||
return 0 ;
|
||||
} /* pvf_read_header */
|
||||
104
project/jni/sndfile/src/raw.c
Normal file
104
project/jni/sndfile/src/raw.c
Normal file
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
raw_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = SFE_NO_ERROR ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
|
||||
if (CPU_IS_BIG_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
else if (CPU_IS_LITTLE_ENDIAN && (psf->endian == 0 || psf->endian == SF_ENDIAN_CPU))
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
psf->dataoffset = 0 ;
|
||||
psf->datalength = psf->filelength ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_U8 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
error = ulaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
error = alaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_GSM610 :
|
||||
error = gsm610_init (psf) ;
|
||||
break ;
|
||||
|
||||
/* Lite remove start */
|
||||
case SF_FORMAT_FLOAT :
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DWVW_12 :
|
||||
error = dwvw_init (psf, 12) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DWVW_16 :
|
||||
error = dwvw_init (psf, 16) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DWVW_24 :
|
||||
error = dwvw_init (psf, 24) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_VOX_ADPCM :
|
||||
error = vox_adpcm_init (psf) ;
|
||||
break ;
|
||||
/* Lite remove end */
|
||||
|
||||
default : return SFE_BAD_OPEN_FORMAT ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* raw_open */
|
||||
716
project/jni/sndfile/src/rf64.c
Normal file
716
project/jni/sndfile/src/rf64.c
Normal file
@@ -0,0 +1,716 @@
|
||||
/*
|
||||
** Copyright (C) 2008-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2009 Uli Franke <cls@nebadje.org>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** This format documented at:
|
||||
** http://www.sr.se/utveckling/tu/bwf/prog/RF_64v1_4.pdf
|
||||
**
|
||||
** But this may be a better reference:
|
||||
** http://www.ebu.ch/CMSimages/en/tec_doc_t3306-2007_tcm6-42570.pdf
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
#include "wav_w64.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Macros to handle big/little endian issues.
|
||||
*/
|
||||
#define RF64_MARKER MAKE_MARKER ('R', 'F', '6', '4')
|
||||
#define FFFF_MARKER MAKE_MARKER (0xff, 0xff, 0xff, 0xff)
|
||||
#define WAVE_MARKER MAKE_MARKER ('W', 'A', 'V', 'E')
|
||||
#define ds64_MARKER MAKE_MARKER ('d', 's', '6', '4')
|
||||
#define fmt_MARKER MAKE_MARKER ('f', 'm', 't', ' ')
|
||||
#define fact_MARKER MAKE_MARKER ('f', 'a', 'c', 't')
|
||||
#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a')
|
||||
|
||||
#define bext_MARKER MAKE_MARKER ('b', 'e', 'x', 't')
|
||||
#define OggS_MARKER MAKE_MARKER ('O', 'g', 'g', 'S')
|
||||
#define wvpk_MARKER MAKE_MARKER ('w', 'v', 'p', 'k')
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Typedefs.
|
||||
*/
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ;
|
||||
static int rf64_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int rf64_close (SF_PRIVATE *psf) ;
|
||||
static int rf64_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
rf64_open (SF_PRIVATE *psf)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
int subformat, error = 0 ;
|
||||
int blockalign, framesperblock ;
|
||||
|
||||
if ((wpriv = calloc (1, sizeof (WAV_PRIVATE))) == NULL)
|
||||
return SFE_MALLOC_FAILED ;
|
||||
psf->container_data = wpriv ;
|
||||
wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
|
||||
|
||||
/* All RF64 files are little endian. */
|
||||
psf->endian = SF_ENDIAN_LITTLE ;
|
||||
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = rf64_read_header (psf, &blockalign, &framesperblock)) != 0)
|
||||
return error ;
|
||||
} ;
|
||||
|
||||
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RF64)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
if ((error = rf64_write_header (psf, SF_FALSE)))
|
||||
return error ;
|
||||
|
||||
psf->write_header = rf64_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = rf64_close ;
|
||||
psf->command = rf64_command ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
error = ulaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
error = alaw_init (psf) ;
|
||||
break ;
|
||||
|
||||
/* Lite remove start */
|
||||
case SF_FORMAT_FLOAT :
|
||||
error = float32_init (psf) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_DOUBLE :
|
||||
error = double64_init (psf) ;
|
||||
break ;
|
||||
|
||||
/* Lite remove end */
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
return error ;
|
||||
} /* rf64_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
enum
|
||||
{ HAVE_ds64 = 0x01,
|
||||
HAVE_fmt = 0x02,
|
||||
HAVE_bext = 0x04,
|
||||
HAVE_data = 0x08
|
||||
} ;
|
||||
|
||||
#define HAVE_CHUNK(CHUNK) ((parsestage & CHUNK) != 0)
|
||||
|
||||
static int
|
||||
rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
WAV_FMT *wav_fmt ;
|
||||
sf_count_t riff_size = 0, frame_count = 0, ds64_datalength = 0 ;
|
||||
unsigned int size32, parsestage = 0 ;
|
||||
int marker, marks [2], error, done = 0, format = 0 ;
|
||||
|
||||
if ((wpriv = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
wav_fmt = &wpriv->wav_fmt ;
|
||||
|
||||
/* Set position to start of file to begin reading header. */
|
||||
psf_binheader_readf (psf, "pmmm", 0, &marker, marks, marks + 1) ;
|
||||
if (marker != RF64_MARKER || marks [1] != WAVE_MARKER)
|
||||
return SFE_RF64_NOT_RF64 ;
|
||||
|
||||
if (marks [0] == FFFF_MARKER)
|
||||
psf_log_printf (psf, "%M\n %M\n", RF64_MARKER, WAVE_MARKER) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : 0x%x (should be 0xFFFFFFFF)\n %M\n", RF64_MARKER, WAVE_MARKER) ;
|
||||
|
||||
while (NOT (done))
|
||||
{ psf_binheader_readf (psf, "em4", &marker, &size32) ;
|
||||
|
||||
switch (marker)
|
||||
{ case ds64_MARKER :
|
||||
{ unsigned int table_len, bytesread ;
|
||||
|
||||
/* Read ds64 sizes (3 8-byte words). */
|
||||
bytesread = psf_binheader_readf (psf, "888", &riff_size, &ds64_datalength, &frame_count) ;
|
||||
|
||||
/* Read table length. */
|
||||
bytesread += psf_binheader_readf (psf, "4", &table_len) ;
|
||||
/* Skip table for now. (this was "table_len + 4", why?) */
|
||||
bytesread += psf_binheader_readf (psf, "j", table_len) ;
|
||||
|
||||
if (size32 == bytesread)
|
||||
psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
else if (size32 >= bytesread + 4)
|
||||
{ unsigned int next ;
|
||||
psf_binheader_readf (psf, "m", &next) ;
|
||||
if (next == fmt_MARKER)
|
||||
{ psf_log_printf (psf, "%M : %u (should be %u)\n", marker, size32, bytesread) ;
|
||||
psf_binheader_readf (psf, "j", -4) ;
|
||||
}
|
||||
else
|
||||
{ psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
psf_binheader_readf (psf, "j", size32 - bytesread - 4) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->filelength != riff_size + 8)
|
||||
psf_log_printf (psf, " Riff size : %D (should be %D)\n", riff_size, psf->filelength - 8) ;
|
||||
else
|
||||
psf_log_printf (psf, " Riff size : %D\n", riff_size) ;
|
||||
|
||||
psf_log_printf (psf, " Data size : %D\n", ds64_datalength) ;
|
||||
|
||||
psf_log_printf (psf, " Frames : %D\n", frame_count) ;
|
||||
psf_log_printf (psf, " Table length : %u\n", table_len) ;
|
||||
|
||||
} ;
|
||||
parsestage |= HAVE_ds64 ;
|
||||
break ;
|
||||
|
||||
case fmt_MARKER:
|
||||
psf_log_printf (psf, "%M : %u\n", marker, size32) ;
|
||||
if ((error = wav_w64_read_fmt_chunk (psf, size32)) != 0)
|
||||
return error ;
|
||||
format = wav_fmt->format ;
|
||||
parsestage |= HAVE_fmt ;
|
||||
break ;
|
||||
|
||||
case bext_MARKER :
|
||||
if ((error = wav_read_bext_chunk (psf, size32)) != 0)
|
||||
return error ;
|
||||
parsestage |= HAVE_bext ;
|
||||
break ;
|
||||
|
||||
case data_MARKER :
|
||||
/* see wav for more sophisticated parsing -> implement state machine with parsestage */
|
||||
|
||||
if (HAVE_CHUNK (HAVE_ds64))
|
||||
{ if (size32 == 0xffffffff)
|
||||
psf_log_printf (psf, "%M : 0x%x\n", marker, size32) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : 0x%x (should be 0xffffffff\n", marker, size32) ;
|
||||
psf->datalength = ds64_datalength ;
|
||||
}
|
||||
else
|
||||
{ if (size32 == 0xffffffff)
|
||||
{ psf_log_printf (psf, "%M : 0x%x\n", marker, size32) ;
|
||||
psf_log_printf (psf, " *** Data length not specified no 'ds64' chunk.\n") ;
|
||||
}
|
||||
else
|
||||
{ psf_log_printf (psf, "%M : 0x%x\n**** Weird, RF64 file without a 'ds64' chunk and no valid 'data' size.\n", marker, size32) ;
|
||||
psf->datalength = size32 ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
|
||||
if (psf->dataoffset > 0)
|
||||
{ if (size32 == 0 && riff_size == 8 && psf->filelength > 44)
|
||||
{ psf_log_printf (psf, " *** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
} ;
|
||||
|
||||
/* Only set dataend if there really is data at the end. */
|
||||
if (psf->datalength + psf->dataoffset < psf->filelength)
|
||||
psf->dataend = psf->datalength + psf->dataoffset ;
|
||||
|
||||
if (NOT (psf->sf.seekable) || psf->dataoffset < 0)
|
||||
break ;
|
||||
|
||||
/* Seek past data and continue reading header. */
|
||||
psf_fseek (psf, psf->datalength, SEEK_CUR) ;
|
||||
|
||||
if (psf_ftell (psf) != psf->datalength + psf->dataoffset)
|
||||
psf_log_printf (psf, " *** psf_fseek past end error ***\n") ;
|
||||
break ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
|
||||
&& isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF))
|
||||
{ psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, size32) ;
|
||||
if (size32 < 8)
|
||||
done = SF_TRUE ;
|
||||
psf_binheader_readf (psf, "j", size32) ;
|
||||
break ;
|
||||
} ;
|
||||
if (psf_ftell (psf) & 0x03)
|
||||
{ psf_log_printf (psf, " Unknown chunk marker at position 0x%x. Resynching.\n", size32 - 4) ;
|
||||
psf_binheader_readf (psf, "j", -3) ;
|
||||
break ;
|
||||
} ;
|
||||
psf_log_printf (psf, "*** Unknown chunk marker (0x%X) at position 0x%X. Exiting parser.\n", marker, psf_ftell (psf) - 4) ;
|
||||
done = SF_TRUE ;
|
||||
break ;
|
||||
} ; /* switch (marker) */
|
||||
|
||||
if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (marker))
|
||||
{ psf_log_printf (psf, "End\n") ;
|
||||
break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->dataoffset <= 0)
|
||||
return SFE_WAV_NO_DATA ;
|
||||
|
||||
/* WAVs can be little or big endian */
|
||||
psf->endian = psf->rwf_endian ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
if (psf->is_pipe == 0)
|
||||
{ /*
|
||||
** Check for 'wvpk' at the start of the DATA section. Not able to
|
||||
** handle this.
|
||||
*/
|
||||
psf_binheader_readf (psf, "4", &marker) ;
|
||||
if (marker == wvpk_MARKER || marker == OggS_MARKER)
|
||||
return SFE_WAV_WVPK_DATA ;
|
||||
} ;
|
||||
|
||||
/* Seek to start of DATA section. */
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
if (psf->blockwidth)
|
||||
{ if (psf->filelength - psf->dataoffset < psf->datalength)
|
||||
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
|
||||
else
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
} ;
|
||||
|
||||
if (frame_count != psf->sf.frames)
|
||||
psf_log_printf (psf, "*** Calculated frame count %d does not match value from 'ds64' chunk of %d.\n", psf->sf.frames, frame_count) ;
|
||||
|
||||
switch (format)
|
||||
{
|
||||
case WAVE_FORMAT_EXTENSIBLE :
|
||||
|
||||
/* with WAVE_FORMAT_EXTENSIBLE the psf->sf.format field is already set. We just have to set the major to rf64 */
|
||||
psf->sf.format = (psf->sf.format & ~SF_FORMAT_TYPEMASK ) | SF_FORMAT_RF64 ;
|
||||
|
||||
if (psf->sf.format == (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM))
|
||||
{ *blockalign = wav_fmt->msadpcm.blockalign ;
|
||||
*framesperblock = wav_fmt->msadpcm.samplesperblock ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_PCM :
|
||||
psf->sf.format = SF_FORMAT_RF64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_MULAW :
|
||||
case IBM_FORMAT_MULAW :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_ULAW) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_ALAW :
|
||||
case IBM_FORMAT_ALAW :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_ALAW) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_MS_ADPCM :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_MS_ADPCM) ;
|
||||
*blockalign = wav_fmt->msadpcm.blockalign ;
|
||||
*framesperblock = wav_fmt->msadpcm.samplesperblock ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_IMA_ADPCM :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_IMA_ADPCM) ;
|
||||
*blockalign = wav_fmt->ima.blockalign ;
|
||||
*framesperblock = wav_fmt->ima.samplesperblock ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_GSM610 :
|
||||
psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_GSM610) ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_IEEE_FLOAT :
|
||||
psf->sf.format = SF_FORMAT_RF64 ;
|
||||
psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ;
|
||||
break ;
|
||||
|
||||
case WAVE_FORMAT_G721_ADPCM :
|
||||
psf->sf.format = SF_FORMAT_RF64 | SF_FORMAT_G721_32 ;
|
||||
break ;
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
if (wpriv->fmt_is_broken)
|
||||
wav_w64_analyze (psf) ;
|
||||
|
||||
/* Only set the format endian-ness if its non-standard big-endian. */
|
||||
if (psf->endian == SF_ENDIAN_BIG)
|
||||
psf->sf.format |= SF_ENDIAN_BIG ;
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_read_header */
|
||||
|
||||
/* known WAVEFORMATEXTENSIBLE GUIDS */
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM =
|
||||
{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
} ;
|
||||
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM =
|
||||
{ 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
} ;
|
||||
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT =
|
||||
{ 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
} ;
|
||||
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW =
|
||||
{ 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
} ;
|
||||
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW =
|
||||
{ 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 }
|
||||
} ;
|
||||
|
||||
/*
|
||||
** the next two are from
|
||||
** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html
|
||||
*/
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM =
|
||||
{ 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
|
||||
} ;
|
||||
|
||||
static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT =
|
||||
{ 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 }
|
||||
} ;
|
||||
|
||||
|
||||
static int
|
||||
rf64_write_fmt_chunk (SF_PRIVATE *psf)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
int subformat, fmt_size ;
|
||||
|
||||
if ((wpriv = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
|
||||
|
||||
/* initial section (same for all, it appears) */
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
case SF_FORMAT_FLOAT :
|
||||
case SF_FORMAT_DOUBLE :
|
||||
case SF_FORMAT_ULAW :
|
||||
case SF_FORMAT_ALAW :
|
||||
fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ;
|
||||
|
||||
/* fmt : format, channels, samplerate */
|
||||
psf_binheader_writef (psf, "4224", fmt_size, WAVE_FORMAT_EXTENSIBLE, psf->sf.channels, psf->sf.samplerate) ;
|
||||
/* fmt : bytespersec */
|
||||
psf_binheader_writef (psf, "4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
|
||||
/* fmt : blockalign, bitwidth */
|
||||
psf_binheader_writef (psf, "22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
|
||||
|
||||
/* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */
|
||||
psf_binheader_writef (psf, "2", 22) ;
|
||||
|
||||
/* wValidBitsPerSample, for our use same as bitwidth as we use it fully */
|
||||
psf_binheader_writef (psf, "2", psf->bytewidth * 8) ;
|
||||
|
||||
/* For an Ambisonic file set the channel mask to zero.
|
||||
** Otherwise use a default based on the channel count.
|
||||
*/
|
||||
if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE)
|
||||
psf_binheader_writef (psf, "4", 0) ;
|
||||
else if (wpriv->wavex_channelmask != 0)
|
||||
psf_binheader_writef (psf, "4", wpriv->wavex_channelmask) ;
|
||||
else
|
||||
{ /*
|
||||
** Ok some liberty is taken here to use the most commonly used channel masks
|
||||
** instead of "no mapping". If you really want to use "no mapping" for 8 channels and less
|
||||
** please don't use wavex. (otherwise we'll have to create a new SF_COMMAND)
|
||||
*/
|
||||
switch (psf->sf.channels)
|
||||
{ case 1 : /* center channel mono */
|
||||
psf_binheader_writef (psf, "4", 0x4) ;
|
||||
break ;
|
||||
|
||||
case 2 : /* front left and right */
|
||||
psf_binheader_writef (psf, "4", 0x1 | 0x2) ;
|
||||
break ;
|
||||
|
||||
case 4 : /* Quad */
|
||||
psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x10 | 0x20) ;
|
||||
break ;
|
||||
|
||||
case 6 : /* 5.1 */
|
||||
psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20) ;
|
||||
break ;
|
||||
|
||||
case 8 : /* 7.1 */
|
||||
psf_binheader_writef (psf, "4", 0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80) ;
|
||||
break ;
|
||||
|
||||
default : /* 0 when in doubt , use direct out, ie NO mapping*/
|
||||
psf_binheader_writef (psf, "4", 0x0) ;
|
||||
break ;
|
||||
} ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_MS_ADPCM : /* Todo, GUID exists might have different header as per wav_write_header */
|
||||
default :
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
/* GUID section, different for each */
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_U8 :
|
||||
case SF_FORMAT_PCM_16 :
|
||||
case SF_FORMAT_PCM_24 :
|
||||
case SF_FORMAT_PCM_32 :
|
||||
wavex_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ?
|
||||
&MSGUID_SUBTYPE_PCM : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_FLOAT :
|
||||
case SF_FORMAT_DOUBLE :
|
||||
wavex_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ?
|
||||
&MSGUID_SUBTYPE_IEEE_FLOAT : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ULAW :
|
||||
wavex_write_guid (psf, &MSGUID_SUBTYPE_MULAW) ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_ALAW :
|
||||
wavex_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ;
|
||||
break ;
|
||||
|
||||
default : return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_write_fmt_chunk */
|
||||
|
||||
|
||||
static int
|
||||
rf64_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ sf_count_t current ;
|
||||
int error = 0, has_data = SF_FALSE ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (psf->dataoffset > 0 && current > psf->dataoffset)
|
||||
has_data = SF_TRUE ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
if (psf->bytewidth > 0)
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
/* Reset the current header length to zero. */
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
psf_binheader_writef (psf, "em4m", RF64_MARKER, 0xffffffff, WAVE_MARKER) ;
|
||||
|
||||
/* Currently no table. */
|
||||
psf_binheader_writef (psf, "m48884", ds64_MARKER, 28, psf->filelength - 8, psf->datalength, psf->sf.frames, 0) ;
|
||||
|
||||
/* WAVE and 'fmt ' markers. */
|
||||
psf_binheader_writef (psf, "m", fmt_MARKER) ;
|
||||
|
||||
/* Write the 'fmt ' chunk. */
|
||||
switch (psf->sf.format & SF_FORMAT_TYPEMASK)
|
||||
{ case SF_FORMAT_WAV :
|
||||
psf_log_printf (psf, "ooops SF_FORMAT_WAV\n") ;
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
break ;
|
||||
|
||||
case SF_FORMAT_WAVEX :
|
||||
case SF_FORMAT_RF64 :
|
||||
if ((error = rf64_write_fmt_chunk (psf)) != 0)
|
||||
return error ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
} ;
|
||||
|
||||
if (psf->broadcast_16k != NULL)
|
||||
wav_write_bext_chunk (psf) ;
|
||||
|
||||
#if 0
|
||||
/* The LIST/INFO chunk. */
|
||||
if (psf->str_flags & SF_STR_LOCATE_START)
|
||||
wav_write_strings (psf, SF_STR_LOCATE_START) ;
|
||||
|
||||
if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START)
|
||||
{ psf_binheader_writef (psf, "m4", PEAK_MARKER, WAV_PEAK_CHUNK_SIZE (psf->sf.channels)) ;
|
||||
psf_binheader_writef (psf, "44", 1, time (NULL)) ;
|
||||
for (k = 0 ; k < psf->sf.channels ; k++)
|
||||
psf_binheader_writef (psf, "ft8", (float) psf->peak_info->peaks [k].value, psf->peak_info->peaks [k].position) ;
|
||||
} ;
|
||||
|
||||
// if (psf->broadcast_info != NULL)
|
||||
// wav_write_bext_chunk (psf) ;
|
||||
|
||||
if (psf->instrument != NULL)
|
||||
{ int tmp ;
|
||||
double dtune = (double) (0x40000000) / 25.0 ;
|
||||
|
||||
psf_binheader_writef (psf, "m4", smpl_MARKER, 9 * 4 + psf->instrument->loop_count * 6 * 4) ;
|
||||
psf_binheader_writef (psf, "44", 0, 0) ; /* Manufacturer zero is everyone */
|
||||
tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */
|
||||
psf_binheader_writef (psf, "44", tmp, psf->instrument->basenote) ;
|
||||
tmp = (unsigned int) (psf->instrument->detune * dtune + 0.5) ;
|
||||
psf_binheader_writef (psf, "4", tmp) ;
|
||||
psf_binheader_writef (psf, "44", 0, 0) ; /* SMTPE format */
|
||||
psf_binheader_writef (psf, "44", psf->instrument->loop_count, 0) ;
|
||||
|
||||
for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++)
|
||||
{ int type ;
|
||||
|
||||
type = psf->instrument->loops [tmp].mode ;
|
||||
type = (type == SF_LOOP_FORWARD ? 0 : type==SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ;
|
||||
|
||||
psf_binheader_writef (psf, "44", tmp, type) ;
|
||||
psf_binheader_writef (psf, "44", psf->instrument->loops [tmp].start, psf->instrument->loops [tmp].end) ;
|
||||
psf_binheader_writef (psf, "44", 0, psf->instrument->loops [tmp].count) ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
if (psf->headindex + 8 < psf->dataoffset)
|
||||
{ /* Add PAD data if necessary. */
|
||||
k = psf->dataoffset - 16 - psf->headindex ;
|
||||
psf_binheader_writef (psf, "m4z", PAD_MARKER, k, make_size_t (k)) ;
|
||||
} ;
|
||||
|
||||
#endif
|
||||
|
||||
psf_binheader_writef (psf, "m4", data_MARKER, 0xffffffff) ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
if (has_data && psf->dataoffset != psf->headindex)
|
||||
{ printf ("Oooops : has_data && psf->dataoffset != psf->headindex\n") ;
|
||||
return psf->error = SFE_INTERNAL ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (NOT (has_data))
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
else if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* rf64_write_header */
|
||||
|
||||
static int
|
||||
rf64_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ // rf64_write_tailer (psf) ;
|
||||
|
||||
psf->write_header (psf, SF_TRUE) ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_close */
|
||||
|
||||
static int
|
||||
rf64_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize)
|
||||
{ WAV_PRIVATE *wpriv ;
|
||||
|
||||
if ((wpriv = psf->container_data) == NULL)
|
||||
return SFE_INTERNAL ;
|
||||
|
||||
switch (command)
|
||||
{ case SFC_WAVEX_SET_AMBISONIC :
|
||||
if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAVEX)
|
||||
{ if (datasize == SF_AMBISONIC_NONE)
|
||||
wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ;
|
||||
else if (datasize == SF_AMBISONIC_B_FORMAT)
|
||||
wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ;
|
||||
else
|
||||
return 0 ;
|
||||
} ;
|
||||
return wpriv->wavex_ambisonic ;
|
||||
|
||||
case SFC_WAVEX_GET_AMBISONIC :
|
||||
return wpriv->wavex_ambisonic ;
|
||||
|
||||
case SFC_SET_CHANNEL_MAP_INFO :
|
||||
wpriv->wavex_channelmask = wavex_gen_channel_mask (psf->channel_map, psf->sf.channels) ;
|
||||
return (wpriv->wavex_channelmask != 0) ;
|
||||
|
||||
default :
|
||||
break ;
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* rf64_command */
|
||||
|
||||
319
project/jni/sndfile/src/rx2.c
Normal file
319
project/jni/sndfile/src/rx2.c
Normal file
@@ -0,0 +1,319 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE == 0)
|
||||
|
||||
int
|
||||
rx2_open (SF_PRIVATE *psf)
|
||||
{ if (psf)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
return 0 ;
|
||||
} /* rx2_open */
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define CAT_MARKER (MAKE_MARKER ('C', 'A', 'T', ' '))
|
||||
#define GLOB_MARKER (MAKE_MARKER ('G', 'L', 'O', 'B'))
|
||||
|
||||
#define RECY_MARKER (MAKE_MARKER ('R', 'E', 'C', 'Y'))
|
||||
|
||||
#define SLCL_MARKER (MAKE_MARKER ('S', 'L', 'C', 'L'))
|
||||
#define SLCE_MARKER (MAKE_MARKER ('S', 'L', 'C', 'E'))
|
||||
|
||||
#define DEVL_MARKER (MAKE_MARKER ('D', 'E', 'V', 'L'))
|
||||
#define TRSH_MARKER (MAKE_MARKER ('T', 'R', 'S', 'H'))
|
||||
|
||||
#define EQ_MARKER (MAKE_MARKER ('E', 'Q', ' ', ' '))
|
||||
#define COMP_MARKER (MAKE_MARKER ('C', 'O', 'M', 'P'))
|
||||
|
||||
#define SINF_MARKER (MAKE_MARKER ('S', 'I', 'N', 'F'))
|
||||
#define SDAT_MARKER (MAKE_MARKER ('S', 'D', 'A', 'T'))
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Typedefs for file chunks.
|
||||
*/
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Private static functions.
|
||||
*/
|
||||
static int rx2_close (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public functions.
|
||||
*/
|
||||
|
||||
int
|
||||
rx2_open (SF_PRIVATE *psf)
|
||||
{ static const char *marker_type [4] =
|
||||
{ "Original Enabled", "Enabled Hidden",
|
||||
"Additional/PencilTool", "Disabled"
|
||||
} ;
|
||||
|
||||
int error, marker, length, glob_offset, slce_count, frames ;
|
||||
|
||||
int sdat_length = 0, slce_total = 0 ;
|
||||
|
||||
int n_channels ;
|
||||
|
||||
|
||||
/* So far only doing read. */
|
||||
|
||||
psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ;
|
||||
|
||||
if (marker != CAT_MARKER)
|
||||
{ psf_log_printf (psf, "length : %d\n", length) ;
|
||||
return -1000 ;
|
||||
} ;
|
||||
|
||||
if (length != psf->filelength - 8)
|
||||
psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ;
|
||||
else
|
||||
psf_log_printf (psf, "%M : %d\n", marker, length) ;
|
||||
|
||||
/* 'REX2' marker */
|
||||
psf_binheader_readf (psf, "m", &marker) ;
|
||||
psf_log_printf (psf, "%M", marker) ;
|
||||
|
||||
/* 'HEAD' marker */
|
||||
psf_binheader_readf (psf, "m", &marker) ;
|
||||
psf_log_printf (psf, "%M\n", marker) ;
|
||||
|
||||
/* Grab 'GLOB' offset. */
|
||||
psf_binheader_readf (psf, "E4", &glob_offset) ;
|
||||
glob_offset += 0x14 ; /* Add the current file offset. */
|
||||
|
||||
/* Jump to offset 0x30 */
|
||||
psf_binheader_readf (psf, "p", 0x30) ;
|
||||
|
||||
/* Get name length */
|
||||
length = 0 ;
|
||||
psf_binheader_readf (psf, "1", &length) ;
|
||||
if (length >= SIGNED_SIZEOF (psf->u.cbuf))
|
||||
{ psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ;
|
||||
return -1001 ;
|
||||
}
|
||||
|
||||
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
|
||||
psf_binheader_readf (psf, "b", psf->u.cbuf, length) ;
|
||||
psf_log_printf (psf, " Text : \"%s\"\n", psf->u.cbuf) ;
|
||||
|
||||
/* Jump to GLOB offset position. */
|
||||
if (glob_offset & 1)
|
||||
glob_offset ++ ;
|
||||
|
||||
psf_binheader_readf (psf, "p", glob_offset) ;
|
||||
|
||||
slce_count = 0 ;
|
||||
/* GLOB */
|
||||
while (1)
|
||||
{ psf_binheader_readf (psf, "m", &marker) ;
|
||||
|
||||
if (marker != SLCE_MARKER && slce_count > 0)
|
||||
{ psf_log_printf (psf, " SLCE count : %d\n", slce_count) ;
|
||||
slce_count = 0 ;
|
||||
}
|
||||
switch (marker)
|
||||
{ case GLOB_MARKER:
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " %M : %d\n", marker, length) ;
|
||||
psf_binheader_readf (psf, "j", length) ;
|
||||
break ;
|
||||
|
||||
case RECY_MARKER:
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " %M : %d\n", marker, length) ;
|
||||
psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */
|
||||
break ;
|
||||
|
||||
case CAT_MARKER:
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " %M : %d\n", marker, length) ;
|
||||
/*-psf_binheader_readf (psf, "j", length) ;-*/
|
||||
break ;
|
||||
|
||||
case DEVL_MARKER:
|
||||
psf_binheader_readf (psf, "mE4", &marker, &length) ;
|
||||
psf_log_printf (psf, " DEVL%M : %d\n", marker, length) ;
|
||||
if (length & 1)
|
||||
length ++ ;
|
||||
psf_binheader_readf (psf, "j", length) ;
|
||||
break ;
|
||||
|
||||
case EQ_MARKER:
|
||||
case COMP_MARKER:
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " %M : %d\n", marker, length) ;
|
||||
/* This is weird!!!! why make this (length - 1) */
|
||||
if (length & 1)
|
||||
length ++ ;
|
||||
psf_binheader_readf (psf, "j", length) ;
|
||||
break ;
|
||||
|
||||
case SLCL_MARKER:
|
||||
psf_log_printf (psf, " %M\n (Offset, Next Offset, Type)\n", marker) ;
|
||||
slce_count = 0 ;
|
||||
break ;
|
||||
|
||||
case SLCE_MARKER:
|
||||
{ int len [4], indx ;
|
||||
|
||||
psf_binheader_readf (psf, "E4444", &len [0], &len [1], &len [2], &len [3]) ;
|
||||
|
||||
indx = ((len [3] & 0x0000FFFF) >> 8) & 3 ;
|
||||
|
||||
if (len [2] == 1)
|
||||
{ if (indx != 1)
|
||||
indx = 3 ; /* 2 cases, where next slice offset = 1 -> disabled & enabled/hidden */
|
||||
|
||||
psf_log_printf (psf, " %M : (%6d, ?: 0x%X, %s)\n", marker, len [1], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
|
||||
}
|
||||
else
|
||||
{ slce_total += len [2] ;
|
||||
|
||||
psf_log_printf (psf, " %M : (%6d, SLCE_next_ofs:%d, ?: 0x%X, %s)\n", marker, len [1], len [2], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
|
||||
} ;
|
||||
|
||||
slce_count ++ ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
case SINF_MARKER:
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " %M : %d\n", marker, length) ;
|
||||
|
||||
psf_binheader_readf (psf, "E2", &n_channels) ;
|
||||
n_channels = (n_channels & 0x0000FF00) >> 8 ;
|
||||
psf_log_printf (psf, " Channels : %d\n", n_channels) ;
|
||||
|
||||
psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &frames) ;
|
||||
psf->sf.frames = frames ;
|
||||
psf_log_printf (psf, " Sample Rate : %d\n", psf->sf.samplerate) ;
|
||||
psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " ??????????? : %d\n", length) ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
psf_log_printf (psf, " ??????????? : %d\n", length) ;
|
||||
break ;
|
||||
|
||||
case SDAT_MARKER:
|
||||
psf_binheader_readf (psf, "E4", &length) ;
|
||||
|
||||
sdat_length = length ;
|
||||
|
||||
/* Get the current offset. */
|
||||
psf->dataoffset = psf_binheader_readf (psf, NULL) ;
|
||||
|
||||
if (psf->dataoffset + length != psf->filelength)
|
||||
psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ;
|
||||
else
|
||||
psf_log_printf (psf, " %M : %d\n", marker, length) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ;
|
||||
return -1003 ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
/* SDAT always last marker in file. */
|
||||
if (marker == SDAT_MARKER)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
puts (psf->logbuffer) ;
|
||||
puts ("-----------------------------------") ;
|
||||
|
||||
printf ("SDAT length : %d\n", sdat_length) ;
|
||||
printf ("SLCE count : %d\n", slce_count) ;
|
||||
|
||||
/* Hack for zero slice count. */
|
||||
if (slce_count == 0 && slce_total == 1)
|
||||
slce_total = frames ;
|
||||
|
||||
printf ("SLCE samples : %d\n", slce_total) ;
|
||||
|
||||
/* Two bytes per sample. */
|
||||
printf ("Comp Ratio : %f:1\n", (2.0 * slce_total * n_channels) / sdat_length) ;
|
||||
|
||||
puts (" ") ;
|
||||
|
||||
psf->logbuffer [0] = 0 ;
|
||||
|
||||
/* OK, have the header although not too sure what it all means. */
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf_fseek (psf, psf->dataoffset, SEEK_SET))
|
||||
return SFE_BAD_SEEK ;
|
||||
|
||||
psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ;
|
||||
|
||||
psf->sf.channels = 1 ;
|
||||
psf->bytewidth = 2 ;
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
|
||||
if ((error = dwvw_init (psf, 16)))
|
||||
return error ;
|
||||
|
||||
psf->container_close = rx2_close ;
|
||||
|
||||
if (! psf->sf.frames && psf->blockwidth)
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
|
||||
/* All done. */
|
||||
|
||||
return 0 ;
|
||||
} /* rx2_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
rx2_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* Now we know for certain the length of the file we can re-write
|
||||
** correct values for the FORM, 8SVX and BODY chunks.
|
||||
*/
|
||||
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* rx2_close */
|
||||
|
||||
#endif
|
||||
632
project/jni/sndfile/src/sd2.c
Normal file
632
project/jni/sndfile/src/sd2.c
Normal file
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
** Copyright (C) 2004 Paavo Jumppanen
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The sd2 support implemented in this file was partially sponsored
|
||||
** (financially) by Paavo Jumppanen.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Documentation on the Mac resource fork was obtained here :
|
||||
** http://developer.apple.com/documentation/mac/MoreToolbox/MoreToolbox-99.html
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Markers.
|
||||
*/
|
||||
|
||||
#define Sd2f_MARKER MAKE_MARKER ('S', 'd', '2', 'f')
|
||||
#define Sd2a_MARKER MAKE_MARKER ('S', 'd', '2', 'a')
|
||||
#define ALCH_MARKER MAKE_MARKER ('A', 'L', 'C', 'H')
|
||||
#define lsf1_MARKER MAKE_MARKER ('l', 's', 'f', '1')
|
||||
|
||||
#define STR_MARKER MAKE_MARKER ('S', 'T', 'R', ' ')
|
||||
#define sdML_MARKER MAKE_MARKER ('s', 'd', 'M', 'L')
|
||||
|
||||
enum
|
||||
{ RSRC_STR = 111,
|
||||
RSRC_BIN
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ unsigned char * rsrc_data ;
|
||||
int rsrc_len ;
|
||||
int need_to_free_rsrc_data ;
|
||||
|
||||
int data_offset, data_length ;
|
||||
int map_offset, map_length ;
|
||||
|
||||
int type_count, type_offset ;
|
||||
int item_offset ;
|
||||
|
||||
int str_index, str_count ;
|
||||
|
||||
int string_offset ;
|
||||
|
||||
/* All the above just to get these three. */
|
||||
int sample_size, sample_rate, channels ;
|
||||
} SD2_RSRC ;
|
||||
|
||||
typedef struct
|
||||
{ int type ;
|
||||
int id ;
|
||||
char name [32] ;
|
||||
char value [32] ;
|
||||
int value_len ;
|
||||
} STR_RSRC ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Private static functions.
|
||||
*/
|
||||
|
||||
static int sd2_close (SF_PRIVATE *psf) ;
|
||||
|
||||
static int sd2_parse_rsrc_fork (SF_PRIVATE *psf) ;
|
||||
static int parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc) ;
|
||||
|
||||
static int sd2_write_rsrc_fork (SF_PRIVATE *psf, int calc_length) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public functions.
|
||||
*/
|
||||
|
||||
int
|
||||
sd2_open (SF_PRIVATE *psf)
|
||||
{ int subformat, error = 0, valid ;
|
||||
|
||||
/* SD2 is always big endian. */
|
||||
psf->endian = SF_ENDIAN_BIG ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->rsrclength > 0))
|
||||
{ psf_use_rsrc (psf, SF_TRUE) ;
|
||||
valid = psf_file_valid (psf) ;
|
||||
psf_use_rsrc (psf, SF_FALSE) ;
|
||||
if (! valid)
|
||||
{ psf_log_printf (psf, "sd2_open : psf->rsrc.filedes < 0\n") ;
|
||||
return SFE_SD2_BAD_RSRC ;
|
||||
} ;
|
||||
|
||||
error = sd2_parse_rsrc_fork (psf) ;
|
||||
|
||||
if (error)
|
||||
goto error_cleanup ;
|
||||
} ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SD2)
|
||||
{ error = SFE_BAD_OPEN_FORMAT ;
|
||||
goto error_cleanup ;
|
||||
} ;
|
||||
|
||||
subformat = SF_CODEC (psf->sf.format) ;
|
||||
psf->dataoffset = 0 ;
|
||||
|
||||
/* Only open and write the resource in RDWR mode is its current length is zero. */
|
||||
if (psf->file.mode == SFM_WRITE || (psf->file.mode == SFM_RDWR && psf->rsrclength == 0))
|
||||
{ psf->rsrc.mode = psf->file.mode ;
|
||||
psf_open_rsrc (psf) ;
|
||||
|
||||
error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
|
||||
|
||||
if (error)
|
||||
goto error_cleanup ;
|
||||
|
||||
/* Not needed. */
|
||||
psf->write_header = NULL ;
|
||||
} ;
|
||||
|
||||
psf->container_close = sd2_close ;
|
||||
|
||||
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
|
||||
|
||||
switch (subformat)
|
||||
{ case SF_FORMAT_PCM_S8 : /* 8-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_16 : /* 16-bit linear PCM. */
|
||||
case SF_FORMAT_PCM_24 : /* 24-bit linear PCM */
|
||||
error = pcm_init (psf) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
error = SFE_UNIMPLEMENTED ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
|
||||
error_cleanup:
|
||||
|
||||
/* Close the resource fork regardless. We won't need it again. */
|
||||
psf_close_rsrc (psf) ;
|
||||
|
||||
return error ;
|
||||
} /* sd2_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
sd2_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE)
|
||||
{ /* Now we know for certain the audio_length of the file we can re-write
|
||||
** correct values for the FORM, 8SVX and BODY chunks.
|
||||
*/
|
||||
|
||||
} ;
|
||||
|
||||
return 0 ;
|
||||
} /* sd2_close */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline void
|
||||
write_char (unsigned char * data, int offset, char value)
|
||||
{ data [offset] = value ;
|
||||
} /* write_char */
|
||||
|
||||
static inline void
|
||||
write_short (unsigned char * data, int offset, short value)
|
||||
{ data [offset] = value >> 8 ;
|
||||
data [offset + 1] = value ;
|
||||
} /* write_char */
|
||||
|
||||
static inline void
|
||||
write_int (unsigned char * data, int offset, int value)
|
||||
{ data [offset] = value >> 24 ;
|
||||
data [offset + 1] = value >> 16 ;
|
||||
data [offset + 2] = value >> 8 ;
|
||||
data [offset + 3] = value ;
|
||||
} /* write_int */
|
||||
|
||||
static inline void
|
||||
write_marker (unsigned char * data, int offset, int value)
|
||||
{
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
{ data [offset] = value >> 24 ;
|
||||
data [offset + 1] = value >> 16 ;
|
||||
data [offset + 2] = value >> 8 ;
|
||||
data [offset + 3] = value ;
|
||||
}
|
||||
else
|
||||
{ data [offset] = value ;
|
||||
data [offset + 1] = value >> 8 ;
|
||||
data [offset + 2] = value >> 16 ;
|
||||
data [offset + 3] = value >> 24 ;
|
||||
} ;
|
||||
} /* write_marker */
|
||||
|
||||
static void
|
||||
write_str (unsigned char * data, int offset, const char * buffer, int buffer_len)
|
||||
{ memcpy (data + offset, buffer, buffer_len) ;
|
||||
} /* write_str */
|
||||
|
||||
static int
|
||||
sd2_write_rsrc_fork (SF_PRIVATE *psf, int UNUSED (calc_length))
|
||||
{ SD2_RSRC rsrc ;
|
||||
STR_RSRC str_rsrc [] =
|
||||
{ { RSRC_STR, 1000, "_sample-size", "", 0 },
|
||||
{ RSRC_STR, 1001, "_sample-rate", "", 0 },
|
||||
{ RSRC_STR, 1002, "_channels", "", 0 },
|
||||
{ RSRC_BIN, 1000, "_Markers", "", 8 }
|
||||
} ;
|
||||
|
||||
int k, str_offset, data_offset, next_str ;
|
||||
|
||||
psf_use_rsrc (psf, SF_TRUE) ;
|
||||
|
||||
memset (&rsrc, 0, sizeof (rsrc)) ;
|
||||
|
||||
rsrc.sample_rate = psf->sf.samplerate ;
|
||||
rsrc.sample_size = psf->bytewidth ;
|
||||
rsrc.channels = psf->sf.channels ;
|
||||
|
||||
rsrc.rsrc_data = psf->header ;
|
||||
rsrc.rsrc_len = sizeof (psf->header) ;
|
||||
memset (rsrc.rsrc_data, 0xea, rsrc.rsrc_len) ;
|
||||
|
||||
snprintf (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ;
|
||||
snprintf (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ;
|
||||
snprintf (str_rsrc [2].value, sizeof (str_rsrc [2].value), "_%d", rsrc.channels) ;
|
||||
|
||||
for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
|
||||
{ if (str_rsrc [k].value_len == 0)
|
||||
{ str_rsrc [k].value_len = strlen (str_rsrc [k].value) ;
|
||||
str_rsrc [k].value [0] = str_rsrc [k].value_len - 1 ;
|
||||
} ;
|
||||
|
||||
/* Turn name string into a pascal string. */
|
||||
str_rsrc [k].name [0] = strlen (str_rsrc [k].name) - 1 ;
|
||||
} ;
|
||||
|
||||
rsrc.data_offset = 0x100 ;
|
||||
|
||||
/*
|
||||
** Calculate data length :
|
||||
** length of strings, plus the length of the sdML chunk.
|
||||
*/
|
||||
rsrc.data_length = 0 ;
|
||||
for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
|
||||
rsrc.data_length += str_rsrc [k].value_len + 4 ;
|
||||
|
||||
rsrc.map_offset = rsrc.data_offset + rsrc.data_length ;
|
||||
|
||||
/* Very start of resource fork. */
|
||||
write_int (rsrc.rsrc_data, 0, rsrc.data_offset) ;
|
||||
write_int (rsrc.rsrc_data, 4, rsrc.map_offset) ;
|
||||
write_int (rsrc.rsrc_data, 8, rsrc.data_length) ;
|
||||
|
||||
write_char (rsrc.rsrc_data, 0x30, strlen (psf->file.name.c)) ;
|
||||
write_str (rsrc.rsrc_data, 0x31, psf->file.name.c, strlen (psf->file.name.c)) ;
|
||||
|
||||
write_short (rsrc.rsrc_data, 0x50, 0) ;
|
||||
write_marker (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ;
|
||||
write_marker (rsrc.rsrc_data, 0x56, lsf1_MARKER) ;
|
||||
|
||||
/* Very start of resource map. */
|
||||
write_int (rsrc.rsrc_data, rsrc.map_offset + 0, rsrc.data_offset) ;
|
||||
write_int (rsrc.rsrc_data, rsrc.map_offset + 4, rsrc.map_offset) ;
|
||||
write_int (rsrc.rsrc_data, rsrc.map_offset + 8, rsrc.data_length) ;
|
||||
|
||||
/* These I don't currently understand. */
|
||||
if (1)
|
||||
{ write_char (rsrc.rsrc_data, rsrc.map_offset+ 16, 1) ;
|
||||
/* Next resource map. */
|
||||
write_int (rsrc.rsrc_data, rsrc.map_offset + 17, 0x12345678) ;
|
||||
/* File ref number. */
|
||||
write_short (rsrc.rsrc_data, rsrc.map_offset + 21, 0xabcd) ;
|
||||
/* Fork attributes. */
|
||||
write_short (rsrc.rsrc_data, rsrc.map_offset + 23, 0) ;
|
||||
} ;
|
||||
|
||||
/* Resource type offset. */
|
||||
rsrc.type_offset = rsrc.map_offset + 30 ;
|
||||
write_short (rsrc.rsrc_data, rsrc.map_offset + 24, rsrc.type_offset - rsrc.map_offset - 2) ;
|
||||
|
||||
/* Type index max. */
|
||||
rsrc.type_count = 2 ;
|
||||
write_short (rsrc.rsrc_data, rsrc.map_offset + 28, rsrc.type_count - 1) ;
|
||||
|
||||
rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
|
||||
|
||||
rsrc.str_count = ARRAY_LEN (str_rsrc) ;
|
||||
rsrc.string_offset = rsrc.item_offset + (rsrc.str_count + 1) * 12 - rsrc.map_offset ;
|
||||
write_short (rsrc.rsrc_data, rsrc.map_offset + 26, rsrc.string_offset) ;
|
||||
|
||||
/* Write 'STR ' resource type. */
|
||||
rsrc.str_count = 3 ;
|
||||
write_marker (rsrc.rsrc_data, rsrc.type_offset, STR_MARKER) ;
|
||||
write_short (rsrc.rsrc_data, rsrc.type_offset + 4, rsrc.str_count - 1) ;
|
||||
write_short (rsrc.rsrc_data, rsrc.type_offset + 6, 0x12) ;
|
||||
|
||||
/* Write 'sdML' resource type. */
|
||||
write_marker (rsrc.rsrc_data, rsrc.type_offset + 8, sdML_MARKER) ;
|
||||
write_short (rsrc.rsrc_data, rsrc.type_offset + 12, 0) ;
|
||||
write_short (rsrc.rsrc_data, rsrc.type_offset + 14, 0x36) ;
|
||||
|
||||
str_offset = rsrc.map_offset + rsrc.string_offset ;
|
||||
next_str = 0 ;
|
||||
data_offset = rsrc.data_offset ;
|
||||
for (k = 0 ; k < ARRAY_LEN (str_rsrc) ; k++)
|
||||
{ write_str (rsrc.rsrc_data, str_offset, str_rsrc [k].name, strlen (str_rsrc [k].name)) ;
|
||||
|
||||
write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12, str_rsrc [k].id) ;
|
||||
write_short (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 2, next_str) ;
|
||||
|
||||
str_offset += strlen (str_rsrc [k].name) ;
|
||||
next_str += strlen (str_rsrc [k].name) ;
|
||||
|
||||
write_int (rsrc.rsrc_data, rsrc.item_offset + k * 12 + 4, data_offset - rsrc.data_offset) ;
|
||||
|
||||
write_int (rsrc.rsrc_data, data_offset, str_rsrc [k].value_len) ;
|
||||
write_str (rsrc.rsrc_data, data_offset + 4, str_rsrc [k].value, str_rsrc [k].value_len) ;
|
||||
data_offset += 4 + str_rsrc [k].value_len ;
|
||||
} ;
|
||||
|
||||
/* Finally, calculate and set map length. */
|
||||
rsrc.map_length = str_offset - rsrc.map_offset ;
|
||||
write_int (rsrc.rsrc_data, 12, rsrc.map_length) ;
|
||||
write_int (rsrc.rsrc_data, rsrc.map_offset + 12, rsrc.map_length) ;
|
||||
|
||||
rsrc.rsrc_len = rsrc.map_offset + rsrc.map_length ;
|
||||
|
||||
psf_fwrite (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
|
||||
|
||||
psf_use_rsrc (psf, SF_FALSE) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
return 0 ;
|
||||
} /* sd2_write_rsrc_fork */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static inline int
|
||||
read_char (const unsigned char * data, int offset)
|
||||
{ return data [offset] ;
|
||||
} /* read_char */
|
||||
|
||||
static inline int
|
||||
read_short (const unsigned char * data, int offset)
|
||||
{ return (data [offset] << 8) + data [offset + 1] ;
|
||||
} /* read_short */
|
||||
|
||||
static inline int
|
||||
read_int (const unsigned char * data, int offset)
|
||||
{ return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
|
||||
} /* read_int */
|
||||
|
||||
static inline int
|
||||
read_marker (const unsigned char * data, int offset)
|
||||
{
|
||||
if (CPU_IS_BIG_ENDIAN)
|
||||
return (data [offset] << 24) + (data [offset + 1] << 16) + (data [offset + 2] << 8) + data [offset + 3] ;
|
||||
else if (CPU_IS_LITTLE_ENDIAN)
|
||||
return data [offset] + (data [offset + 1] << 8) + (data [offset + 2] << 16) + (data [offset + 3] << 24) ;
|
||||
else
|
||||
return 0x666 ;
|
||||
} /* read_marker */
|
||||
|
||||
static void
|
||||
read_str (const unsigned char * data, int offset, char * buffer, int buffer_len)
|
||||
{ int k ;
|
||||
|
||||
memset (buffer, 0, buffer_len) ;
|
||||
|
||||
for (k = 0 ; k < buffer_len - 1 ; k++)
|
||||
{ if (psf_isprint (data [offset + k]) == 0)
|
||||
return ;
|
||||
buffer [k] = data [offset + k] ;
|
||||
} ;
|
||||
return ;
|
||||
} /* read_str */
|
||||
|
||||
static int
|
||||
sd2_parse_rsrc_fork (SF_PRIVATE *psf)
|
||||
{ SD2_RSRC rsrc ;
|
||||
int k, marker, error = 0 ;
|
||||
|
||||
psf_use_rsrc (psf, SF_TRUE) ;
|
||||
|
||||
memset (&rsrc, 0, sizeof (rsrc)) ;
|
||||
|
||||
rsrc.rsrc_len = psf_get_filelen (psf) ;
|
||||
psf_log_printf (psf, "Resource length : %d (0x%04X)\n", rsrc.rsrc_len, rsrc.rsrc_len) ;
|
||||
|
||||
if (rsrc.rsrc_len > SIGNED_SIZEOF (psf->header))
|
||||
{ rsrc.rsrc_data = calloc (1, rsrc.rsrc_len) ;
|
||||
rsrc.need_to_free_rsrc_data = SF_TRUE ;
|
||||
}
|
||||
else
|
||||
rsrc.rsrc_data = psf->header ;
|
||||
|
||||
/* Read in the whole lot. */
|
||||
psf_fread (rsrc.rsrc_data, rsrc.rsrc_len, 1, psf) ;
|
||||
|
||||
/* Reset the header storage because we have changed to the rsrcdes. */
|
||||
psf->headindex = psf->headend = rsrc.rsrc_len ;
|
||||
|
||||
rsrc.data_offset = read_int (rsrc.rsrc_data, 0) ;
|
||||
rsrc.map_offset = read_int (rsrc.rsrc_data, 4) ;
|
||||
rsrc.data_length = read_int (rsrc.rsrc_data, 8) ;
|
||||
rsrc.map_length = read_int (rsrc.rsrc_data, 12) ;
|
||||
|
||||
if (rsrc.data_offset == 0x51607 && rsrc.map_offset == 0x20000)
|
||||
{ psf_log_printf (psf, "Trying offset of 0x52 bytes.\n") ;
|
||||
rsrc.data_offset = read_int (rsrc.rsrc_data, 0x52 + 0) + 0x52 ;
|
||||
rsrc.map_offset = read_int (rsrc.rsrc_data, 0x52 + 4) + 0x52 ;
|
||||
rsrc.data_length = read_int (rsrc.rsrc_data, 0x52 + 8) ;
|
||||
rsrc.map_length = read_int (rsrc.rsrc_data, 0x52 + 12) ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " data offset : 0x%04X\n map offset : 0x%04X\n"
|
||||
" data length : 0x%04X\n map length : 0x%04X\n",
|
||||
rsrc.data_offset, rsrc.map_offset, rsrc.data_length, rsrc.map_length) ;
|
||||
|
||||
if (rsrc.data_offset > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Error : rsrc.data_offset (%d, 0x%x) > len\n", rsrc.data_offset, rsrc.data_offset) ;
|
||||
error = SFE_SD2_BAD_DATA_OFFSET ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
if (rsrc.map_offset > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Error : rsrc.map_offset > len\n") ;
|
||||
error = SFE_SD2_BAD_MAP_OFFSET ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
if (rsrc.data_length > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Error : rsrc.data_length > len\n") ;
|
||||
error = SFE_SD2_BAD_DATA_LENGTH ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
if (rsrc.map_length > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Error : rsrc.map_length > len\n") ;
|
||||
error = SFE_SD2_BAD_MAP_LENGTH ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
if (rsrc.data_offset + rsrc.data_length != rsrc.map_offset || rsrc.map_offset + rsrc.map_length != rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Error : This does not look like a MacOSX resource fork.\n") ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
if (rsrc.map_offset + 28 >= rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Bad map offset (%d + 28 > %d).\n", rsrc.map_offset, rsrc.rsrc_len) ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
rsrc.string_offset = rsrc.map_offset + read_short (rsrc.rsrc_data, rsrc.map_offset + 26) ;
|
||||
if (rsrc.string_offset > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Bad string offset (%d).\n", rsrc.string_offset) ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
rsrc.type_offset = rsrc.map_offset + 30 ;
|
||||
|
||||
rsrc.type_count = read_short (rsrc.rsrc_data, rsrc.map_offset + 28) + 1 ;
|
||||
if (rsrc.type_count < 1)
|
||||
{ psf_log_printf (psf, "Bad type count.\n") ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
rsrc.item_offset = rsrc.type_offset + rsrc.type_count * 8 ;
|
||||
if (rsrc.item_offset < 0 || rsrc.item_offset > rsrc.rsrc_len)
|
||||
{ psf_log_printf (psf, "Bad item offset (%d).\n", rsrc.item_offset) ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
|
||||
rsrc.str_index = -1 ;
|
||||
for (k = 0 ; k < rsrc.type_count ; k ++)
|
||||
{ marker = read_marker (rsrc.rsrc_data, rsrc.type_offset + k * 8) ;
|
||||
|
||||
if (marker == STR_MARKER)
|
||||
{ rsrc.str_index = k ;
|
||||
rsrc.str_count = read_short (rsrc.rsrc_data, rsrc.type_offset + k * 8 + 4) + 1 ;
|
||||
error = parse_str_rsrc (psf, &rsrc) ;
|
||||
goto parse_rsrc_fork_cleanup ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "No 'STR ' resource.\n") ;
|
||||
error = SFE_SD2_BAD_RSRC ;
|
||||
|
||||
parse_rsrc_fork_cleanup :
|
||||
|
||||
psf_use_rsrc (psf, SF_FALSE) ;
|
||||
|
||||
if (rsrc.need_to_free_rsrc_data)
|
||||
free (rsrc.rsrc_data) ;
|
||||
|
||||
return error ;
|
||||
} /* sd2_parse_rsrc_fork */
|
||||
|
||||
static int
|
||||
parse_str_rsrc (SF_PRIVATE *psf, SD2_RSRC * rsrc)
|
||||
{ char name [32], value [32] ;
|
||||
int k, str_offset, rsrc_id, data_offset = 0, data_len = 0 ;
|
||||
|
||||
psf_log_printf (psf, "Finding parameters :\n") ;
|
||||
|
||||
str_offset = rsrc->string_offset ;
|
||||
psf_log_printf (psf, " Offset RsrcId dlen slen Value\n") ;
|
||||
|
||||
for (k = 0 ; data_offset + data_len < rsrc->rsrc_len ; k++)
|
||||
{ int slen ;
|
||||
|
||||
slen = read_char (rsrc->rsrc_data, str_offset) ;
|
||||
read_str (rsrc->rsrc_data, str_offset + 1, name, SF_MIN (SIGNED_SIZEOF (name), slen + 1)) ;
|
||||
str_offset += slen + 1 ;
|
||||
|
||||
rsrc_id = read_short (rsrc->rsrc_data, rsrc->item_offset + k * 12) ;
|
||||
|
||||
data_offset = rsrc->data_offset + read_int (rsrc->rsrc_data, rsrc->item_offset + k * 12 + 4) ;
|
||||
if (data_offset < 0 || data_offset > rsrc->rsrc_len)
|
||||
{ psf_log_printf (psf, "Exiting parser on data offset of %d.\n", data_offset) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
data_len = read_int (rsrc->rsrc_data, data_offset) ;
|
||||
if (data_len < 0 || data_len > rsrc->rsrc_len)
|
||||
{ psf_log_printf (psf, "Exiting parser on data length of %d.\n", data_len) ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
slen = read_char (rsrc->rsrc_data, data_offset + 4) ;
|
||||
read_str (rsrc->rsrc_data, data_offset + 5, value, SF_MIN (SIGNED_SIZEOF (value), slen + 1)) ;
|
||||
|
||||
psf_log_printf (psf, " 0x%04x %4d %4d %3d '%s'\n", data_offset, rsrc_id, data_len, slen, value) ;
|
||||
|
||||
if (rsrc_id == 1000 && rsrc->sample_size == 0)
|
||||
rsrc->sample_size = strtol (value, NULL, 10) ;
|
||||
else if (rsrc_id == 1001 && rsrc->sample_rate == 0)
|
||||
rsrc->sample_rate = strtol (value, NULL, 10) ;
|
||||
else if (rsrc_id == 1002 && rsrc->channels == 0)
|
||||
rsrc->channels = strtol (value, NULL, 10) ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "Found Parameters :\n") ;
|
||||
psf_log_printf (psf, " sample-size : %d\n", rsrc->sample_size) ;
|
||||
psf_log_printf (psf, " sample-rate : %d\n", rsrc->sample_rate) ;
|
||||
psf_log_printf (psf, " channels : %d\n", rsrc->channels) ;
|
||||
|
||||
if (rsrc->sample_rate <= 4 && rsrc->sample_size > 4)
|
||||
{ int temp ;
|
||||
|
||||
psf_log_printf (psf, "Geez!! Looks like sample rate and sample size got switched.\nCorrecting this screw up.\n") ;
|
||||
temp = rsrc->sample_rate ;
|
||||
rsrc->sample_rate = rsrc->sample_size ;
|
||||
rsrc->sample_size = temp ;
|
||||
} ;
|
||||
|
||||
if (rsrc->sample_rate < 0)
|
||||
{ psf_log_printf (psf, "Bad sample rate (%d)\n", rsrc->sample_rate) ;
|
||||
return SFE_SD2_BAD_RSRC ;
|
||||
} ;
|
||||
|
||||
if (rsrc->channels < 0)
|
||||
{ psf_log_printf (psf, "Bad channel count (%d)\n", rsrc->channels) ;
|
||||
return SFE_SD2_BAD_RSRC ;
|
||||
} ;
|
||||
|
||||
psf->sf.samplerate = rsrc->sample_rate ;
|
||||
psf->sf.channels = rsrc->channels ;
|
||||
psf->bytewidth = rsrc->sample_size ;
|
||||
|
||||
switch (rsrc->sample_size)
|
||||
{ case 1 :
|
||||
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_S8 ;
|
||||
break ;
|
||||
|
||||
case 2 :
|
||||
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ;
|
||||
break ;
|
||||
|
||||
case 3 :
|
||||
psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_24 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "Bad sample size (%d)\n", rsrc->sample_size) ;
|
||||
return SFE_SD2_BAD_SAMPLE_SIZE ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, "ok\n") ;
|
||||
|
||||
return 0 ;
|
||||
} /* parse_str_rsrc */
|
||||
|
||||
1005
project/jni/sndfile/src/sds.c
Normal file
1005
project/jni/sndfile/src/sds.c
Normal file
File diff suppressed because it is too large
Load Diff
63
project/jni/sndfile/src/sf_unistd.h
Normal file
63
project/jni/sndfile/src/sf_unistd.h
Normal file
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/* Some defines that microsoft 'forgot' to implement. */
|
||||
|
||||
#ifndef S_IRWXU
|
||||
#define S_IRWXU 0000700 /* rwx, owner */
|
||||
#endif
|
||||
|
||||
#ifndef S_IRUSR
|
||||
#define S_IRUSR 0000400 /* read permission, owner */
|
||||
#endif
|
||||
|
||||
#ifndef S_IWUSR
|
||||
#define S_IWUSR 0000200 /* write permission, owner */
|
||||
#endif
|
||||
|
||||
#ifndef S_IXUSR
|
||||
#define S_IXUSR 0000100 /* execute/search permission, owner */
|
||||
#endif
|
||||
|
||||
/* Windows doesn't have group permissions so set all these to zero. */
|
||||
#define S_IRWXG 0 /* rwx, group */
|
||||
#define S_IRGRP 0 /* read permission, group */
|
||||
#define S_IWGRP 0 /* write permission, grougroup */
|
||||
#define S_IXGRP 0 /* execute/search permission, group */
|
||||
|
||||
/* Windows doesn't have others permissions so set all these to zero. */
|
||||
#define S_IRWXO 0 /* rwx, other */
|
||||
#define S_IROTH 0 /* read permission, other */
|
||||
#define S_IWOTH 0 /* write permission, other */
|
||||
#define S_IXOTH 0 /* execute/search permission, other */
|
||||
|
||||
#ifndef S_ISFIFO
|
||||
#define S_ISFIFO(mode) (((mode) & _S_IFMT) == _S_IFIFO)
|
||||
#endif
|
||||
|
||||
#ifndef S_ISREG
|
||||
#define S_ISREG(mode) (((mode) & _S_IFREG) == _S_IFREG)
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Don't know if these are still needed.
|
||||
**
|
||||
** #define _IFMT _S_IFMT
|
||||
** #define _IFREG _S_IFREG
|
||||
*/
|
||||
|
||||
113
project/jni/sndfile/src/sfconfig.h
Normal file
113
project/jni/sndfile/src/sfconfig.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** Autoconf leaves many config parameters undefined.
|
||||
** Here we change then from being undefined to defining them to 0.
|
||||
** This allows things like:
|
||||
**
|
||||
** #if HAVE_CONFIG_PARAM
|
||||
**
|
||||
** and
|
||||
**
|
||||
** if (HAVE_CONFIG_PARAM)
|
||||
** do_something () ;
|
||||
*/
|
||||
|
||||
#ifndef SFCONFIG_H
|
||||
#define SFCONFIG_H
|
||||
|
||||
/* Include the Autoconf generated file. */
|
||||
#include "config.h"
|
||||
|
||||
/* Now fiddle the values. */
|
||||
|
||||
#ifndef HAVE_ALSA_ASOUNDLIB_H
|
||||
#define HAVE_ALSA_ASOUNDLIB_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_BYTESWAP_H
|
||||
#define HAVE_BYTESWAP_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_DECL_S_IRGRP
|
||||
#define HAVE_DECL_S_IRGRP 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_ENDIAN_H
|
||||
#define HAVE_ENDIAN_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_FSYNC
|
||||
#define HAVE_FSYNC 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LOCALE_H
|
||||
#define HAVE_LOCALE_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LRINT
|
||||
#define HAVE_LRINT 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_LRINTF
|
||||
#define HAVE_LRINTF 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_MMAP
|
||||
#define HAVE_MMAP 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PREAD
|
||||
#define HAVE_PREAD 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PWRITE
|
||||
#define HAVE_PWRITE 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SETLOCALE
|
||||
#define HAVE_SETLOCALE 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SQLITE3
|
||||
#define HAVE_SQLITE3 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_STDINT_H
|
||||
#define HAVE_STDINT_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_SYS_WAIT_H
|
||||
#define HAVE_SYS_WAIT_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_UNISTD_H
|
||||
#define HAVE_UNISTD_H 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_PIPE
|
||||
#define HAVE_PIPE 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_WAITPID
|
||||
#define HAVE_WAITPID 0
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
254
project/jni/sndfile/src/sfendian.h
Normal file
254
project/jni/sndfile/src/sfendian.h
Normal file
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 SFENDIAN_INCLUDED
|
||||
#define SFENDIAN_INCLUDED
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#if HAVE_STDINT_H
|
||||
#include <stdint.h>
|
||||
#elif HAVE_INTTYPES_H
|
||||
#include <inttypes.h>
|
||||
#endif
|
||||
|
||||
#if (defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
/* Good, we have int64_t. */
|
||||
#elif (defined (SIZEOF_LONG_LONG) && (SIZEOF_LONG_LONG == 8))
|
||||
typedef long long int64_t ;
|
||||
#elif (defined (SIZEOF_LONG) && (SIZEOF_LONG == 8))
|
||||
typedef long int64_t ;
|
||||
#elif (defined (WIN32) || defined (_WIN32))
|
||||
typedef __int64 int64_t ;
|
||||
#else
|
||||
#error "No 64 bit integer type."
|
||||
#endif
|
||||
|
||||
#if HAVE_BYTESWAP_H
|
||||
|
||||
#include <byteswap.h>
|
||||
|
||||
#define ENDSWAP_SHORT(x) ((short) bswap_16 (x))
|
||||
#define ENDSWAP_INT(x) ((int) bswap_32 (x))
|
||||
|
||||
#else
|
||||
|
||||
#define ENDSWAP_SHORT(x) ((((x) >> 8) & 0xFF) + (((x) & 0xFF) << 8))
|
||||
#define ENDSWAP_INT(x) ((((x) >> 24) & 0xFF) + (((x) >> 8) & 0xFF00) + (((x) & 0xFF00) << 8) + (((x) & 0xFF) << 24))
|
||||
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Many file types (ie WAV, AIFF) use sets of four consecutive bytes as a
|
||||
** marker indicating different sections of the file.
|
||||
** The following MAKE_MARKER macro allows th creation of integer constants
|
||||
** for these markers.
|
||||
*/
|
||||
|
||||
#if (CPU_IS_LITTLE_ENDIAN == 1)
|
||||
#define MAKE_MARKER(a,b,c,d) ((a) | ((b) << 8) | ((c) << 16) | ((d) << 24))
|
||||
#elif (CPU_IS_BIG_ENDIAN == 1)
|
||||
#define MAKE_MARKER(a,b,c,d) (((a) << 24) | ((b) << 16) | ((c) << 8) | (d))
|
||||
#else
|
||||
#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
|
||||
#endif
|
||||
|
||||
/*
|
||||
** Macros to handle reading of data of a specific endian-ness into host endian
|
||||
** shorts and ints. The single input is an unsigned char* pointer to the start
|
||||
** of the object. There are two versions of each macro as we need to deal with
|
||||
** both big and little endian CPUs.
|
||||
*/
|
||||
|
||||
#if (CPU_IS_LITTLE_ENDIAN == 1)
|
||||
#define LES2H_SHORT(x) (x)
|
||||
#define LEI2H_INT(x) (x)
|
||||
|
||||
#define BES2H_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define BEI2H_INT(x) ENDSWAP_INT (x)
|
||||
|
||||
#define H2BE_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define H2BE_INT(x) ENDSWAP_INT (x)
|
||||
|
||||
#elif (CPU_IS_BIG_ENDIAN == 1)
|
||||
#define LES2H_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define LEI2H_INT(x) ENDSWAP_INT (x)
|
||||
|
||||
#define BES2H_SHORT(x) (x)
|
||||
#define BEI2H_INT(x) (x)
|
||||
|
||||
#define H2LE_SHORT(x) ENDSWAP_SHORT (x)
|
||||
#define H2LE_INT(x) ENDSWAP_INT (x)
|
||||
|
||||
#else
|
||||
#error "Target CPU endian-ness unknown. May need to hand edit src/sfconfig.h"
|
||||
#endif
|
||||
|
||||
#define LET2H_SHORT_PTR(x) ((x) [1] + ((x) [2] << 8))
|
||||
#define LET2H_INT_PTR(x) (((x) [0] << 8) + ((x) [1] << 16) + ((x) [2] << 24))
|
||||
|
||||
#define BET2H_SHORT_PTR(x) (((x) [0] << 8) + (x) [1])
|
||||
#define BET2H_INT_PTR(x) (((x) [0] << 24) + ((x) [1] << 16) + ((x) [2] << 8))
|
||||
|
||||
/*-----------------------------------------------------------------------------------------------
|
||||
** Generic functions for performing endian swapping on integer arrays.
|
||||
*/
|
||||
|
||||
static inline void
|
||||
endswap_short_array (short *ptr, int len)
|
||||
{ short temp ;
|
||||
|
||||
while (--len >= 0)
|
||||
{ temp = ptr [len] ;
|
||||
ptr [len] = ENDSWAP_SHORT (temp) ;
|
||||
} ;
|
||||
} /* endswap_short_array */
|
||||
|
||||
static inline void
|
||||
endswap_short_copy (short *dest, const short *src, int len)
|
||||
{
|
||||
while (--len >= 0)
|
||||
{ dest [len] = ENDSWAP_SHORT (src [len]) ;
|
||||
} ;
|
||||
} /* endswap_short_copy */
|
||||
|
||||
static inline void
|
||||
endswap_int_array (int *ptr, int len)
|
||||
{ int temp ;
|
||||
|
||||
while (--len >= 0)
|
||||
{ temp = ptr [len] ;
|
||||
ptr [len] = ENDSWAP_INT (temp) ;
|
||||
} ;
|
||||
} /* endswap_int_array */
|
||||
|
||||
static inline void
|
||||
endswap_int_copy (int *dest, const int *src, int len)
|
||||
{
|
||||
while (--len >= 0)
|
||||
{ dest [len] = ENDSWAP_INT (src [len]) ;
|
||||
} ;
|
||||
} /* endswap_int_copy */
|
||||
|
||||
/*========================================================================================
|
||||
*/
|
||||
|
||||
#if (HAVE_BYTESWAP_H && defined (SIZEOF_INT64_T) && (SIZEOF_INT64_T == 8))
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_array (int64_t *ptr, int len)
|
||||
{ int64_t value ;
|
||||
|
||||
while (--len >= 0)
|
||||
{ value = ptr [len] ;
|
||||
ptr [len] = bswap_64 (value) ;
|
||||
} ;
|
||||
} /* endswap_int64_t_array */
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
|
||||
{ int64_t value ;
|
||||
|
||||
while (--len >= 0)
|
||||
{ value = src [len] ;
|
||||
dest [len] = bswap_64 (value) ;
|
||||
} ;
|
||||
} /* endswap_int64_t_copy */
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_array (int64_t *ptr, int len)
|
||||
{ unsigned char *ucptr, temp ;
|
||||
|
||||
ucptr = (unsigned char *) ptr ;
|
||||
ucptr += 8 * len ;
|
||||
while (--len >= 0)
|
||||
{ ucptr -= 8 ;
|
||||
|
||||
temp = ucptr [0] ;
|
||||
ucptr [0] = ucptr [7] ;
|
||||
ucptr [7] = temp ;
|
||||
|
||||
temp = ucptr [1] ;
|
||||
ucptr [1] = ucptr [6] ;
|
||||
ucptr [6] = temp ;
|
||||
|
||||
temp = ucptr [2] ;
|
||||
ucptr [2] = ucptr [5] ;
|
||||
ucptr [5] = temp ;
|
||||
|
||||
temp = ucptr [3] ;
|
||||
ucptr [3] = ucptr [4] ;
|
||||
ucptr [4] = temp ;
|
||||
} ;
|
||||
} /* endswap_int64_t_array */
|
||||
|
||||
static inline void
|
||||
endswap_int64_t_copy (int64_t *dest, const int64_t *src, int len)
|
||||
{ const unsigned char *psrc ;
|
||||
unsigned char *pdest ;
|
||||
|
||||
if (dest == src)
|
||||
{ endswap_int64_t_array (dest, len) ;
|
||||
return ;
|
||||
} ;
|
||||
|
||||
psrc = ((const unsigned char *) src) + 8 * len ;
|
||||
pdest = ((unsigned char *) dest) + 8 * len ;
|
||||
while (--len >= 0)
|
||||
{ psrc -= 8 ;
|
||||
pdest -= 8 ;
|
||||
|
||||
pdest [0] = psrc [7] ;
|
||||
pdest [2] = psrc [5] ;
|
||||
pdest [4] = psrc [3] ;
|
||||
pdest [6] = psrc [1] ;
|
||||
pdest [7] = psrc [0] ;
|
||||
pdest [1] = psrc [6] ;
|
||||
pdest [3] = psrc [4] ;
|
||||
pdest [5] = psrc [2] ;
|
||||
} ;
|
||||
} /* endswap_int64_t_copy */
|
||||
|
||||
#endif
|
||||
|
||||
/* A couple of wrapper functions. */
|
||||
|
||||
static inline void
|
||||
endswap_float_array (float *ptr, int len)
|
||||
{ endswap_int_array ((void *) ptr, len) ;
|
||||
} /* endswap_float_array */
|
||||
|
||||
static inline void
|
||||
endswap_double_array (double *ptr, int len)
|
||||
{ endswap_int64_t_array ((void *) ptr, len) ;
|
||||
} /* endswap_double_array */
|
||||
|
||||
static inline void
|
||||
endswap_float_copy (float *dest, const float *src, int len)
|
||||
{ endswap_int_copy ((int *) dest, (const int *) src, len) ;
|
||||
} /* endswap_float_copy */
|
||||
|
||||
static inline void
|
||||
endswap_double_copy (double *dest, const double *src, int len)
|
||||
{ endswap_int64_t_copy ((int64_t *) dest, (const int64_t *) src, len) ;
|
||||
} /* endswap_double_copy */
|
||||
|
||||
#endif /* SFENDIAN_INCLUDED */
|
||||
|
||||
2923
project/jni/sndfile/src/sndfile.c
Normal file
2923
project/jni/sndfile/src/sndfile.c
Normal file
File diff suppressed because it is too large
Load Diff
666
project/jni/sndfile/src/sndfile.h
Normal file
666
project/jni/sndfile/src/sndfile.h
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** sndfile.h -- system-wide definitions
|
||||
**
|
||||
** API documentation is in the doc/ directory of the source code tarball
|
||||
** and at http://www.mega-nerd.com/libsndfile/api.html.
|
||||
*/
|
||||
|
||||
#ifndef SNDFILE_H
|
||||
#define SNDFILE_H
|
||||
|
||||
/* This is the version 1.0.X header file. */
|
||||
#define SNDFILE_1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* The following file types can be read and written.
|
||||
** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise
|
||||
** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and
|
||||
** SF_FORMAT_SUBMASK can be used to separate the major and minor file
|
||||
** types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /* Major formats. */
|
||||
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */
|
||||
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
|
||||
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
|
||||
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
|
||||
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
|
||||
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
|
||||
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
|
||||
SF_FORMAT_VOC = 0x080000, /* VOC files. */
|
||||
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
|
||||
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
|
||||
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
|
||||
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
|
||||
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
|
||||
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
|
||||
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
|
||||
SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */
|
||||
SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */
|
||||
SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */
|
||||
SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */
|
||||
SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */
|
||||
SF_FORMAT_CAF = 0x180000, /* Core Audio File format */
|
||||
SF_FORMAT_WVE = 0x190000, /* Psion WVE format */
|
||||
SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */
|
||||
SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */
|
||||
SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */
|
||||
|
||||
/* Subtypes from here on. */
|
||||
|
||||
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
|
||||
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
|
||||
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
|
||||
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
|
||||
|
||||
SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */
|
||||
|
||||
SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */
|
||||
SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */
|
||||
|
||||
SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */
|
||||
SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */
|
||||
SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */
|
||||
SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */
|
||||
|
||||
SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */
|
||||
SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */
|
||||
|
||||
SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */
|
||||
SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */
|
||||
SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */
|
||||
|
||||
SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */
|
||||
|
||||
SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */
|
||||
SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */
|
||||
|
||||
SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */
|
||||
|
||||
/* Endian-ness options. */
|
||||
|
||||
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
|
||||
SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */
|
||||
SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */
|
||||
SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */
|
||||
|
||||
SF_FORMAT_SUBMASK = 0x0000FFFF,
|
||||
SF_FORMAT_TYPEMASK = 0x0FFF0000,
|
||||
SF_FORMAT_ENDMASK = 0x30000000
|
||||
} ;
|
||||
|
||||
/*
|
||||
** The following are the valid command numbers for the sf_command()
|
||||
** interface. The use of these commands is documented in the file
|
||||
** command.html in the doc directory of the source code distribution.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFC_GET_LIB_VERSION = 0x1000,
|
||||
SFC_GET_LOG_INFO = 0x1001,
|
||||
SFC_GET_CURRENT_SF_INFO = 0x1002,
|
||||
|
||||
|
||||
SFC_GET_NORM_DOUBLE = 0x1010,
|
||||
SFC_GET_NORM_FLOAT = 0x1011,
|
||||
SFC_SET_NORM_DOUBLE = 0x1012,
|
||||
SFC_SET_NORM_FLOAT = 0x1013,
|
||||
SFC_SET_SCALE_FLOAT_INT_READ = 0x1014,
|
||||
SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015,
|
||||
|
||||
SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020,
|
||||
SFC_GET_SIMPLE_FORMAT = 0x1021,
|
||||
|
||||
SFC_GET_FORMAT_INFO = 0x1028,
|
||||
|
||||
SFC_GET_FORMAT_MAJOR_COUNT = 0x1030,
|
||||
SFC_GET_FORMAT_MAJOR = 0x1031,
|
||||
SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032,
|
||||
SFC_GET_FORMAT_SUBTYPE = 0x1033,
|
||||
|
||||
SFC_CALC_SIGNAL_MAX = 0x1040,
|
||||
SFC_CALC_NORM_SIGNAL_MAX = 0x1041,
|
||||
SFC_CALC_MAX_ALL_CHANNELS = 0x1042,
|
||||
SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043,
|
||||
SFC_GET_SIGNAL_MAX = 0x1044,
|
||||
SFC_GET_MAX_ALL_CHANNELS = 0x1045,
|
||||
|
||||
SFC_SET_ADD_PEAK_CHUNK = 0x1050,
|
||||
SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051,
|
||||
|
||||
SFC_UPDATE_HEADER_NOW = 0x1060,
|
||||
SFC_SET_UPDATE_HEADER_AUTO = 0x1061,
|
||||
|
||||
SFC_FILE_TRUNCATE = 0x1080,
|
||||
|
||||
SFC_SET_RAW_START_OFFSET = 0x1090,
|
||||
|
||||
SFC_SET_DITHER_ON_WRITE = 0x10A0,
|
||||
SFC_SET_DITHER_ON_READ = 0x10A1,
|
||||
|
||||
SFC_GET_DITHER_INFO_COUNT = 0x10A2,
|
||||
SFC_GET_DITHER_INFO = 0x10A3,
|
||||
|
||||
SFC_GET_EMBED_FILE_INFO = 0x10B0,
|
||||
|
||||
SFC_SET_CLIPPING = 0x10C0,
|
||||
SFC_GET_CLIPPING = 0x10C1,
|
||||
|
||||
SFC_GET_INSTRUMENT = 0x10D0,
|
||||
SFC_SET_INSTRUMENT = 0x10D1,
|
||||
|
||||
SFC_GET_LOOP_INFO = 0x10E0,
|
||||
|
||||
SFC_GET_BROADCAST_INFO = 0x10F0,
|
||||
SFC_SET_BROADCAST_INFO = 0x10F1,
|
||||
|
||||
SFC_GET_CHANNEL_MAP_INFO = 0x1100,
|
||||
SFC_SET_CHANNEL_MAP_INFO = 0x1101,
|
||||
|
||||
SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110,
|
||||
|
||||
/* Support for Wavex Ambisonics Format */
|
||||
SFC_WAVEX_SET_AMBISONIC = 0x1200,
|
||||
SFC_WAVEX_GET_AMBISONIC = 0x1201,
|
||||
|
||||
SFC_SET_VBR_ENCODING_QUALITY = 0x1300,
|
||||
|
||||
/* Following commands for testing only. */
|
||||
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
|
||||
|
||||
/*
|
||||
** SFC_SET_ADD_* values are deprecated and will disappear at some
|
||||
** time in the future. They are guaranteed to be here up to and
|
||||
** including version 1.0.8 to avoid breakage of existng software.
|
||||
** They currently do nothing and will continue to do nothing.
|
||||
*/
|
||||
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
|
||||
SFC_SET_ADD_DITHER_ON_READ = 0x1071
|
||||
} ;
|
||||
|
||||
|
||||
/*
|
||||
** String types that can be set and read from files. Not all file types
|
||||
** support this and even the file types which support one, may not support
|
||||
** all string types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_STR_TITLE = 0x01,
|
||||
SF_STR_COPYRIGHT = 0x02,
|
||||
SF_STR_SOFTWARE = 0x03,
|
||||
SF_STR_ARTIST = 0x04,
|
||||
SF_STR_COMMENT = 0x05,
|
||||
SF_STR_DATE = 0x06,
|
||||
SF_STR_ALBUM = 0x07,
|
||||
SF_STR_LICENSE = 0x08,
|
||||
SF_STR_TRACKNUMBER = 0x09,
|
||||
SF_STR_GENRE = 0x10
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Use the following as the start and end index when doing metadata
|
||||
** transcoding.
|
||||
*/
|
||||
|
||||
#define SF_STR_FIRST SF_STR_TITLE
|
||||
#define SF_STR_LAST SF_STR_GENRE
|
||||
|
||||
enum
|
||||
{ /* True and false */
|
||||
SF_FALSE = 0,
|
||||
SF_TRUE = 1,
|
||||
|
||||
/* Modes for opening files. */
|
||||
SFM_READ = 0x10,
|
||||
SFM_WRITE = 0x20,
|
||||
SFM_RDWR = 0x30,
|
||||
|
||||
SF_AMBISONIC_NONE = 0x40,
|
||||
SF_AMBISONIC_B_FORMAT = 0x41
|
||||
} ;
|
||||
|
||||
/* Public error values. These are guaranteed to remain unchanged for the duration
|
||||
** of the library major version number.
|
||||
** There are also a large number of private error numbers which are internal to
|
||||
** the library which can change at any time.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_ERR_NO_ERROR = 0,
|
||||
SF_ERR_UNRECOGNISED_FORMAT = 1,
|
||||
SF_ERR_SYSTEM = 2,
|
||||
SF_ERR_MALFORMED_FILE = 3,
|
||||
SF_ERR_UNSUPPORTED_ENCODING = 4
|
||||
} ;
|
||||
|
||||
|
||||
/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP).
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_CHANNEL_MAP_INVALID = 0,
|
||||
SF_CHANNEL_MAP_MONO = 1,
|
||||
SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */
|
||||
SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */
|
||||
SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT,
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT,
|
||||
SF_CHANNEL_MAP_FRONT_CENTER,
|
||||
SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */
|
||||
SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */
|
||||
SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */
|
||||
SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */
|
||||
SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */
|
||||
SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */
|
||||
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_W,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_X,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Y,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Z,
|
||||
|
||||
SF_CHANNEL_MAP_MAX
|
||||
} ;
|
||||
|
||||
|
||||
/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */
|
||||
|
||||
typedef struct SNDFILE_tag SNDFILE ;
|
||||
|
||||
/* The following typedef is system specific and is defined when libsndfile is
|
||||
** compiled. sf_count_t will be a 64 bit value when the underlying OS allows
|
||||
** 64 bit file offsets.
|
||||
** On windows, we need to allow the same header file to be compiler by both GCC
|
||||
** and the Microsoft compiler.
|
||||
*/
|
||||
|
||||
#if (defined (_MSCVER) || defined (_MSC_VER))
|
||||
typedef __int64 sf_count_t ;
|
||||
#define SF_COUNT_MAX 0x7fffffffffffffffi64
|
||||
#else
|
||||
typedef int64_t sf_count_t ;
|
||||
#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
|
||||
#endif
|
||||
|
||||
|
||||
/* A pointer to a SF_INFO structure is passed to sf_open () and filled in.
|
||||
** On write, the SF_INFO structure is filled in by the user and passed into
|
||||
** sf_open ().
|
||||
*/
|
||||
|
||||
struct SF_INFO
|
||||
{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */
|
||||
int samplerate ;
|
||||
int channels ;
|
||||
int format ;
|
||||
int sections ;
|
||||
int seekable ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_INFO SF_INFO ;
|
||||
|
||||
/* The SF_FORMAT_INFO struct is used to retrieve information about the sound
|
||||
** file formats libsndfile supports using the sf_command () interface.
|
||||
**
|
||||
** Using this interface will allow applications to support new file formats
|
||||
** and encoding types when libsndfile is upgraded, without requiring
|
||||
** re-compilation of the application.
|
||||
**
|
||||
** Please consult the libsndfile documentation (particularly the information
|
||||
** on the sf_command () interface) for examples of its use.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int format ;
|
||||
const char *name ;
|
||||
const char *extension ;
|
||||
} SF_FORMAT_INFO ;
|
||||
|
||||
/*
|
||||
** Enums and typedefs for adding dither on read and write.
|
||||
** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
|
||||
** and SFC_SET_DITHER_ON_READ.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFD_DEFAULT_LEVEL = 0,
|
||||
SFD_CUSTOM_LEVEL = 0x40000000,
|
||||
|
||||
SFD_NO_DITHER = 500,
|
||||
SFD_WHITE = 501,
|
||||
SFD_TRIANGULAR_PDF = 502
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ int type ;
|
||||
double level ;
|
||||
const char *name ;
|
||||
} SF_DITHER_INFO ;
|
||||
|
||||
/* Struct used to retrieve information about a file embedded within a
|
||||
** larger file. See SFC_GET_EMBED_FILE_INFO.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t offset ;
|
||||
sf_count_t length ;
|
||||
} SF_EMBED_FILE_INFO ;
|
||||
|
||||
/*
|
||||
** Structs used to retrieve music sample information from a file.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /*
|
||||
** The loop mode field in SF_INSTRUMENT will be one of the following.
|
||||
*/
|
||||
SF_LOOP_NONE = 800,
|
||||
SF_LOOP_FORWARD,
|
||||
SF_LOOP_BACKWARD,
|
||||
SF_LOOP_ALTERNATING
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ int gain ;
|
||||
char basenote, detune ;
|
||||
char velocity_lo, velocity_hi ;
|
||||
char key_lo, key_hi ;
|
||||
int loop_count ;
|
||||
|
||||
struct
|
||||
{ int mode ;
|
||||
unsigned int start ;
|
||||
unsigned int end ;
|
||||
unsigned int count ;
|
||||
} loops [16] ; /* make variable in a sensible way */
|
||||
} SF_INSTRUMENT ;
|
||||
|
||||
|
||||
|
||||
/* Struct used to retrieve loop information from a file.*/
|
||||
typedef struct
|
||||
{
|
||||
short time_sig_num ; /* any positive integer > 0 */
|
||||
short time_sig_den ; /* any positive power of 2 > 0 */
|
||||
int loop_mode ; /* see SF_LOOP enum */
|
||||
|
||||
int num_beats ; /* this is NOT the amount of quarter notes !!!*/
|
||||
/* a full bar of 4/4 is 4 beats */
|
||||
/* a full bar of 7/8 is 7 beats */
|
||||
|
||||
float bpm ; /* suggestion, as it can be calculated using other fields:*/
|
||||
/* file's lenght, file's sampleRate and our time_sig_den*/
|
||||
/* -> bpms are always the amount of _quarter notes_ per minute */
|
||||
|
||||
int root_key ; /* MIDI note, or -1 for None */
|
||||
int future [6] ;
|
||||
} SF_LOOP_INFO ;
|
||||
|
||||
|
||||
/* Struct used to retrieve broadcast (EBU) information from a file.
|
||||
** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
|
||||
*/
|
||||
#define SF_BROADCAST_INFO_VAR(coding_hist_size) \
|
||||
struct \
|
||||
{ char description [256] ; \
|
||||
char originator [32] ; \
|
||||
char originator_reference [32] ; \
|
||||
char origination_date [10] ; \
|
||||
char origination_time [8] ; \
|
||||
unsigned int time_reference_low ; \
|
||||
unsigned int time_reference_high ; \
|
||||
short version ; \
|
||||
char umid [64] ; \
|
||||
char reserved [190] ; \
|
||||
unsigned int coding_history_size ; \
|
||||
char coding_history [coding_hist_size] ; \
|
||||
}
|
||||
|
||||
/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */
|
||||
typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ;
|
||||
|
||||
|
||||
/* Virtual I/O functionality. */
|
||||
|
||||
typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_tell) (void *user_data) ;
|
||||
|
||||
struct SF_VIRTUAL_IO
|
||||
{ sf_vio_get_filelen get_filelen ;
|
||||
sf_vio_seek seek ;
|
||||
sf_vio_read read ;
|
||||
sf_vio_write write ;
|
||||
sf_vio_tell tell ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ;
|
||||
|
||||
|
||||
/* Open the specified file for read, write or both. On error, this will
|
||||
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
|
||||
** to sf_strerror ().
|
||||
** All calls to sf_open() should be matched with a call to sf_close().
|
||||
*/
|
||||
|
||||
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;
|
||||
|
||||
|
||||
/* Use the existing file descriptor to create a SNDFILE object. If close_desc
|
||||
** is TRUE, the file descriptor will be closed when sf_close() is called. If
|
||||
** it is FALSE, the descritor will not be closed.
|
||||
** When passed a descriptor like this, the library will assume that the start
|
||||
** of file header is at the current file offset. This allows sound files within
|
||||
** larger container files to be read and/or written.
|
||||
** On error, this will return a NULL pointer. To find the error number, pass a
|
||||
** NULL SNDFILE to sf_strerror ().
|
||||
** All calls to sf_open_fd() should be matched with a call to sf_close().
|
||||
|
||||
*/
|
||||
|
||||
SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
|
||||
|
||||
SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
|
||||
|
||||
|
||||
/* sf_error () returns a error number which can be translated to a text
|
||||
** string using sf_error_number().
|
||||
*/
|
||||
|
||||
int sf_error (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_strerror () returns to the caller a pointer to the current error message for
|
||||
** the given SNDFILE.
|
||||
*/
|
||||
|
||||
const char* sf_strerror (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_error_number () allows the retrieval of the error string for each internal
|
||||
** error number.
|
||||
**
|
||||
*/
|
||||
|
||||
const char* sf_error_number (int errnum) ;
|
||||
|
||||
|
||||
/* The following two error functions are deprecated but they will remain in the
|
||||
** library for the forseeable future. The function sf_strerror() should be used
|
||||
** in their place.
|
||||
*/
|
||||
|
||||
int sf_perror (SNDFILE *sndfile) ;
|
||||
int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
|
||||
|
||||
|
||||
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
|
||||
|
||||
int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ;
|
||||
|
||||
|
||||
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
|
||||
|
||||
int sf_format_check (const SF_INFO *info) ;
|
||||
|
||||
|
||||
/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
|
||||
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
|
||||
** stdio.h function fseek ().
|
||||
** An offset of zero with whence set to SEEK_SET will position the
|
||||
** read / write pointer to the first data sample.
|
||||
** On success sf_seek returns the current position in (multi-channel)
|
||||
** samples from the start of the file.
|
||||
** Please see the libsndfile documentation for moving the read pointer
|
||||
** separately from the write pointer on files open in mode SFM_RDWR.
|
||||
** On error all of these functions return -1.
|
||||
*/
|
||||
|
||||
sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ;
|
||||
|
||||
|
||||
/* Functions for retrieving and setting string data within sound files.
|
||||
** Not all file types support this features; AIFF and WAV do. For both
|
||||
** functions, the str_type parameter must be one of the SF_STR_* values
|
||||
** defined above.
|
||||
** On error, sf_set_string() returns non-zero while sf_get_string()
|
||||
** returns NULL.
|
||||
*/
|
||||
|
||||
int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
|
||||
|
||||
const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
|
||||
|
||||
|
||||
/* Return the library version string. */
|
||||
|
||||
const char * sf_version_string (void) ;
|
||||
|
||||
|
||||
/* Functions for reading/writing the waveform data of a sound file.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of frames.
|
||||
** The number of items actually read/written = frames * number of channels.
|
||||
** sf_xxxx_raw read/writes the raw data bytes from/to the file
|
||||
** sf_xxxx_short passes data in the native short format
|
||||
** sf_xxxx_int passes data in the native int format
|
||||
** sf_xxxx_float passes data in the native float format
|
||||
** sf_xxxx_double passes data in the native double format
|
||||
** All of these read/write function return number of frames read/written.
|
||||
*/
|
||||
|
||||
sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of items.
|
||||
** Otherwise similar to above.
|
||||
** All of these read/write function return number of items read/written.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ;
|
||||
|
||||
|
||||
/* Close the SNDFILE and clean up all memory allocations associated with this
|
||||
** file.
|
||||
** Returns 0 on success, or an error number.
|
||||
*/
|
||||
|
||||
int sf_close (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
|
||||
** to force the writing of data to disk. If the file is opened SFM_READ
|
||||
** no action is taken.
|
||||
*/
|
||||
|
||||
void sf_write_sync (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
|
||||
/* The function sf_wchar_open() is Windows Only!
|
||||
** Open a file passing in a Windows Unicode filename. Otherwise, this is
|
||||
** the same as sf_open().
|
||||
**
|
||||
** In order for this to work, you need to do the following:
|
||||
**
|
||||
** #include <windows.h>
|
||||
** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
|
||||
** #including <sndfile.h>
|
||||
*/
|
||||
|
||||
#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES)
|
||||
SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SNDFILE_H */
|
||||
|
||||
666
project/jni/sndfile/src/sndfile.h.in
Normal file
666
project/jni/sndfile/src/sndfile.h.in
Normal file
@@ -0,0 +1,666 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
** sndfile.h -- system-wide definitions
|
||||
**
|
||||
** API documentation is in the doc/ directory of the source code tarball
|
||||
** and at http://www.mega-nerd.com/libsndfile/api.html.
|
||||
*/
|
||||
|
||||
#ifndef SNDFILE_H
|
||||
#define SNDFILE_H
|
||||
|
||||
/* This is the version 1.0.X header file. */
|
||||
#define SNDFILE_1
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* The following file types can be read and written.
|
||||
** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise
|
||||
** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and
|
||||
** SF_FORMAT_SUBMASK can be used to separate the major and minor file
|
||||
** types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /* Major formats. */
|
||||
SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */
|
||||
SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */
|
||||
SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */
|
||||
SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */
|
||||
SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */
|
||||
SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */
|
||||
SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */
|
||||
SF_FORMAT_VOC = 0x080000, /* VOC files. */
|
||||
SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */
|
||||
SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */
|
||||
SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */
|
||||
SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */
|
||||
SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */
|
||||
SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */
|
||||
SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */
|
||||
SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */
|
||||
SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */
|
||||
SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */
|
||||
SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */
|
||||
SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */
|
||||
SF_FORMAT_CAF = 0x180000, /* Core Audio File format */
|
||||
SF_FORMAT_WVE = 0x190000, /* Psion WVE format */
|
||||
SF_FORMAT_OGG = 0x200000, /* Xiph OGG container */
|
||||
SF_FORMAT_MPC2K = 0x210000, /* Akai MPC 2000 sampler */
|
||||
SF_FORMAT_RF64 = 0x220000, /* RF64 WAV file */
|
||||
|
||||
/* Subtypes from here on. */
|
||||
|
||||
SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */
|
||||
SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */
|
||||
SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */
|
||||
SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */
|
||||
|
||||
SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */
|
||||
|
||||
SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */
|
||||
SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */
|
||||
|
||||
SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */
|
||||
SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */
|
||||
SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */
|
||||
SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */
|
||||
|
||||
SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */
|
||||
SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */
|
||||
|
||||
SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */
|
||||
SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */
|
||||
SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */
|
||||
|
||||
SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */
|
||||
SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */
|
||||
|
||||
SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */
|
||||
SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */
|
||||
|
||||
SF_FORMAT_VORBIS = 0x0060, /* Xiph Vorbis encoding. */
|
||||
|
||||
/* Endian-ness options. */
|
||||
|
||||
SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */
|
||||
SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */
|
||||
SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */
|
||||
SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */
|
||||
|
||||
SF_FORMAT_SUBMASK = 0x0000FFFF,
|
||||
SF_FORMAT_TYPEMASK = 0x0FFF0000,
|
||||
SF_FORMAT_ENDMASK = 0x30000000
|
||||
} ;
|
||||
|
||||
/*
|
||||
** The following are the valid command numbers for the sf_command()
|
||||
** interface. The use of these commands is documented in the file
|
||||
** command.html in the doc directory of the source code distribution.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFC_GET_LIB_VERSION = 0x1000,
|
||||
SFC_GET_LOG_INFO = 0x1001,
|
||||
SFC_GET_CURRENT_SF_INFO = 0x1002,
|
||||
|
||||
|
||||
SFC_GET_NORM_DOUBLE = 0x1010,
|
||||
SFC_GET_NORM_FLOAT = 0x1011,
|
||||
SFC_SET_NORM_DOUBLE = 0x1012,
|
||||
SFC_SET_NORM_FLOAT = 0x1013,
|
||||
SFC_SET_SCALE_FLOAT_INT_READ = 0x1014,
|
||||
SFC_SET_SCALE_INT_FLOAT_WRITE = 0x1015,
|
||||
|
||||
SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020,
|
||||
SFC_GET_SIMPLE_FORMAT = 0x1021,
|
||||
|
||||
SFC_GET_FORMAT_INFO = 0x1028,
|
||||
|
||||
SFC_GET_FORMAT_MAJOR_COUNT = 0x1030,
|
||||
SFC_GET_FORMAT_MAJOR = 0x1031,
|
||||
SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032,
|
||||
SFC_GET_FORMAT_SUBTYPE = 0x1033,
|
||||
|
||||
SFC_CALC_SIGNAL_MAX = 0x1040,
|
||||
SFC_CALC_NORM_SIGNAL_MAX = 0x1041,
|
||||
SFC_CALC_MAX_ALL_CHANNELS = 0x1042,
|
||||
SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043,
|
||||
SFC_GET_SIGNAL_MAX = 0x1044,
|
||||
SFC_GET_MAX_ALL_CHANNELS = 0x1045,
|
||||
|
||||
SFC_SET_ADD_PEAK_CHUNK = 0x1050,
|
||||
SFC_SET_ADD_HEADER_PAD_CHUNK = 0x1051,
|
||||
|
||||
SFC_UPDATE_HEADER_NOW = 0x1060,
|
||||
SFC_SET_UPDATE_HEADER_AUTO = 0x1061,
|
||||
|
||||
SFC_FILE_TRUNCATE = 0x1080,
|
||||
|
||||
SFC_SET_RAW_START_OFFSET = 0x1090,
|
||||
|
||||
SFC_SET_DITHER_ON_WRITE = 0x10A0,
|
||||
SFC_SET_DITHER_ON_READ = 0x10A1,
|
||||
|
||||
SFC_GET_DITHER_INFO_COUNT = 0x10A2,
|
||||
SFC_GET_DITHER_INFO = 0x10A3,
|
||||
|
||||
SFC_GET_EMBED_FILE_INFO = 0x10B0,
|
||||
|
||||
SFC_SET_CLIPPING = 0x10C0,
|
||||
SFC_GET_CLIPPING = 0x10C1,
|
||||
|
||||
SFC_GET_INSTRUMENT = 0x10D0,
|
||||
SFC_SET_INSTRUMENT = 0x10D1,
|
||||
|
||||
SFC_GET_LOOP_INFO = 0x10E0,
|
||||
|
||||
SFC_GET_BROADCAST_INFO = 0x10F0,
|
||||
SFC_SET_BROADCAST_INFO = 0x10F1,
|
||||
|
||||
SFC_GET_CHANNEL_MAP_INFO = 0x1100,
|
||||
SFC_SET_CHANNEL_MAP_INFO = 0x1101,
|
||||
|
||||
SFC_RAW_DATA_NEEDS_ENDSWAP = 0x1110,
|
||||
|
||||
/* Support for Wavex Ambisonics Format */
|
||||
SFC_WAVEX_SET_AMBISONIC = 0x1200,
|
||||
SFC_WAVEX_GET_AMBISONIC = 0x1201,
|
||||
|
||||
SFC_SET_VBR_ENCODING_QUALITY = 0x1300,
|
||||
|
||||
/* Following commands for testing only. */
|
||||
SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001,
|
||||
|
||||
/*
|
||||
** SFC_SET_ADD_* values are deprecated and will disappear at some
|
||||
** time in the future. They are guaranteed to be here up to and
|
||||
** including version 1.0.8 to avoid breakage of existng software.
|
||||
** They currently do nothing and will continue to do nothing.
|
||||
*/
|
||||
SFC_SET_ADD_DITHER_ON_WRITE = 0x1070,
|
||||
SFC_SET_ADD_DITHER_ON_READ = 0x1071
|
||||
} ;
|
||||
|
||||
|
||||
/*
|
||||
** String types that can be set and read from files. Not all file types
|
||||
** support this and even the file types which support one, may not support
|
||||
** all string types.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_STR_TITLE = 0x01,
|
||||
SF_STR_COPYRIGHT = 0x02,
|
||||
SF_STR_SOFTWARE = 0x03,
|
||||
SF_STR_ARTIST = 0x04,
|
||||
SF_STR_COMMENT = 0x05,
|
||||
SF_STR_DATE = 0x06,
|
||||
SF_STR_ALBUM = 0x07,
|
||||
SF_STR_LICENSE = 0x08,
|
||||
SF_STR_TRACKNUMBER = 0x09,
|
||||
SF_STR_GENRE = 0x10
|
||||
} ;
|
||||
|
||||
/*
|
||||
** Use the following as the start and end index when doing metadata
|
||||
** transcoding.
|
||||
*/
|
||||
|
||||
#define SF_STR_FIRST SF_STR_TITLE
|
||||
#define SF_STR_LAST SF_STR_GENRE
|
||||
|
||||
enum
|
||||
{ /* True and false */
|
||||
SF_FALSE = 0,
|
||||
SF_TRUE = 1,
|
||||
|
||||
/* Modes for opening files. */
|
||||
SFM_READ = 0x10,
|
||||
SFM_WRITE = 0x20,
|
||||
SFM_RDWR = 0x30,
|
||||
|
||||
SF_AMBISONIC_NONE = 0x40,
|
||||
SF_AMBISONIC_B_FORMAT = 0x41
|
||||
} ;
|
||||
|
||||
/* Public error values. These are guaranteed to remain unchanged for the duration
|
||||
** of the library major version number.
|
||||
** There are also a large number of private error numbers which are internal to
|
||||
** the library which can change at any time.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_ERR_NO_ERROR = 0,
|
||||
SF_ERR_UNRECOGNISED_FORMAT = 1,
|
||||
SF_ERR_SYSTEM = 2,
|
||||
SF_ERR_MALFORMED_FILE = 3,
|
||||
SF_ERR_UNSUPPORTED_ENCODING = 4
|
||||
} ;
|
||||
|
||||
|
||||
/* Channel map values (used with SFC_SET/GET_CHANNEL_MAP).
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SF_CHANNEL_MAP_INVALID = 0,
|
||||
SF_CHANNEL_MAP_MONO = 1,
|
||||
SF_CHANNEL_MAP_LEFT, /* Apple calls this 'Left' */
|
||||
SF_CHANNEL_MAP_RIGHT, /* Apple calls this 'Right' */
|
||||
SF_CHANNEL_MAP_CENTER, /* Apple calls this 'Center' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT,
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT,
|
||||
SF_CHANNEL_MAP_FRONT_CENTER,
|
||||
SF_CHANNEL_MAP_REAR_CENTER, /* Apple calls this 'Center Surround', Msft calls this 'Back Center' */
|
||||
SF_CHANNEL_MAP_REAR_LEFT, /* Apple calls this 'Left Surround', Msft calls this 'Back Left' */
|
||||
SF_CHANNEL_MAP_REAR_RIGHT, /* Apple calls this 'Right Surround', Msft calls this 'Back Right' */
|
||||
SF_CHANNEL_MAP_LFE, /* Apple calls this 'LFEScreen', Msft calls this 'Low Frequency' */
|
||||
SF_CHANNEL_MAP_FRONT_LEFT_OF_CENTER, /* Apple calls this 'Left Center' */
|
||||
SF_CHANNEL_MAP_FRONT_RIGHT_OF_CENTER, /* Apple calls this 'Right Center */
|
||||
SF_CHANNEL_MAP_SIDE_LEFT, /* Apple calls this 'Left Surround Direct' */
|
||||
SF_CHANNEL_MAP_SIDE_RIGHT, /* Apple calls this 'Right Surround Direct' */
|
||||
SF_CHANNEL_MAP_TOP_CENTER, /* Apple calls this 'Top Center Surround' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_LEFT, /* Apple calls this 'Vertical Height Left' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_RIGHT, /* Apple calls this 'Vertical Height Right' */
|
||||
SF_CHANNEL_MAP_TOP_FRONT_CENTER, /* Apple calls this 'Vertical Height Center' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_LEFT, /* Apple and MS call this 'Top Back Left' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_RIGHT, /* Apple and MS call this 'Top Back Right' */
|
||||
SF_CHANNEL_MAP_TOP_REAR_CENTER, /* Apple and MS call this 'Top Back Center' */
|
||||
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_W,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_X,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Y,
|
||||
SF_CHANNEL_MAP_AMBISONIC_B_Z,
|
||||
|
||||
SF_CHANNEL_MAP_MAX
|
||||
} ;
|
||||
|
||||
|
||||
/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */
|
||||
|
||||
typedef struct SNDFILE_tag SNDFILE ;
|
||||
|
||||
/* The following typedef is system specific and is defined when libsndfile is
|
||||
** compiled. sf_count_t will be a 64 bit value when the underlying OS allows
|
||||
** 64 bit file offsets.
|
||||
** On windows, we need to allow the same header file to be compiler by both GCC
|
||||
** and the Microsoft compiler.
|
||||
*/
|
||||
|
||||
#if (defined (_MSCVER) || defined (_MSC_VER))
|
||||
typedef __int64 sf_count_t ;
|
||||
#define SF_COUNT_MAX 0x7fffffffffffffffi64
|
||||
#else
|
||||
typedef @TYPEOF_SF_COUNT_T@ sf_count_t ;
|
||||
#define SF_COUNT_MAX @SF_COUNT_MAX@
|
||||
#endif
|
||||
|
||||
|
||||
/* A pointer to a SF_INFO structure is passed to sf_open () and filled in.
|
||||
** On write, the SF_INFO structure is filled in by the user and passed into
|
||||
** sf_open ().
|
||||
*/
|
||||
|
||||
struct SF_INFO
|
||||
{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */
|
||||
int samplerate ;
|
||||
int channels ;
|
||||
int format ;
|
||||
int sections ;
|
||||
int seekable ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_INFO SF_INFO ;
|
||||
|
||||
/* The SF_FORMAT_INFO struct is used to retrieve information about the sound
|
||||
** file formats libsndfile supports using the sf_command () interface.
|
||||
**
|
||||
** Using this interface will allow applications to support new file formats
|
||||
** and encoding types when libsndfile is upgraded, without requiring
|
||||
** re-compilation of the application.
|
||||
**
|
||||
** Please consult the libsndfile documentation (particularly the information
|
||||
** on the sf_command () interface) for examples of its use.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ int format ;
|
||||
const char *name ;
|
||||
const char *extension ;
|
||||
} SF_FORMAT_INFO ;
|
||||
|
||||
/*
|
||||
** Enums and typedefs for adding dither on read and write.
|
||||
** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE
|
||||
** and SFC_SET_DITHER_ON_READ.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ SFD_DEFAULT_LEVEL = 0,
|
||||
SFD_CUSTOM_LEVEL = 0x40000000,
|
||||
|
||||
SFD_NO_DITHER = 500,
|
||||
SFD_WHITE = 501,
|
||||
SFD_TRIANGULAR_PDF = 502
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ int type ;
|
||||
double level ;
|
||||
const char *name ;
|
||||
} SF_DITHER_INFO ;
|
||||
|
||||
/* Struct used to retrieve information about a file embedded within a
|
||||
** larger file. See SFC_GET_EMBED_FILE_INFO.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ sf_count_t offset ;
|
||||
sf_count_t length ;
|
||||
} SF_EMBED_FILE_INFO ;
|
||||
|
||||
/*
|
||||
** Structs used to retrieve music sample information from a file.
|
||||
*/
|
||||
|
||||
enum
|
||||
{ /*
|
||||
** The loop mode field in SF_INSTRUMENT will be one of the following.
|
||||
*/
|
||||
SF_LOOP_NONE = 800,
|
||||
SF_LOOP_FORWARD,
|
||||
SF_LOOP_BACKWARD,
|
||||
SF_LOOP_ALTERNATING
|
||||
} ;
|
||||
|
||||
typedef struct
|
||||
{ int gain ;
|
||||
char basenote, detune ;
|
||||
char velocity_lo, velocity_hi ;
|
||||
char key_lo, key_hi ;
|
||||
int loop_count ;
|
||||
|
||||
struct
|
||||
{ int mode ;
|
||||
unsigned int start ;
|
||||
unsigned int end ;
|
||||
unsigned int count ;
|
||||
} loops [16] ; /* make variable in a sensible way */
|
||||
} SF_INSTRUMENT ;
|
||||
|
||||
|
||||
|
||||
/* Struct used to retrieve loop information from a file.*/
|
||||
typedef struct
|
||||
{
|
||||
short time_sig_num ; /* any positive integer > 0 */
|
||||
short time_sig_den ; /* any positive power of 2 > 0 */
|
||||
int loop_mode ; /* see SF_LOOP enum */
|
||||
|
||||
int num_beats ; /* this is NOT the amount of quarter notes !!!*/
|
||||
/* a full bar of 4/4 is 4 beats */
|
||||
/* a full bar of 7/8 is 7 beats */
|
||||
|
||||
float bpm ; /* suggestion, as it can be calculated using other fields:*/
|
||||
/* file's lenght, file's sampleRate and our time_sig_den*/
|
||||
/* -> bpms are always the amount of _quarter notes_ per minute */
|
||||
|
||||
int root_key ; /* MIDI note, or -1 for None */
|
||||
int future [6] ;
|
||||
} SF_LOOP_INFO ;
|
||||
|
||||
|
||||
/* Struct used to retrieve broadcast (EBU) information from a file.
|
||||
** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE.
|
||||
*/
|
||||
#define SF_BROADCAST_INFO_VAR(coding_hist_size) \
|
||||
struct \
|
||||
{ char description [256] ; \
|
||||
char originator [32] ; \
|
||||
char originator_reference [32] ; \
|
||||
char origination_date [10] ; \
|
||||
char origination_time [8] ; \
|
||||
unsigned int time_reference_low ; \
|
||||
unsigned int time_reference_high ; \
|
||||
short version ; \
|
||||
char umid [64] ; \
|
||||
char reserved [190] ; \
|
||||
unsigned int coding_history_size ; \
|
||||
char coding_history [coding_hist_size] ; \
|
||||
}
|
||||
|
||||
/* SF_BROADCAST_INFO is the above struct with coding_history field of 256 bytes. */
|
||||
typedef SF_BROADCAST_INFO_VAR (256) SF_BROADCAST_INFO ;
|
||||
|
||||
|
||||
/* Virtual I/O functionality. */
|
||||
|
||||
typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ;
|
||||
typedef sf_count_t (*sf_vio_tell) (void *user_data) ;
|
||||
|
||||
struct SF_VIRTUAL_IO
|
||||
{ sf_vio_get_filelen get_filelen ;
|
||||
sf_vio_seek seek ;
|
||||
sf_vio_read read ;
|
||||
sf_vio_write write ;
|
||||
sf_vio_tell tell ;
|
||||
} ;
|
||||
|
||||
typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ;
|
||||
|
||||
|
||||
/* Open the specified file for read, write or both. On error, this will
|
||||
** return a NULL pointer. To find the error number, pass a NULL SNDFILE
|
||||
** to sf_strerror ().
|
||||
** All calls to sf_open() should be matched with a call to sf_close().
|
||||
*/
|
||||
|
||||
SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ;
|
||||
|
||||
|
||||
/* Use the existing file descriptor to create a SNDFILE object. If close_desc
|
||||
** is TRUE, the file descriptor will be closed when sf_close() is called. If
|
||||
** it is FALSE, the descritor will not be closed.
|
||||
** When passed a descriptor like this, the library will assume that the start
|
||||
** of file header is at the current file offset. This allows sound files within
|
||||
** larger container files to be read and/or written.
|
||||
** On error, this will return a NULL pointer. To find the error number, pass a
|
||||
** NULL SNDFILE to sf_strerror ().
|
||||
** All calls to sf_open_fd() should be matched with a call to sf_close().
|
||||
|
||||
*/
|
||||
|
||||
SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ;
|
||||
|
||||
SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ;
|
||||
|
||||
|
||||
/* sf_error () returns a error number which can be translated to a text
|
||||
** string using sf_error_number().
|
||||
*/
|
||||
|
||||
int sf_error (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_strerror () returns to the caller a pointer to the current error message for
|
||||
** the given SNDFILE.
|
||||
*/
|
||||
|
||||
const char* sf_strerror (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* sf_error_number () allows the retrieval of the error string for each internal
|
||||
** error number.
|
||||
**
|
||||
*/
|
||||
|
||||
const char* sf_error_number (int errnum) ;
|
||||
|
||||
|
||||
/* The following two error functions are deprecated but they will remain in the
|
||||
** library for the forseeable future. The function sf_strerror() should be used
|
||||
** in their place.
|
||||
*/
|
||||
|
||||
int sf_perror (SNDFILE *sndfile) ;
|
||||
int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ;
|
||||
|
||||
|
||||
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
|
||||
|
||||
int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ;
|
||||
|
||||
|
||||
/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */
|
||||
|
||||
int sf_format_check (const SF_INFO *info) ;
|
||||
|
||||
|
||||
/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses
|
||||
** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as
|
||||
** stdio.h function fseek ().
|
||||
** An offset of zero with whence set to SEEK_SET will position the
|
||||
** read / write pointer to the first data sample.
|
||||
** On success sf_seek returns the current position in (multi-channel)
|
||||
** samples from the start of the file.
|
||||
** Please see the libsndfile documentation for moving the read pointer
|
||||
** separately from the write pointer on files open in mode SFM_RDWR.
|
||||
** On error all of these functions return -1.
|
||||
*/
|
||||
|
||||
sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ;
|
||||
|
||||
|
||||
/* Functions for retrieving and setting string data within sound files.
|
||||
** Not all file types support this features; AIFF and WAV do. For both
|
||||
** functions, the str_type parameter must be one of the SF_STR_* values
|
||||
** defined above.
|
||||
** On error, sf_set_string() returns non-zero while sf_get_string()
|
||||
** returns NULL.
|
||||
*/
|
||||
|
||||
int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ;
|
||||
|
||||
const char* sf_get_string (SNDFILE *sndfile, int str_type) ;
|
||||
|
||||
|
||||
/* Return the library version string. */
|
||||
|
||||
const char * sf_version_string (void) ;
|
||||
|
||||
|
||||
/* Functions for reading/writing the waveform data of a sound file.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of frames.
|
||||
** The number of items actually read/written = frames * number of channels.
|
||||
** sf_xxxx_raw read/writes the raw data bytes from/to the file
|
||||
** sf_xxxx_short passes data in the native short format
|
||||
** sf_xxxx_int passes data in the native int format
|
||||
** sf_xxxx_float passes data in the native float format
|
||||
** sf_xxxx_double passes data in the native double format
|
||||
** All of these read/write function return number of frames read/written.
|
||||
*/
|
||||
|
||||
sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ;
|
||||
sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ;
|
||||
|
||||
|
||||
/* Functions for reading and writing the data chunk in terms of items.
|
||||
** Otherwise similar to above.
|
||||
** All of these read/write function return number of items read/written.
|
||||
*/
|
||||
|
||||
sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ;
|
||||
sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ;
|
||||
|
||||
|
||||
/* Close the SNDFILE and clean up all memory allocations associated with this
|
||||
** file.
|
||||
** Returns 0 on success, or an error number.
|
||||
*/
|
||||
|
||||
int sf_close (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file
|
||||
** to force the writing of data to disk. If the file is opened SFM_READ
|
||||
** no action is taken.
|
||||
*/
|
||||
|
||||
void sf_write_sync (SNDFILE *sndfile) ;
|
||||
|
||||
|
||||
|
||||
/* The function sf_wchar_open() is Windows Only!
|
||||
** Open a file passing in a Windows Unicode filename. Otherwise, this is
|
||||
** the same as sf_open().
|
||||
**
|
||||
** In order for this to work, you need to do the following:
|
||||
**
|
||||
** #include <windows.h>
|
||||
** #define ENABLE_SNDFILE_WINDOWS_PROTOTYPES 1
|
||||
** #including <sndfile.h>
|
||||
*/
|
||||
|
||||
#if (defined (ENABLE_SNDFILE_WINDOWS_PROTOTYPES) && ENABLE_SNDFILE_WINDOWS_PROTOTYPES)
|
||||
SNDFILE* sf_wchar_open (LPCWSTR wpath, int mode, SF_INFO *sfinfo) ;
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
} /* extern "C" */
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SNDFILE_H */
|
||||
|
||||
422
project/jni/sndfile/src/sndfile.hh
Normal file
422
project/jni/sndfile/src/sndfile.hh
Normal file
@@ -0,0 +1,422 @@
|
||||
/*
|
||||
** Copyright (C) 2005-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** All rights reserved.
|
||||
**
|
||||
** Redistribution and use in source and binary forms, with or without
|
||||
** modification, are permitted provided that the following conditions are
|
||||
** met:
|
||||
**
|
||||
** * Redistributions of source code must retain the above copyright
|
||||
** notice, this list of conditions and the following disclaimer.
|
||||
** * Redistributions in binary form must reproduce the above copyright
|
||||
** notice, this list of conditions and the following disclaimer in
|
||||
** the documentation and/or other materials provided with the
|
||||
** distribution.
|
||||
** * Neither the author nor the names of any contributors may be used
|
||||
** to endorse or promote products derived from this software without
|
||||
** specific prior written permission.
|
||||
**
|
||||
** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
** TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
** PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
** CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
** EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
** PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
|
||||
** OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
||||
** WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
|
||||
** OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||
** ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
** The above modified BSD style license (GPL and LGPL compatible) applies to
|
||||
** this file. It does not apply to libsndfile itself which is released under
|
||||
** the GNU LGPL or the libsndfile test suite which is released under the GNU
|
||||
** GPL.
|
||||
** This means that this header file can be used under this modified BSD style
|
||||
** license, but the LGPL still holds for the libsndfile library itself.
|
||||
*/
|
||||
|
||||
/*
|
||||
** sndfile.hh -- A lightweight C++ wrapper for the libsndfile API.
|
||||
**
|
||||
** All the methods are inlines and all functionality is contained in this
|
||||
** file. There is no separate implementation file.
|
||||
**
|
||||
** API documentation is in the doc/ directory of the source code tarball
|
||||
** and at http://www.mega-nerd.com/libsndfile/api.html.
|
||||
*/
|
||||
|
||||
#ifndef SNDFILE_HH
|
||||
#define SNDFILE_HH
|
||||
|
||||
#include <sndfile.h>
|
||||
|
||||
#include <string>
|
||||
#include <new> // for std::nothrow
|
||||
|
||||
class SndfileHandle
|
||||
{ private :
|
||||
struct SNDFILE_ref
|
||||
{ SNDFILE_ref (void) ;
|
||||
~SNDFILE_ref (void) ;
|
||||
|
||||
SNDFILE *sf ;
|
||||
SF_INFO sfinfo ;
|
||||
int ref ;
|
||||
} ;
|
||||
|
||||
SNDFILE_ref *p ;
|
||||
|
||||
public :
|
||||
/* Default constructor */
|
||||
SndfileHandle (void) : p (NULL) {} ;
|
||||
SndfileHandle (const char *path, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (std::string const & path, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
SndfileHandle (int fd, bool close_desc, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
SndfileHandle (LPCWSTR wpath, int mode = SFM_READ,
|
||||
int format = 0, int channels = 0, int samplerate = 0) ;
|
||||
#endif
|
||||
|
||||
~SndfileHandle (void) ;
|
||||
|
||||
SndfileHandle (const SndfileHandle &orig) ;
|
||||
SndfileHandle & operator = (const SndfileHandle &rhs) ;
|
||||
|
||||
/* Mainly for debugging/testing. */
|
||||
int refCount (void) const { return (p == NULL) ? 0 : p->ref ; }
|
||||
|
||||
operator bool () const { return (p != NULL) ; }
|
||||
|
||||
bool operator == (const SndfileHandle &rhs) const { return (p == rhs.p) ; }
|
||||
|
||||
sf_count_t frames (void) const { return p ? p->sfinfo.frames : 0 ; }
|
||||
int format (void) const { return p ? p->sfinfo.format : 0 ; }
|
||||
int channels (void) const { return p ? p->sfinfo.channels : 0 ; }
|
||||
int samplerate (void) const { return p ? p->sfinfo.samplerate : 0 ; }
|
||||
|
||||
int error (void) const ;
|
||||
const char * strError (void) const ;
|
||||
|
||||
int command (int cmd, void *data, int datasize) ;
|
||||
|
||||
sf_count_t seek (sf_count_t frames, int whence) ;
|
||||
|
||||
void writeSync (void) ;
|
||||
|
||||
int setString (int str_type, const char* str) ;
|
||||
|
||||
const char* getString (int str_type) const ;
|
||||
|
||||
static int formatCheck (int format, int channels, int samplerate) ;
|
||||
|
||||
sf_count_t read (short *ptr, sf_count_t items) ;
|
||||
sf_count_t read (int *ptr, sf_count_t items) ;
|
||||
sf_count_t read (float *ptr, sf_count_t items) ;
|
||||
sf_count_t read (double *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t write (const short *ptr, sf_count_t items) ;
|
||||
sf_count_t write (const int *ptr, sf_count_t items) ;
|
||||
sf_count_t write (const float *ptr, sf_count_t items) ;
|
||||
sf_count_t write (const double *ptr, sf_count_t items) ;
|
||||
|
||||
sf_count_t readf (short *ptr, sf_count_t frames) ;
|
||||
sf_count_t readf (int *ptr, sf_count_t frames) ;
|
||||
sf_count_t readf (float *ptr, sf_count_t frames) ;
|
||||
sf_count_t readf (double *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t writef (const short *ptr, sf_count_t frames) ;
|
||||
sf_count_t writef (const int *ptr, sf_count_t frames) ;
|
||||
sf_count_t writef (const float *ptr, sf_count_t frames) ;
|
||||
sf_count_t writef (const double *ptr, sf_count_t frames) ;
|
||||
|
||||
sf_count_t readRaw (void *ptr, sf_count_t bytes) ;
|
||||
sf_count_t writeRaw (const void *ptr, sf_count_t bytes) ;
|
||||
|
||||
/**< Raw access to the handle. SndfileHandle keeps ownership. */
|
||||
SNDFILE * rawHandle (void) ;
|
||||
|
||||
/**< Take ownership of handle, iff reference count is 1. */
|
||||
SNDFILE * takeOwnership (void) ;
|
||||
} ;
|
||||
|
||||
/*==============================================================================
|
||||
** Nothing but implementation below.
|
||||
*/
|
||||
|
||||
inline
|
||||
SndfileHandle::SNDFILE_ref::SNDFILE_ref (void)
|
||||
: ref (1)
|
||||
{}
|
||||
|
||||
inline
|
||||
SndfileHandle::SNDFILE_ref::~SNDFILE_ref (void)
|
||||
{ if (sf != NULL) sf_close (sf) ; }
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (const char *path, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open (path, mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle const char * constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (std::string const & path, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open (path.c_str (), mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle std::string constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (int fd, bool close_desc, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
if (fd < 0)
|
||||
return ;
|
||||
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_open_fd (fd, mode, &p->sfinfo, close_desc) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle fd constructor */
|
||||
|
||||
inline
|
||||
SndfileHandle::~SndfileHandle (void)
|
||||
{ if (p != NULL && --p->ref == 0)
|
||||
delete p ;
|
||||
} /* SndfileHandle destructor */
|
||||
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (const SndfileHandle &orig)
|
||||
: p (orig.p)
|
||||
{ if (p != NULL)
|
||||
++p->ref ;
|
||||
} /* SndfileHandle copy constructor */
|
||||
|
||||
inline SndfileHandle &
|
||||
SndfileHandle::operator = (const SndfileHandle &rhs)
|
||||
{
|
||||
if (&rhs == this)
|
||||
return *this ;
|
||||
if (p != NULL && --p->ref == 0)
|
||||
delete p ;
|
||||
|
||||
p = rhs.p ;
|
||||
if (p != NULL)
|
||||
++p->ref ;
|
||||
|
||||
return *this ;
|
||||
} /* SndfileHandle assignment operator */
|
||||
|
||||
inline int
|
||||
SndfileHandle::error (void) const
|
||||
{ return sf_error (p->sf) ; }
|
||||
|
||||
inline const char *
|
||||
SndfileHandle::strError (void) const
|
||||
{ return sf_strerror (p->sf) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::command (int cmd, void *data, int datasize)
|
||||
{ return sf_command (p->sf, cmd, data, datasize) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::seek (sf_count_t frame_count, int whence)
|
||||
{ return sf_seek (p->sf, frame_count, whence) ; }
|
||||
|
||||
inline void
|
||||
SndfileHandle::writeSync (void)
|
||||
{ sf_write_sync (p->sf) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::setString (int str_type, const char* str)
|
||||
{ return sf_set_string (p->sf, str_type, str) ; }
|
||||
|
||||
inline const char*
|
||||
SndfileHandle::getString (int str_type) const
|
||||
{ return sf_get_string (p->sf, str_type) ; }
|
||||
|
||||
inline int
|
||||
SndfileHandle::formatCheck (int fmt, int chans, int srate)
|
||||
{
|
||||
SF_INFO sfinfo ;
|
||||
|
||||
sfinfo.frames = 0 ;
|
||||
sfinfo.channels = chans ;
|
||||
sfinfo.format = fmt ;
|
||||
sfinfo.samplerate = srate ;
|
||||
sfinfo.sections = 0 ;
|
||||
sfinfo.seekable = 0 ;
|
||||
|
||||
return sf_format_check (&sfinfo) ;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------*/
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (short *ptr, sf_count_t items)
|
||||
{ return sf_read_short (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (int *ptr, sf_count_t items)
|
||||
{ return sf_read_int (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (float *ptr, sf_count_t items)
|
||||
{ return sf_read_float (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::read (double *ptr, sf_count_t items)
|
||||
{ return sf_read_double (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const short *ptr, sf_count_t items)
|
||||
{ return sf_write_short (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const int *ptr, sf_count_t items)
|
||||
{ return sf_write_int (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const float *ptr, sf_count_t items)
|
||||
{ return sf_write_float (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::write (const double *ptr, sf_count_t items)
|
||||
{ return sf_write_double (p->sf, ptr, items) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (short *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_short (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (int *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_int (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (float *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_float (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readf (double *ptr, sf_count_t frame_count)
|
||||
{ return sf_readf_double (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const short *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_short (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const int *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_int (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const float *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_float (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writef (const double *ptr, sf_count_t frame_count)
|
||||
{ return sf_writef_double (p->sf, ptr, frame_count) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::readRaw (void *ptr, sf_count_t bytes)
|
||||
{ return sf_read_raw (p->sf, ptr, bytes) ; }
|
||||
|
||||
inline sf_count_t
|
||||
SndfileHandle::writeRaw (const void *ptr, sf_count_t bytes)
|
||||
{ return sf_write_raw (p->sf, ptr, bytes) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::rawHandle (void)
|
||||
{ return (p ? p->sf : NULL) ; }
|
||||
|
||||
inline SNDFILE *
|
||||
SndfileHandle::takeOwnership (void)
|
||||
{
|
||||
if (p == NULL || (p->ref != 1))
|
||||
return NULL ;
|
||||
|
||||
SNDFILE * sf = p->sf ;
|
||||
p->sf = NULL ;
|
||||
delete p ;
|
||||
p = NULL ;
|
||||
return sf ;
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SNDFILE_WINDOWS_PROTOTYPES
|
||||
|
||||
inline
|
||||
SndfileHandle::SndfileHandle (LPCWSTR wpath, int mode, int fmt, int chans, int srate)
|
||||
: p (NULL)
|
||||
{
|
||||
p = new (std::nothrow) SNDFILE_ref () ;
|
||||
|
||||
if (p != NULL)
|
||||
{ p->ref = 1 ;
|
||||
|
||||
p->sfinfo.frames = 0 ;
|
||||
p->sfinfo.channels = chans ;
|
||||
p->sfinfo.format = fmt ;
|
||||
p->sfinfo.samplerate = srate ;
|
||||
p->sfinfo.sections = 0 ;
|
||||
p->sfinfo.seekable = 0 ;
|
||||
|
||||
p->sf = sf_wchar_open (wpath, mode, &p->sfinfo) ;
|
||||
} ;
|
||||
|
||||
return ;
|
||||
} /* SndfileHandle const wchar_t * constructor */
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* SNDFILE_HH */
|
||||
|
||||
214
project/jni/sndfile/src/strings.c
Normal file
214
project/jni/sndfile/src/strings.c
Normal file
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
** Copyright (C) 2001-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "common.h"
|
||||
|
||||
#define STRINGS_DEBUG 0
|
||||
#if STRINGS_DEBUG
|
||||
static void hexdump (void *data, int len) ;
|
||||
#endif
|
||||
|
||||
int
|
||||
psf_store_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
{ char new_str [128] ;
|
||||
size_t len_remaining, str_len ;
|
||||
int k, str_flags ;
|
||||
|
||||
if (str == NULL)
|
||||
return SFE_STR_BAD_STRING ;
|
||||
|
||||
str_len = strlen (str) ;
|
||||
|
||||
/* A few extra checks for write mode. */
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if ((psf->str_flags & SF_STR_ALLOW_START) == 0)
|
||||
return SFE_STR_NO_SUPPORT ;
|
||||
if (psf->have_written && (psf->str_flags & SF_STR_ALLOW_END) == 0)
|
||||
return SFE_STR_NO_SUPPORT ;
|
||||
/* Only allow zero length strings for software. */
|
||||
if (str_type != SF_STR_SOFTWARE && str_len == 0)
|
||||
return SFE_STR_BAD_STRING ;
|
||||
} ;
|
||||
|
||||
/* Find the next free slot in table. */
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
{ /* If we find a matching entry clear it. */
|
||||
if (psf->strings [k].type == str_type)
|
||||
psf->strings [k].type = -1 ;
|
||||
|
||||
if (psf->strings [k].type == 0)
|
||||
break ;
|
||||
} ;
|
||||
|
||||
/* Determine flags */
|
||||
str_flags = SF_STR_LOCATE_START ;
|
||||
if (psf->file.mode == SFM_RDWR || psf->have_written)
|
||||
{ if ((psf->str_flags & SF_STR_ALLOW_END) == 0)
|
||||
return SFE_STR_NO_ADD_END ;
|
||||
str_flags = SF_STR_LOCATE_END ;
|
||||
} ;
|
||||
|
||||
/* More sanity checking. */
|
||||
if (k >= SF_MAX_STRINGS)
|
||||
return SFE_STR_MAX_COUNT ;
|
||||
|
||||
if (k == 0 && psf->str_end != NULL)
|
||||
{ psf_log_printf (psf, "SFE_STR_WEIRD : k == 0 && psf->str_end != NULL\n") ;
|
||||
return SFE_STR_WEIRD ;
|
||||
} ;
|
||||
|
||||
if (k != 0 && psf->str_end == NULL)
|
||||
{ psf_log_printf (psf, "SFE_STR_WEIRD : k != 0 && psf->str_end == NULL\n") ;
|
||||
return SFE_STR_WEIRD ;
|
||||
} ;
|
||||
|
||||
/* Special case for the first string. */
|
||||
if (k == 0)
|
||||
psf->str_end = psf->str_storage ;
|
||||
|
||||
switch (str_type)
|
||||
{ case SF_STR_SOFTWARE :
|
||||
/* In write mode, want to append libsndfile-version to string. */
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (strstr (str, PACKAGE) == NULL)
|
||||
{ /*
|
||||
** If the supplied string does not already contain a
|
||||
** libsndfile-X.Y.Z component, then add it.
|
||||
*/
|
||||
if (strlen (str) == 0)
|
||||
snprintf (new_str, sizeof (new_str), "%s-%s", PACKAGE, VERSION) ;
|
||||
else
|
||||
snprintf (new_str, sizeof (new_str), "%s (%s-%s)", str, PACKAGE, VERSION) ;
|
||||
}
|
||||
else
|
||||
snprintf (new_str, sizeof (new_str), "%s", str) ;
|
||||
|
||||
str = new_str ;
|
||||
} ;
|
||||
break ;
|
||||
|
||||
case SF_STR_TITLE :
|
||||
case SF_STR_COPYRIGHT :
|
||||
case SF_STR_ARTIST :
|
||||
case SF_STR_COMMENT :
|
||||
case SF_STR_DATE :
|
||||
case SF_STR_ALBUM :
|
||||
case SF_STR_LICENSE :
|
||||
case SF_STR_TRACKNUMBER :
|
||||
case SF_STR_GENRE :
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, "%s : SFE_STR_BAD_TYPE\n", __func__) ;
|
||||
return SFE_STR_BAD_TYPE ;
|
||||
} ;
|
||||
|
||||
str_len = strlen (str) ;
|
||||
|
||||
len_remaining = SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage) ;
|
||||
|
||||
if (len_remaining < str_len + 2)
|
||||
return SFE_STR_MAX_DATA ;
|
||||
|
||||
psf->strings [k].type = str_type ;
|
||||
psf->strings [k].str = psf->str_end ;
|
||||
psf->strings [k].flags = str_flags ;
|
||||
|
||||
memcpy (psf->str_end, str, str_len + 1) ;
|
||||
/* Plus one to catch string terminator. */
|
||||
psf->str_end += str_len + 1 ;
|
||||
|
||||
psf->str_flags |= str_flags ;
|
||||
|
||||
#if STRINGS_DEBUG
|
||||
psf_log_printf (psf, "str_storage : %X\n", (int) psf->str_storage) ;
|
||||
psf_log_printf (psf, "str_end : %X\n", (int) psf->str_end) ;
|
||||
psf_log_printf (psf, "sizeof (str_storage) : %d\n", SIGNED_SIZEOF (psf->str_storage)) ;
|
||||
psf_log_printf (psf, "used : %d\n", (int ) (psf->str_end - psf->str_storage)) ;
|
||||
psf_log_printf (psf, "remaining : %d\n", SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage)) ;
|
||||
|
||||
hexdump (psf->str_storage, 300) ;
|
||||
#endif
|
||||
|
||||
return 0 ;
|
||||
} /* psf_store_string */
|
||||
|
||||
int
|
||||
psf_set_string (SF_PRIVATE *psf, int str_type, const char *str)
|
||||
{ if (psf->file.mode == SFM_READ)
|
||||
return SFE_STR_NOT_WRITE ;
|
||||
|
||||
return psf_store_string (psf, str_type, str) ;
|
||||
} /* psf_set_string */
|
||||
|
||||
const char*
|
||||
psf_get_string (SF_PRIVATE *psf, int str_type)
|
||||
{ int k ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
if (str_type == psf->strings [k].type)
|
||||
return psf->strings [k].str ;
|
||||
|
||||
return NULL ;
|
||||
} /* psf_get_string */
|
||||
|
||||
int
|
||||
psf_location_string_count (const SF_PRIVATE * psf, int location)
|
||||
{ int k, count = 0 ;
|
||||
|
||||
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
|
||||
if (psf->strings [k].type > 0 && psf->strings [k].flags & location)
|
||||
count ++ ;
|
||||
|
||||
return count ;
|
||||
} /* psf_location_string_count */
|
||||
|
||||
/*==============================================================================
|
||||
*/
|
||||
|
||||
#if STRINGS_DEBUG
|
||||
|
||||
#include <ctype.h>
|
||||
static void
|
||||
hexdump (void *data, int len)
|
||||
{ unsigned char *ptr ;
|
||||
int k ;
|
||||
|
||||
ptr = data ;
|
||||
|
||||
puts ("---------------------------------------------------------") ;
|
||||
while (len >= 16)
|
||||
{ for (k = 0 ; k < 16 ; k++)
|
||||
printf ("%02X ", ptr [k] & 0xFF) ;
|
||||
printf (" ") ;
|
||||
for (k = 0 ; k < 16 ; k++)
|
||||
printf ("%c", psf_isprint (ptr [k]) ? ptr [k] : '.') ;
|
||||
puts ("") ;
|
||||
ptr += 16 ;
|
||||
len -= 16 ;
|
||||
} ;
|
||||
} /* hexdump */
|
||||
|
||||
#endif
|
||||
416
project/jni/sndfile/src/svx.c
Normal file
416
project/jni/sndfile/src/svx.c
Normal file
@@ -0,0 +1,416 @@
|
||||
/*
|
||||
** Copyright (C) 1999-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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 "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Macros to handle big/little endian issues.
|
||||
*/
|
||||
|
||||
#define FORM_MARKER (MAKE_MARKER ('F', 'O', 'R', 'M'))
|
||||
#define SVX8_MARKER (MAKE_MARKER ('8', 'S', 'V', 'X'))
|
||||
#define SV16_MARKER (MAKE_MARKER ('1', '6', 'S', 'V'))
|
||||
#define VHDR_MARKER (MAKE_MARKER ('V', 'H', 'D', 'R'))
|
||||
#define BODY_MARKER (MAKE_MARKER ('B', 'O', 'D', 'Y'))
|
||||
|
||||
#define ATAK_MARKER (MAKE_MARKER ('A', 'T', 'A', 'K'))
|
||||
#define RLSE_MARKER (MAKE_MARKER ('R', 'L', 'S', 'E'))
|
||||
|
||||
#define c_MARKER (MAKE_MARKER ('(', 'c', ')', ' '))
|
||||
#define NAME_MARKER (MAKE_MARKER ('N', 'A', 'M', 'E'))
|
||||
#define AUTH_MARKER (MAKE_MARKER ('A', 'U', 'T', 'H'))
|
||||
#define ANNO_MARKER (MAKE_MARKER ('A', 'N', 'N', 'O'))
|
||||
#define CHAN_MARKER (MAKE_MARKER ('C', 'H', 'A', 'N'))
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Typedefs for file chunks.
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ unsigned int oneShotHiSamples, repeatHiSamples, samplesPerHiCycle ;
|
||||
unsigned short samplesPerSec ;
|
||||
unsigned char octave, compression ;
|
||||
unsigned int volume ;
|
||||
} VHDR_CHUNK ;
|
||||
|
||||
enum {
|
||||
HAVE_FORM = 0x01,
|
||||
|
||||
HAVE_SVX = 0x02,
|
||||
HAVE_VHDR = 0x04,
|
||||
HAVE_BODY = 0x08
|
||||
} ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
* Private static functions.
|
||||
*/
|
||||
|
||||
static int svx_close (SF_PRIVATE *psf) ;
|
||||
static int svx_write_header (SF_PRIVATE *psf, int calc_length) ;
|
||||
static int svx_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public function.
|
||||
*/
|
||||
|
||||
int
|
||||
svx_open (SF_PRIVATE *psf)
|
||||
{ int error ;
|
||||
|
||||
if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0))
|
||||
{ if ((error = svx_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */
|
||||
|
||||
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
|
||||
if (psf->blockwidth)
|
||||
psf->sf.frames = psf->datalength / psf->blockwidth ;
|
||||
|
||||
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
|
||||
} ;
|
||||
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
{ if (psf->is_pipe)
|
||||
return SFE_NO_PIPE_WRITE ;
|
||||
|
||||
if ((SF_CONTAINER (psf->sf.format)) != SF_FORMAT_SVX)
|
||||
return SFE_BAD_OPEN_FORMAT ;
|
||||
|
||||
psf->endian = SF_ENDIAN (psf->sf.format) ;
|
||||
|
||||
if (psf->endian == SF_ENDIAN_LITTLE || (CPU_IS_LITTLE_ENDIAN && psf->endian == SF_ENDIAN_CPU))
|
||||
return SFE_BAD_ENDIAN ;
|
||||
|
||||
psf->endian = SF_ENDIAN_BIG ; /* All SVX files are big endian. */
|
||||
|
||||
error = svx_write_header (psf, SF_FALSE) ;
|
||||
if (error)
|
||||
return error ;
|
||||
|
||||
psf->write_header = svx_write_header ;
|
||||
} ;
|
||||
|
||||
psf->container_close = svx_close ;
|
||||
|
||||
if ((error = pcm_init (psf)))
|
||||
return error ;
|
||||
|
||||
return 0 ;
|
||||
} /* svx_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
svx_read_header (SF_PRIVATE *psf)
|
||||
{ VHDR_CHUNK vhdr ;
|
||||
unsigned int FORMsize, vhdrsize, dword, marker ;
|
||||
int filetype = 0, parsestage = 0, done = 0 ;
|
||||
int bytecount = 0, channels ;
|
||||
|
||||
if (psf->filelength > SF_PLATFORM_S64 (0xffffffff))
|
||||
psf_log_printf (psf, "Warning : filelength > 0xffffffff. This is bad!!!!\n") ;
|
||||
|
||||
memset (&vhdr, 0, sizeof (vhdr)) ;
|
||||
psf_binheader_readf (psf, "p", 0) ;
|
||||
|
||||
/* Set default number of channels. Modify later if necessary */
|
||||
psf->sf.channels = 1 ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_SVX ;
|
||||
|
||||
while (! done)
|
||||
{ psf_binheader_readf (psf, "m", &marker) ;
|
||||
switch (marker)
|
||||
{ case FORM_MARKER :
|
||||
if (parsestage)
|
||||
return SFE_SVX_NO_FORM ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &FORMsize) ;
|
||||
|
||||
if (FORMsize != psf->filelength - 2 * sizeof (dword))
|
||||
{ dword = psf->filelength - 2 * sizeof (dword) ;
|
||||
psf_log_printf (psf, "FORM : %d (should be %d)\n", FORMsize, dword) ;
|
||||
FORMsize = dword ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, "FORM : %d\n", FORMsize) ;
|
||||
parsestage |= HAVE_FORM ;
|
||||
break ;
|
||||
|
||||
case SVX8_MARKER :
|
||||
case SV16_MARKER :
|
||||
if (! (parsestage & HAVE_FORM))
|
||||
return SFE_SVX_NO_FORM ;
|
||||
filetype = marker ;
|
||||
psf_log_printf (psf, " %M\n", marker) ;
|
||||
parsestage |= HAVE_SVX ;
|
||||
break ;
|
||||
|
||||
case VHDR_MARKER :
|
||||
if (! (parsestage & (HAVE_FORM | HAVE_SVX)))
|
||||
return SFE_SVX_NO_FORM ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &vhdrsize) ;
|
||||
|
||||
psf_log_printf (psf, " VHDR : %d\n", vhdrsize) ;
|
||||
|
||||
psf_binheader_readf (psf, "E4442114", &(vhdr.oneShotHiSamples), &(vhdr.repeatHiSamples),
|
||||
&(vhdr.samplesPerHiCycle), &(vhdr.samplesPerSec), &(vhdr.octave), &(vhdr.compression),
|
||||
&(vhdr.volume)) ;
|
||||
|
||||
psf_log_printf (psf, " OneShotHiSamples : %d\n", vhdr.oneShotHiSamples) ;
|
||||
psf_log_printf (psf, " RepeatHiSamples : %d\n", vhdr.repeatHiSamples) ;
|
||||
psf_log_printf (psf, " samplesPerHiCycle : %d\n", vhdr.samplesPerHiCycle) ;
|
||||
psf_log_printf (psf, " Sample Rate : %d\n", vhdr.samplesPerSec) ;
|
||||
psf_log_printf (psf, " Octave : %d\n", vhdr.octave) ;
|
||||
|
||||
psf_log_printf (psf, " Compression : %d => ", vhdr.compression) ;
|
||||
|
||||
switch (vhdr.compression)
|
||||
{ case 0 : psf_log_printf (psf, "None.\n") ;
|
||||
break ;
|
||||
case 1 : psf_log_printf (psf, "Fibonacci delta\n") ;
|
||||
break ;
|
||||
case 2 : psf_log_printf (psf, "Exponential delta\n") ;
|
||||
break ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " Volume : %d\n", vhdr.volume) ;
|
||||
|
||||
psf->sf.samplerate = vhdr.samplesPerSec ;
|
||||
|
||||
if (filetype == SVX8_MARKER)
|
||||
{ psf->sf.format |= SF_FORMAT_PCM_S8 ;
|
||||
psf->bytewidth = 1 ;
|
||||
}
|
||||
else if (filetype == SV16_MARKER)
|
||||
{ psf->sf.format |= SF_FORMAT_PCM_16 ;
|
||||
psf->bytewidth = 2 ;
|
||||
} ;
|
||||
|
||||
parsestage |= HAVE_VHDR ;
|
||||
break ;
|
||||
|
||||
case BODY_MARKER :
|
||||
if (! (parsestage & HAVE_VHDR))
|
||||
return SFE_SVX_NO_BODY ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &dword) ;
|
||||
psf->datalength = dword ;
|
||||
|
||||
psf->dataoffset = psf_ftell (psf) ;
|
||||
if (psf->dataoffset < 0)
|
||||
return SFE_SVX_NO_BODY ;
|
||||
|
||||
if (psf->datalength > psf->filelength - psf->dataoffset)
|
||||
{ psf_log_printf (psf, " BODY : %D (should be %D)\n", psf->datalength, psf->filelength - psf->dataoffset) ;
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " BODY : %D\n", psf->datalength) ;
|
||||
|
||||
parsestage |= HAVE_BODY ;
|
||||
|
||||
if (! psf->sf.seekable)
|
||||
break ;
|
||||
|
||||
psf_fseek (psf, psf->datalength, SEEK_CUR) ;
|
||||
break ;
|
||||
|
||||
case NAME_MARKER :
|
||||
if (! (parsestage & HAVE_SVX))
|
||||
return SFE_SVX_NO_FORM ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &dword) ;
|
||||
|
||||
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
|
||||
|
||||
if (strlen (psf->file.name.c) != dword)
|
||||
{ if (dword > sizeof (psf->file.name.c) - 1)
|
||||
return SFE_SVX_BAD_NAME_LENGTH ;
|
||||
|
||||
psf_binheader_readf (psf, "b", psf->file.name.c, dword) ;
|
||||
psf->file.name.c [dword] = 0 ;
|
||||
}
|
||||
else
|
||||
psf_binheader_readf (psf, "j", dword) ;
|
||||
break ;
|
||||
|
||||
case ANNO_MARKER :
|
||||
if (! (parsestage & HAVE_SVX))
|
||||
return SFE_SVX_NO_FORM ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &dword) ;
|
||||
|
||||
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", dword) ;
|
||||
break ;
|
||||
|
||||
case CHAN_MARKER :
|
||||
if (! (parsestage & HAVE_SVX))
|
||||
return SFE_SVX_NO_FORM ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &dword) ;
|
||||
|
||||
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
|
||||
|
||||
bytecount += psf_binheader_readf (psf, "E4", &channels) ;
|
||||
|
||||
if (channels == 2 || channels == 4)
|
||||
psf_log_printf (psf, " Channels : %d => mono\n", channels) ;
|
||||
else if (channels == 6)
|
||||
{ psf->sf.channels = 2 ;
|
||||
psf_log_printf (psf, " Channels : %d => stereo\n", channels) ;
|
||||
}
|
||||
else
|
||||
psf_log_printf (psf, " Channels : %d *** assuming mono\n", channels) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", dword - bytecount) ;
|
||||
break ;
|
||||
|
||||
|
||||
case AUTH_MARKER :
|
||||
case c_MARKER :
|
||||
if (! (parsestage & HAVE_SVX))
|
||||
return SFE_SVX_NO_FORM ;
|
||||
|
||||
psf_binheader_readf (psf, "E4", &dword) ;
|
||||
|
||||
psf_log_printf (psf, " %M : %d\n", marker, dword) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", dword) ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
if (psf_isprint ((marker >> 24) & 0xFF) && psf_isprint ((marker >> 16) & 0xFF)
|
||||
&& psf_isprint ((marker >> 8) & 0xFF) && psf_isprint (marker & 0xFF))
|
||||
{ psf_binheader_readf (psf, "E4", &dword) ;
|
||||
|
||||
psf_log_printf (psf, "%M : %d (unknown marker)\n", marker, dword) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", dword) ;
|
||||
break ;
|
||||
} ;
|
||||
if ((dword = psf_ftell (psf)) & 0x03)
|
||||
{ psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ;
|
||||
|
||||
psf_binheader_readf (psf, "j", -3) ;
|
||||
break ;
|
||||
} ;
|
||||
psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ;
|
||||
done = 1 ;
|
||||
} ; /* switch (marker) */
|
||||
|
||||
if (! psf->sf.seekable && (parsestage & HAVE_BODY))
|
||||
break ;
|
||||
|
||||
if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (dword))
|
||||
break ;
|
||||
} ; /* while (1) */
|
||||
|
||||
if (vhdr.compression)
|
||||
return SFE_SVX_BAD_COMP ;
|
||||
|
||||
if (psf->dataoffset <= 0)
|
||||
return SFE_SVX_NO_DATA ;
|
||||
|
||||
return 0 ;
|
||||
} /* svx_read_header */
|
||||
|
||||
static int
|
||||
svx_close (SF_PRIVATE *psf)
|
||||
{
|
||||
if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR)
|
||||
svx_write_header (psf, SF_TRUE) ;
|
||||
|
||||
return 0 ;
|
||||
} /* svx_close */
|
||||
|
||||
static int
|
||||
svx_write_header (SF_PRIVATE *psf, int calc_length)
|
||||
{ static char annotation [] = "libsndfile by Erik de Castro Lopo\0\0\0" ;
|
||||
sf_count_t current ;
|
||||
|
||||
current = psf_ftell (psf) ;
|
||||
|
||||
if (calc_length)
|
||||
{ psf->filelength = psf_get_filelen (psf) ;
|
||||
|
||||
psf->datalength = psf->filelength - psf->dataoffset ;
|
||||
|
||||
if (psf->dataend)
|
||||
psf->datalength -= psf->filelength - psf->dataend ;
|
||||
|
||||
psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
|
||||
} ;
|
||||
|
||||
psf->header [0] = 0 ;
|
||||
psf->headindex = 0 ;
|
||||
psf_fseek (psf, 0, SEEK_SET) ;
|
||||
|
||||
/* FORM marker and FORM size. */
|
||||
psf_binheader_writef (psf, "Etm8", FORM_MARKER, (psf->filelength < 8) ?
|
||||
psf->filelength * 0 : psf->filelength - 8) ;
|
||||
|
||||
psf_binheader_writef (psf, "m", (psf->bytewidth == 1) ? SVX8_MARKER : SV16_MARKER) ;
|
||||
|
||||
/* VHDR chunk. */
|
||||
psf_binheader_writef (psf, "Em4", VHDR_MARKER, sizeof (VHDR_CHUNK)) ;
|
||||
/* VHDR : oneShotHiSamples, repeatHiSamples, samplesPerHiCycle */
|
||||
psf_binheader_writef (psf, "E444", psf->sf.frames, 0, 0) ;
|
||||
/* VHDR : samplesPerSec, octave, compression */
|
||||
psf_binheader_writef (psf, "E211", psf->sf.samplerate, 1, 0) ;
|
||||
/* VHDR : volume */
|
||||
psf_binheader_writef (psf, "E4", (psf->bytewidth == 1) ? 0xFF : 0xFFFF) ;
|
||||
|
||||
if (psf->sf.channels == 2)
|
||||
psf_binheader_writef (psf, "Em44", CHAN_MARKER, 4, 6) ;
|
||||
|
||||
/* Filename and annotation strings. */
|
||||
psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->file.name.c, ANNO_MARKER, annotation) ;
|
||||
|
||||
/* BODY marker and size. */
|
||||
psf_binheader_writef (psf, "Etm8", BODY_MARKER, (psf->datalength < 0) ?
|
||||
psf->datalength * 0 : psf->datalength) ;
|
||||
|
||||
psf_fwrite (psf->header, psf->headindex, 1, psf) ;
|
||||
|
||||
if (psf->error)
|
||||
return psf->error ;
|
||||
|
||||
psf->dataoffset = psf->headindex ;
|
||||
|
||||
if (current > 0)
|
||||
psf_fseek (psf, current, SEEK_SET) ;
|
||||
|
||||
return psf->error ;
|
||||
} /* svx_write_header */
|
||||
|
||||
372
project/jni/sndfile/src/txw.c
Normal file
372
project/jni/sndfile/src/txw.c
Normal file
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
** Copyright (C) 2002-2011 Erik de Castro Lopo <erikd@mega-nerd.com>
|
||||
**
|
||||
** This program is free software; you can redistribute it and/or modify
|
||||
** it under the terms of the GNU Lesser General Public License as published by
|
||||
** the Free Software Foundation; either version 2.1 of the License, or
|
||||
** (at your option) any later version.
|
||||
**
|
||||
** This 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 Lesser General Public License for more details.
|
||||
**
|
||||
** You should have received a copy of the GNU Lesser 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.
|
||||
*/
|
||||
|
||||
/*===========================================================================
|
||||
** Yamaha TX16 Sampler Files.
|
||||
**
|
||||
** This header parser was written using information from the SoX source code
|
||||
** and trial and error experimentation. The code here however is all original.
|
||||
*/
|
||||
|
||||
#include "sfconfig.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include "sndfile.h"
|
||||
#include "sfendian.h"
|
||||
#include "common.h"
|
||||
|
||||
#if (ENABLE_EXPERIMENTAL_CODE == 0)
|
||||
|
||||
int
|
||||
txw_open (SF_PRIVATE *psf)
|
||||
{ if (psf)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
return 0 ;
|
||||
} /* txw_open */
|
||||
|
||||
#else
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Markers.
|
||||
*/
|
||||
|
||||
#define TXW_DATA_OFFSET 32
|
||||
|
||||
#define TXW_LOOPED 0x49
|
||||
#define TXW_NO_LOOP 0xC9
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Private static functions.
|
||||
*/
|
||||
|
||||
static int txw_read_header (SF_PRIVATE *psf) ;
|
||||
|
||||
static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
|
||||
static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
|
||||
static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
|
||||
static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
|
||||
|
||||
static sf_count_t txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
** Public functions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha
|
||||
* ftp://ftp.t0.or.at/pub/sound/tx16w/faq/tx16w.tec
|
||||
* http://www.t0.or.at/~mpakesch/tx16w/
|
||||
*
|
||||
* from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith)
|
||||
* char filetype[6] "LM8953"
|
||||
* nulls[10],
|
||||
* dummy_aeg[6]
|
||||
* format 0x49 = looped, 0xC9 = non-looped
|
||||
* sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz
|
||||
* atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16,
|
||||
* depending on [5] but to heck with it
|
||||
* rpt_length[3] (these are for looped samples, attack and loop lengths)
|
||||
* unused[2]
|
||||
*/
|
||||
|
||||
typedef struct
|
||||
{ unsigned char format, srate, sr2, sr3 ;
|
||||
unsigned short srhash ;
|
||||
unsigned int attacklen, repeatlen ;
|
||||
} TXW_HEADER ;
|
||||
|
||||
#define ERROR_666 666
|
||||
|
||||
int
|
||||
txw_open (SF_PRIVATE *psf)
|
||||
{ int error ;
|
||||
|
||||
if (psf->file.mode != SFM_READ)
|
||||
return SFE_UNIMPLEMENTED ;
|
||||
|
||||
if ((error = txw_read_header (psf)))
|
||||
return error ;
|
||||
|
||||
if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset)
|
||||
return SFE_BAD_SEEK ;
|
||||
|
||||
psf->read_short = txw_read_s ;
|
||||
psf->read_int = txw_read_i ;
|
||||
psf->read_float = txw_read_f ;
|
||||
psf->read_double = txw_read_d ;
|
||||
|
||||
psf->seek = txw_seek ;
|
||||
|
||||
return 0 ;
|
||||
} /* txw_open */
|
||||
|
||||
/*------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
static int
|
||||
txw_read_header (SF_PRIVATE *psf)
|
||||
{ TXW_HEADER txwh ;
|
||||
const char *strptr ;
|
||||
|
||||
memset (&txwh, 0, sizeof (txwh)) ;
|
||||
memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
|
||||
psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 16) ;
|
||||
|
||||
if (memcmp (psf->u.cbuf, "LM8953\0\0\0\0\0\0\0\0\0\0", 16) != 0)
|
||||
return ERROR_666 ;
|
||||
|
||||
psf_log_printf (psf, "Read only : Yamaha TX-16 Sampler (.txw)\nLM8953\n") ;
|
||||
|
||||
/* Jump 6 bytes (dummp_aeg), read format, read sample rate. */
|
||||
psf_binheader_readf (psf, "j11", 6, &txwh.format, &txwh.srate) ;
|
||||
|
||||
/* 8 bytes (atc_length[3], rpt_length[3], unused[2]). */
|
||||
psf_binheader_readf (psf, "e33j", &txwh.attacklen, &txwh.repeatlen, 2) ;
|
||||
txwh.sr2 = (txwh.attacklen >> 16) & 0xFE ;
|
||||
txwh.sr3 = (txwh.repeatlen >> 16) & 0xFE ;
|
||||
txwh.attacklen &= 0x1FFFF ;
|
||||
txwh.repeatlen &= 0x1FFFF ;
|
||||
|
||||
switch (txwh.format)
|
||||
{ case TXW_LOOPED :
|
||||
strptr = "looped" ;
|
||||
break ;
|
||||
|
||||
case TXW_NO_LOOP :
|
||||
strptr = "non-looped" ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
psf_log_printf (psf, " Format : 0x%02x => ?????\n", txwh.format) ;
|
||||
return ERROR_666 ;
|
||||
} ;
|
||||
|
||||
psf_log_printf (psf, " Format : 0x%02X => %s\n", txwh.format, strptr) ;
|
||||
|
||||
strptr = NULL ;
|
||||
|
||||
switch (txwh.srate)
|
||||
{ case 1 :
|
||||
psf->sf.samplerate = 33333 ;
|
||||
break ;
|
||||
|
||||
case 2 :
|
||||
psf->sf.samplerate = 50000 ;
|
||||
break ;
|
||||
|
||||
case 3 :
|
||||
psf->sf.samplerate = 16667 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
/* This is ugly and braindead. */
|
||||
txwh.srhash = ((txwh.sr2 & 0xFE) << 8) | (txwh.sr3 & 0xFE) ;
|
||||
switch (txwh.srhash)
|
||||
{ case ((0x6 << 8) | 0x52) :
|
||||
psf->sf.samplerate = 33333 ;
|
||||
break ;
|
||||
|
||||
case ((0x10 << 8) | 0x52) :
|
||||
psf->sf.samplerate = 50000 ;
|
||||
break ;
|
||||
|
||||
case ((0xF6 << 8) | 0x52) :
|
||||
psf->sf.samplerate = 166667 ;
|
||||
break ;
|
||||
|
||||
default :
|
||||
strptr = " Sample Rate : Unknown : forcing to 33333\n" ;
|
||||
psf->sf.samplerate = 33333 ;
|
||||
break ;
|
||||
} ;
|
||||
} ;
|
||||
|
||||
|
||||
if (strptr)
|
||||
psf_log_printf (psf, strptr) ;
|
||||
else if (txwh.srhash)
|
||||
psf_log_printf (psf, " Sample Rate : %d (0x%X) => %d\n", txwh.srate, txwh.srhash, psf->sf.samplerate) ;
|
||||
else
|
||||
psf_log_printf (psf, " Sample Rate : %d => %d\n", txwh.srate, psf->sf.samplerate) ;
|
||||
|
||||
if (txwh.format == TXW_LOOPED)
|
||||
{ psf_log_printf (psf, " Attack Len : %d\n", txwh.attacklen) ;
|
||||
psf_log_printf (psf, " Repeat Len : %d\n", txwh.repeatlen) ;
|
||||
} ;
|
||||
|
||||
psf->dataoffset = TXW_DATA_OFFSET ;
|
||||
psf->datalength = psf->filelength - TXW_DATA_OFFSET ;
|
||||
psf->sf.frames = 2 * psf->datalength / 3 ;
|
||||
|
||||
|
||||
if (psf->datalength % 3 == 1)
|
||||
psf_log_printf (psf, "*** File seems to be truncated, %d extra bytes.\n",
|
||||
(int) (psf->datalength % 3)) ;
|
||||
|
||||
if (txwh.attacklen + txwh.repeatlen > psf->sf.frames)
|
||||
psf_log_printf (psf, "*** File has been truncated.\n") ;
|
||||
|
||||
psf->sf.format = SF_FORMAT_TXW | SF_FORMAT_PCM_16 ;
|
||||
psf->sf.channels = 1 ;
|
||||
psf->sf.sections = 1 ;
|
||||
psf->sf.seekable = SF_TRUE ;
|
||||
|
||||
return 0 ;
|
||||
} /* txw_read_header */
|
||||
|
||||
static sf_count_t
|
||||
txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
|
||||
{ unsigned char *ucptr ;
|
||||
short sample ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = sizeof (psf->u.cbuf) / 3 ;
|
||||
bufferlen -= (bufferlen & 1) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
|
||||
|
||||
ucptr = psf->u.ucbuf ;
|
||||
for (k = 0 ; k < readcount ; k += 2)
|
||||
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
|
||||
ptr [total + k] = sample ;
|
||||
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
|
||||
ptr [total + k + 1] = sample ;
|
||||
ucptr += 3 ;
|
||||
} ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* txw_read_s */
|
||||
|
||||
static sf_count_t
|
||||
txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
|
||||
{ unsigned char *ucptr ;
|
||||
short sample ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
|
||||
bufferlen = sizeof (psf->u.cbuf) / 3 ;
|
||||
bufferlen -= (bufferlen & 1) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
|
||||
|
||||
ucptr = psf->u.ucbuf ;
|
||||
for (k = 0 ; k < readcount ; k += 2)
|
||||
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
|
||||
ptr [total + k] = sample << 16 ;
|
||||
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
|
||||
ptr [total + k + 1] = sample << 16 ;
|
||||
ucptr += 3 ;
|
||||
} ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* txw_read_i */
|
||||
|
||||
static sf_count_t
|
||||
txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
|
||||
{ unsigned char *ucptr ;
|
||||
short sample ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
float normfact ;
|
||||
|
||||
if (psf->norm_float == SF_TRUE)
|
||||
normfact = 1.0 / 0x8000 ;
|
||||
else
|
||||
normfact = 1.0 / 0x10 ;
|
||||
|
||||
bufferlen = sizeof (psf->u.cbuf) / 3 ;
|
||||
bufferlen -= (bufferlen & 1) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
|
||||
|
||||
ucptr = psf->u.ucbuf ;
|
||||
for (k = 0 ; k < readcount ; k += 2)
|
||||
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
|
||||
ptr [total + k] = normfact * sample ;
|
||||
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
|
||||
ptr [total + k + 1] = normfact * sample ;
|
||||
ucptr += 3 ;
|
||||
} ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* txw_read_f */
|
||||
|
||||
static sf_count_t
|
||||
txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
|
||||
{ unsigned char *ucptr ;
|
||||
short sample ;
|
||||
int k, bufferlen, readcount, count ;
|
||||
sf_count_t total = 0 ;
|
||||
double normfact ;
|
||||
|
||||
if (psf->norm_double == SF_TRUE)
|
||||
normfact = 1.0 / 0x8000 ;
|
||||
else
|
||||
normfact = 1.0 / 0x10 ;
|
||||
|
||||
bufferlen = sizeof (psf->u.cbuf) / 3 ;
|
||||
bufferlen -= (bufferlen & 1) ;
|
||||
while (len > 0)
|
||||
{ readcount = (len >= bufferlen) ? bufferlen : len ;
|
||||
count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
|
||||
|
||||
ucptr = psf->u.ucbuf ;
|
||||
for (k = 0 ; k < readcount ; k += 2)
|
||||
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
|
||||
ptr [total + k] = normfact * sample ;
|
||||
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
|
||||
ptr [total + k + 1] = normfact * sample ;
|
||||
ucptr += 3 ;
|
||||
} ;
|
||||
|
||||
total += count ;
|
||||
len -= readcount ;
|
||||
} ;
|
||||
|
||||
return total ;
|
||||
} /* txw_read_d */
|
||||
|
||||
static sf_count_t
|
||||
txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
|
||||
{ if (psf && mode)
|
||||
return offset ;
|
||||
|
||||
return 0 ;
|
||||
} /* txw_seek */
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user