Universal Binary

This commit is contained in:
vspader 2006-04-17 13:09:06 +00:00
parent 5379d9bab7
commit 29afdd5941
106 changed files with 47971 additions and 0 deletions

Binary file not shown.

View file

@ -0,0 +1,14 @@
The main author of libsndfile is Erik de Castro Lopo <erikd@mega-nerd.com>.
The code in the src/GSM610 directory was 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
Code in the src/G72x directory was 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.

View 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!

File diff suppressed because it is too large Load diff

View 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.

View file

@ -0,0 +1,98 @@
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.

View file

@ -0,0 +1,74 @@
This is libsndfile, 1.0.11
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. 'wav32_aiff24' converts a WAV file containing 32 bit floating
point data into a 24 bit PCM AIFF file. 'sndfile2oct' dumps the audio
data of a file in a human readable format. 'sfconvert' is the beginnings
of a audio file format conversion utility. 'make_sine' generates a WAV
file containing one cycle of a sine wave with 4096 sample points in
32 bit floating point format. 'sfinfo' opens a sound file and prints
out information about that file.
The tests/ directory contains programs which link against libsndfile
and test its functionality.
The Win32/ directory contains files and documentation to allow libsndfile
to compile under Win32 with the Microsoft Visual C++ compiler.
The MacOS/ directory contains files and documentation to allow libsndfile
to compile under MacOS with the Metrowerks compiler.
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.
Win32
-----
There are detailed instructions for building libsndfile on Win32 in the file
doc/win32.html
MacOSX
------
Building on MacOSX should be the same as building it on any other Unix.
OTHER PLATFORMS
---------------
To compile libsndfile on platforms which have a Bourne Shell compatible
shell, an ANSI C compiler and a make utility should require no more that
the following three commands :
./configure
make
make install
For platforms without the required shell, it is usually sufficient to
create an approriate config.h file in the src/ directory with correct
values for the following #defines (this would work for AmigaOS) :
#define HAVE_ENDIAN_H 0
#define GUESS_BIG_ENDIAN 1
#define GUESS_LITTLE_ENDIAN 0
#define FORCE_BROKEN_FLOAT 0
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/

View file

@ -0,0 +1,42 @@
Here's a list of what I (erikd AT mega-nerd DOT com) think needs to be
done. The list is by no means exhaustive and people are encouraged to
email me with suggestions.
o Add pipe in/out capabilities. libsndfile should be able to read
its input from a pipe and write its output to a pipe.
o Add checks of the error state after fseek???? Use ferror ().
o Modify tests/lossy_comp_test.c to add tests for stereo files.
o Testing compilation and correctness on more platforms.
o Improve testing routines. Must test all combinations of inputs
and outputs.
o Test sf_seek function on write???
o Add more sound file formats. People should contact me with their
requirements.
o Add support for accessing sound formats with multiple audio
data sections (ie samples within tracker files, Soundfont II and
multi-sample sampler formats).
o Add an interface to allow reading and writing of sample loop points
and other info within AIFF and other file formats. This must be a
general solution.
o Improve documentation. Is HTML documentation good enough?
o Look into the possibility of optional sample rate convert on file
read.
As I am the person who knows libsndfile best, I can probably implement
any new features faster than anybody else (and you can spend your time
writing applications with libsndfile). All I need is some
documentation and some sample files. Please contact me before emailing
me documentation and sample files. I would much rather pull them off
the web than have them clogging up my email inbox.

View 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.

View file

@ -0,0 +1,28 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = README README.original ChangeLog
noinst_HEADERS = g72x.h g72x_priv.h
noinst_LTLIBRARIES = libg72x.la
noinst_PROGRAMS = g72x_test
CFILES = g72x.c g721.c g723_16.c g723_24.c g723_40.c
libg72x_la_SOURCES = $(CFILES) $(noinst_HEADERS)
g72x_test_SOURCES = g72x_test.c
g72x_test_LDADD = ./libg72x.la -lm
check: g72x_test
./g72x_test all
# Disable autoheader.
AUTOHEADER=echo
## Do not edit or modify anything in this comment block.
## The arch-tag line is a file identity tag for the GNU Arch
## revision control system.
##
## arch-tag: d417a8e8-da7f-423d-884d-f03c93379348

View file

@ -0,0 +1,478 @@
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
ACLOCAL = @ACLOCAL@
ALSA_LIBS = @ALSA_LIBS@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
# Disable autoheader.
AUTOHEADER = echo
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
COMPILER_IS_GCC = @COMPILER_IS_GCC@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_EXPERIMENTAL_CODE = @ENABLE_EXPERIMENTAL_CODE@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
GCC_MAJOR_VERSION = @GCC_MAJOR_VERSION@
GETCONF = @GETCONF@
HTML_BGCOLOUR = @HTML_BGCOLOUR@
HTML_FGCOLOUR = @HTML_FGCOLOUR@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
OS_SPECIFIC_CFLAGS = @OS_SPECIFIC_CFLAGS@
OS_SPECIFIC_LINKS = @OS_SPECIFIC_LINKS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SF_COUNT_MAX = @SF_COUNT_MAX@
SHARED_VERSION_INFO = @SHARED_VERSION_INFO@
SHELL = @SHELL@
SHLIB_VERSION_ARG = @SHLIB_VERSION_ARG@
SIZEOF_SF_COUNT_T = @SIZEOF_SF_COUNT_T@
STRIP = @STRIP@
TYPEOF_SF_COUNT_T = @TYPEOF_SF_COUNT_T@
VERSION = @VERSION@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_GETCONF = @ac_ct_GETCONF@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
autogen = @autogen@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldocdir = @htmldocdir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
EXTRA_DIST = README README.original ChangeLog
noinst_HEADERS = g72x.h g72x_priv.h
noinst_LTLIBRARIES = libg72x.la
noinst_PROGRAMS = g72x_test
CFILES = g72x.c g721.c g723_16.c g723_24.c g723_40.c
libg72x_la_SOURCES = $(CFILES) $(noinst_HEADERS)
g72x_test_SOURCES = g72x_test.c
g72x_test_LDADD = ./libg72x.la -lm
subdir = src/G72x
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/src/config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libg72x_la_LDFLAGS =
libg72x_la_LIBADD =
am__objects_1 = g72x.lo g721.lo g723_16.lo g723_24.lo g723_40.lo
am__objects_2 =
am_libg72x_la_OBJECTS = $(am__objects_1) $(am__objects_2)
libg72x_la_OBJECTS = $(am_libg72x_la_OBJECTS)
noinst_PROGRAMS = g72x_test$(EXEEXT)
PROGRAMS = $(noinst_PROGRAMS)
am_g72x_test_OBJECTS = g72x_test.$(OBJEXT)
g72x_test_OBJECTS = $(am_g72x_test_OBJECTS)
g72x_test_DEPENDENCIES = ./libg72x.la
g72x_test_LDFLAGS =
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/g721.Plo ./$(DEPDIR)/g723_16.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/g723_24.Plo ./$(DEPDIR)/g723_40.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/g72x.Plo ./$(DEPDIR)/g72x_test.Po
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
$(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libg72x_la_SOURCES) $(g72x_test_SOURCES)
HEADERS = $(noinst_HEADERS)
DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.in ChangeLog \
Makefile.am
SOURCES = $(libg72x_la_SOURCES) $(g72x_test_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu src/G72x/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" = "$$p" && dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libg72x.la: $(libg72x_la_OBJECTS) $(libg72x_la_DEPENDENCIES)
$(LINK) $(libg72x_la_LDFLAGS) $(libg72x_la_OBJECTS) $(libg72x_la_LIBADD) $(LIBS)
clean-noinstPROGRAMS:
@list='$(noinst_PROGRAMS)'; for p in $$list; do \
f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
echo " rm -f $$p $$f"; \
rm -f $$p $$f ; \
done
g72x_test$(EXEEXT): $(g72x_test_OBJECTS) $(g72x_test_DEPENDENCIES)
@rm -f g72x_test$(EXEEXT)
$(LINK) $(g72x_test_LDFLAGS) $(g72x_test_OBJECTS) $(g72x_test_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g721.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g723_16.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g723_24.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g723_40.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g72x.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/g72x_test.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
.c.lo:
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ../..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
clean-noinstPROGRAMS mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES clean-noinstPROGRAMS \
ctags distclean distclean-compile distclean-generic \
distclean-libtool distclean-tags distdir dvi dvi-am info \
info-am install install-am install-data install-data-am \
install-exec install-exec-am install-info install-info-am \
install-man install-strip installcheck installcheck-am \
installdirs maintainer-clean maintainer-clean-generic \
mostlyclean mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool pdf pdf-am ps ps-am tags uninstall \
uninstall-am uninstall-info-am
check: g72x_test
./g72x_test all
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View file

View 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

View 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
*/
/*
* 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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 101b6e25-457d-490a-99ae-e2e74a26ea24
*/

View file

@ -0,0 +1,169 @@
/*
* 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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: ae265466-c3fc-4f83-bb32-edae488a5ca5
*/

View file

@ -0,0 +1,146 @@
/*
* 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 */
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 75389236-650b-4427-98f3-0df6e8fb24bc
*/

View file

@ -0,0 +1,160 @@
/*
* 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 */
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: eb8d9a00-32bf-4dd2-b287-01b0336d72bf
*/

View file

@ -0,0 +1,636 @@
/*
* 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
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 & 0x37) + 0x30) >> 4 ;
** but could see no valid reason for the + 0x30.
** Removed it and it improved the SNR of the codec.
*/
wanmant = (anmant * (srn & 0x37)) >> 4 ;
retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
(wanmant >> -wanexp);
return (((an ^ srn) < 0) ? -retval : retval);
}
/*
* 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 */
int g72x_reader_init (G72x_DATA *data, int codec)
{ G72x_STATE *pstate ;
if (sizeof (data->private) < sizeof (G72x_STATE))
{ /* This is for safety only. */
return 1 ;
} ;
memset (data, 0, sizeof (G72x_DATA)) ;
pstate = (G72x_STATE*) data->private ;
private_init_state (pstate) ;
pstate->encoder = NULL ;
switch (codec)
{ case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */
pstate->decoder = g723_16_decoder ;
data->blocksize = G723_16_BYTES_PER_BLOCK ;
data->samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 2 ;
break ;
case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */
pstate->decoder = g723_24_decoder ;
data->blocksize = G723_24_BYTES_PER_BLOCK ;
data->samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 3 ;
break ;
case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */
pstate->decoder = g721_decoder ;
data->blocksize = G721_32_BYTES_PER_BLOCK ;
data->samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 4 ;
break ;
case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */
pstate->decoder = g723_40_decoder ;
data->blocksize = G721_40_BYTES_PER_BLOCK ;
data->samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 5 ;
break ;
default : return 1 ;
} ;
return 0 ;
} /* g72x_reader_init */
int g72x_writer_init (G72x_DATA *data, int codec)
{ G72x_STATE *pstate ;
if (sizeof (data->private) < sizeof (G72x_STATE))
{ /* This is for safety only. Gets optimised out. */
return 1 ;
} ;
memset (data, 0, sizeof (G72x_DATA)) ;
pstate = (G72x_STATE*) data->private ;
private_init_state (pstate) ;
pstate->decoder = NULL ;
switch (codec)
{ case G723_16_BITS_PER_SAMPLE : /* 2 bits per sample. */
pstate->encoder = g723_16_encoder ;
data->blocksize = G723_16_BYTES_PER_BLOCK ;
data->samplesperblock = G723_16_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 2 ;
break ;
case G723_24_BITS_PER_SAMPLE : /* 3 bits per sample. */
pstate->encoder = g723_24_encoder ;
data->blocksize = G723_24_BYTES_PER_BLOCK ;
data->samplesperblock = G723_24_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 3 ;
break ;
case G721_32_BITS_PER_SAMPLE : /* 4 bits per sample. */
pstate->encoder = g721_encoder ;
data->blocksize = G721_32_BYTES_PER_BLOCK ;
data->samplesperblock = G721_32_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 4 ;
break ;
case G721_40_BITS_PER_SAMPLE : /* 5 bits per sample. */
pstate->encoder = g723_40_encoder ;
data->blocksize = G721_40_BYTES_PER_BLOCK ;
data->samplesperblock = G721_40_SAMPLES_PER_BLOCK ;
pstate->codec_bits = 5 ;
break ;
default : return 1 ;
} ;
return 0 ;
} /* g72x_writer_init */
int unpack_bytes (G72x_DATA *data, int bits)
{ unsigned int in_buffer = 0 ;
unsigned char in_byte ;
int k, in_bits = 0, bindex = 0 ;
for (k = 0 ; bindex <= data->blocksize && k < G72x_BLOCK_SIZE ; k++)
{ if (in_bits < bits)
{ in_byte = data->block [bindex++] ;
in_buffer |= (in_byte << in_bits);
in_bits += 8;
}
data->samples [k] = in_buffer & ((1 << bits) - 1);
in_buffer >>= bits;
in_bits -= bits;
} ;
return k ;
} /* unpack_bytes */
int g72x_decode_block (G72x_DATA *data)
{ G72x_STATE *pstate ;
int k, count ;
pstate = (G72x_STATE*) data->private ;
count = unpack_bytes (data, pstate->codec_bits) ;
for (k = 0 ; k < count ; k++)
data->samples [k] = pstate->decoder (data->samples [k], pstate) ;
return 0 ;
} /* g72x_decode_block */
int pack_bytes (G72x_DATA *data, int bits)
{
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 |= (data->samples [k] << out_bits) ;
out_bits += bits ;
if (out_bits >= 8)
{ out_byte = out_buffer & 0xFF ;
out_bits -= 8 ;
out_buffer >>= 8 ;
data->block [bindex++] = out_byte ;
}
} ;
return bindex ;
} /* pack_bytes */
int g72x_encode_block (G72x_DATA *data)
{ G72x_STATE *pstate ;
int k, count ;
pstate = (G72x_STATE*) data->private ;
for (k = 0 ; k < data->samplesperblock ; k++)
data->samples [k] = pstate->encoder (data->samples [k], pstate) ;
count = pack_bytes (data, pstate->codec_bits) ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 6298dc75-fd0f-4062-9b90-f73ed69f22d4
*/

View file

@ -0,0 +1,117 @@
/*
** Copyright (C) 1999-2001 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 private.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
} ;
/*
** This is the public structure for passing data between the caller and
** the G72x encoder and decoder.
** The private array is used by the encoder and decoder for internal
** state information and should not be changed in any way by the caller.
** When decoding or encoding a stream, the same instance of this struct
** should be used for every call so that the decoder/encoder keeps the
** correct state data between calls.
*/
typedef struct
{ /* Private data. Don't mess with it. */
unsigned long private [256 / sizeof (long)] ;
/* Public data. Read only. */
int blocksize, max_bytes, samplesperblock, bytesperblock ;
/* Public data. Read and write. */
int blocks, blockcount, samplecount ;
unsigned char block [G72x_BLOCK_SIZE] ;
short samples [G72x_BLOCK_SIZE] ;
} G72x_DATA ;
/* External function definitions. */
int g72x_reader_init (G72x_DATA *data, int codec) ;
int g72x_writer_init (G72x_DATA *data, int codec) ;
/*
** Initialize the ADPCM state table for the given codec.
** Return 0 on success, 1 on fail.
*/
int g72x_decode_block (G72x_DATA *data) ;
/*
** 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 (G72x_DATA *data) ;
/*
** 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 6ca84e5f-f932-4ba1-87ee-37056d921621
*/

View file

@ -0,0 +1,119 @@
/*
* 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
/*
** 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.
*/
typedef struct private_g72x
{ 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 private_g72x* state) ;
int (*decoder) (int, struct private_g72x* state) ;
int codec_bits ;
int byte_index, sample_index ;
} 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);
int unpack_bytes (G72x_DATA *data, int bits) ;
int pack_bytes (G72x_DATA *data, int bits) ;
void private_init_state (G72x_STATE *state_ptr) ;
#endif /* G72X_PRIVATE_H */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: d9ad4da7-0fa3-471d-8020-720b5cfb5e5b
*/

View file

@ -0,0 +1,222 @@
/*
** Copyright (C) 1999-2004 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 General Public License as published by
** the Free Software Foundation; either version 2 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "g72x.h"
#include "g72x_priv.h"
#ifndef M_PI
#define M_PI 3.14159265358979323846264338
#endif
#define BUFFER_SIZE (1<<14) /* Should be (1<<14) */
#define SAMPLE_RATE 11025
static void g721_test (void) ;
static void g723_test (double margin) ;
static void gen_signal_double (double *data, double scale, int datalen) ;
static int error_function (double data, double orig, double margin) ;
static int oct_save_short (short *a, short *b, int len) ;
int
main (int argc, char *argv [])
{ int bDoAll = 0 ;
int nTests = 0 ;
if (argc != 2)
{ printf ("Usage : %s <test>\n", argv [0]) ;
printf (" Where <test> is one of the following:\n") ;
printf (" g721 - test G721 encoder and decoder\n") ;
printf (" g723 - test G721 encoder and decoder\n") ;
printf (" all - perform all tests\n") ;
exit (1) ;
} ;
bDoAll=!strcmp (argv [1], "all");
if (bDoAll || ! strcmp (argv [1], "g721"))
{ g721_test () ;
nTests++ ;
} ;
if (bDoAll || ! strcmp (argv [1], "g723"))
{ g723_test (0.53) ;
nTests++ ;
} ;
if (nTests == 0)
{ printf ("Mono : ************************************\n") ;
printf ("Mono : * No '%s' test defined.\n", argv [1]) ;
printf ("Mono : ************************************\n") ;
return 1 ;
} ;
return 0 ;
} /* main */
static void
g721_test (void)
{
return ;
} /* g721_test */
static void
g723_test (double margin)
{ static double orig_buffer [BUFFER_SIZE] ;
static short orig [BUFFER_SIZE] ;
static short data [BUFFER_SIZE] ;
G72x_STATE encoder_state, decoder_state ;
long k ;
int code, position, max_err ;
private_init_state (&encoder_state) ;
encoder_state.encoder = g723_24_encoder ;
encoder_state.codec_bits = 3 ;
private_init_state (&decoder_state) ;
decoder_state.decoder = g723_24_decoder ;
decoder_state.codec_bits = 3 ;
memset (data, 0, BUFFER_SIZE * sizeof (short)) ;
memset (orig, 0, BUFFER_SIZE * sizeof (short)) ;
printf (" g723_test : ") ;
fflush (stdout) ;
gen_signal_double (orig_buffer, 32000.0, BUFFER_SIZE) ;
for (k = 0 ; k < BUFFER_SIZE ; k++)
orig [k] = (short) orig_buffer [k] ;
/* Write and read data here. */
position = 0 ;
max_err = 0 ;
for (k = 0 ; k < BUFFER_SIZE ; k++)
{ code = encoder_state.encoder (orig [k], &encoder_state) ;
data [k] = decoder_state.decoder (code, &decoder_state) ;
if (abs (orig [k] - data [k]) > max_err)
{ position = k ;
max_err = abs (orig [k] - data [k]) ;
} ;
} ;
printf ("\n\nMax error of %d at postion %d.\n", max_err, position) ;
for (k = 0 ; k < BUFFER_SIZE ; k++)
{ if (error_function (data [k], orig [k], margin))
{ printf ("Line %d: Incorrect sample A (#%ld : %d should be %d).\n", __LINE__, k, data [k], orig [k]) ;
oct_save_short (orig, data, BUFFER_SIZE) ;
exit (1) ;
} ;
} ;
printf ("ok\n") ;
return ;
} /* g723_test */
#define SIGNAL_MAXVAL 30000.0
#define DECAY_COUNT 1000
static void
gen_signal_double (double *gendata, double scale, int gendatalen)
{ int k, ramplen ;
double amp = 0.0 ;
ramplen = DECAY_COUNT ;
for (k = 0 ; k < gendatalen ; k++)
{ if (k <= ramplen)
amp = scale * k / ((double) ramplen) ;
else if (k > gendatalen - ramplen)
amp = scale * (gendatalen - k) / ((double) ramplen) ;
gendata [k] = amp * (0.4 * sin (33.3 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))
+ 0.3 * cos (201.1 * 2.0 * M_PI * ((double) (k+1)) / ((double) SAMPLE_RATE))) ;
} ;
return ;
} /* gen_signal_double */
static int
error_function (double data, double orig, double margin)
{ double error ;
if (fabs (orig) <= 500.0)
error = fabs (fabs (data) - fabs(orig)) / 2000.0 ;
else if (fabs (orig) <= 1000.0)
error = fabs (data - orig) / 3000.0 ;
else
error = fabs (data - orig) / fabs (orig) ;
if (error > margin)
{ printf ("\n\n*******************\nError : %f\n", error) ;
return 1 ;
} ;
return 0 ;
} /* error_function */
static int
oct_save_short (short *a, short *b, int len)
{ FILE *file ;
int k ;
if (! (file = fopen ("error.dat", "w")))
return 1 ;
fprintf (file, "# Not created by Octave\n") ;
fprintf (file, "# name: a\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < len ; k++)
fprintf (file, "% d\n", a [k]) ;
fprintf (file, "# name: b\n") ;
fprintf (file, "# type: matrix\n") ;
fprintf (file, "# rows: %d\n", len) ;
fprintf (file, "# columns: 1\n") ;
for (k = 0 ; k < len ; k++)
fprintf (file, "% d\n", b [k]) ;
fclose (file) ;
return 0 ;
} /* oct_save_short */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0597b442-a5b0-4abf-92a4-92f6c24e85a6
*/

View 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

View 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

View file

@ -0,0 +1,21 @@
## Process this file with automake to produce Makefile.in
EXTRA_DIST = README COPYRIGHT ChangeLog
noinst_HEADERS = gsm.h config.h gsm610_priv.h
noinst_LTLIBRARIES = libgsm.la
CFILES = add.c decode.c gsm_decode.c gsm_encode.c long_term.c preprocess.c \
short_term.c code.c gsm_create.c gsm_destroy.c gsm_option.c lpc.c rpe.c table.c
libgsm_la_SOURCES = $(CFILES) $(noinst_HEADERS)
# Disable autoheader.
AUTOHEADER=echo
## Do not edit or modify anything in this comment block.
## The arch-tag line is a file identity tag for the GNU Arch
## revision control system.
##
## arch-tag: ba91ffbe-9d1d-4044-a1de-e8ee2f890560

View file

@ -0,0 +1,470 @@
# Makefile.in generated by automake 1.7.9 from Makefile.am.
# @configure_input@
# Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003
# Free Software Foundation, Inc.
# This Makefile.in is free software; the Free Software Foundation
# gives unlimited permission to copy and/or distribute it,
# with or without modifications, as long as this notice is preserved.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.
@SET_MAKE@
srcdir = @srcdir@
top_srcdir = @top_srcdir@
VPATH = @srcdir@
pkgdatadir = $(datadir)/@PACKAGE@
pkglibdir = $(libdir)/@PACKAGE@
pkgincludedir = $(includedir)/@PACKAGE@
top_builddir = ../..
am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
INSTALL = @INSTALL@
install_sh_DATA = $(install_sh) -c -m 644
install_sh_PROGRAM = $(install_sh) -c
install_sh_SCRIPT = $(install_sh) -c
INSTALL_HEADER = $(INSTALL_DATA)
transform = $(program_transform_name)
NORMAL_INSTALL = :
PRE_INSTALL = :
POST_INSTALL = :
NORMAL_UNINSTALL = :
PRE_UNINSTALL = :
POST_UNINSTALL = :
host_triplet = @host@
ACLOCAL = @ACLOCAL@
ALSA_LIBS = @ALSA_LIBS@
AMDEP_FALSE = @AMDEP_FALSE@
AMDEP_TRUE = @AMDEP_TRUE@
AMTAR = @AMTAR@
AR = @AR@
AUTOCONF = @AUTOCONF@
# Disable autoheader.
AUTOHEADER = echo
AUTOMAKE = @AUTOMAKE@
AWK = @AWK@
CC = @CC@
CCDEPMODE = @CCDEPMODE@
CFLAGS = @CFLAGS@
COMPILER_IS_GCC = @COMPILER_IS_GCC@
CPP = @CPP@
CPPFLAGS = @CPPFLAGS@
CXX = @CXX@
CXXCPP = @CXXCPP@
CXXDEPMODE = @CXXDEPMODE@
CXXFLAGS = @CXXFLAGS@
CYGPATH_W = @CYGPATH_W@
DEFS = @DEFS@
DEPDIR = @DEPDIR@
ECHO = @ECHO@
ECHO_C = @ECHO_C@
ECHO_N = @ECHO_N@
ECHO_T = @ECHO_T@
EGREP = @EGREP@
ENABLE_EXPERIMENTAL_CODE = @ENABLE_EXPERIMENTAL_CODE@
EXEEXT = @EXEEXT@
F77 = @F77@
FFLAGS = @FFLAGS@
GCC_MAJOR_VERSION = @GCC_MAJOR_VERSION@
GETCONF = @GETCONF@
HTML_BGCOLOUR = @HTML_BGCOLOUR@
HTML_FGCOLOUR = @HTML_FGCOLOUR@
INSTALL_DATA = @INSTALL_DATA@
INSTALL_PROGRAM = @INSTALL_PROGRAM@
INSTALL_SCRIPT = @INSTALL_SCRIPT@
INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
LDFLAGS = @LDFLAGS@
LIBOBJS = @LIBOBJS@
LIBS = @LIBS@
LIBTOOL = @LIBTOOL@
LIBTOOL_DEPS = @LIBTOOL_DEPS@
LN_S = @LN_S@
LTLIBOBJS = @LTLIBOBJS@
MAKEINFO = @MAKEINFO@
OBJEXT = @OBJEXT@
OS_SPECIFIC_CFLAGS = @OS_SPECIFIC_CFLAGS@
OS_SPECIFIC_LINKS = @OS_SPECIFIC_LINKS@
PACKAGE = @PACKAGE@
PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
PACKAGE_NAME = @PACKAGE_NAME@
PACKAGE_STRING = @PACKAGE_STRING@
PACKAGE_TARNAME = @PACKAGE_TARNAME@
PACKAGE_VERSION = @PACKAGE_VERSION@
PATH_SEPARATOR = @PATH_SEPARATOR@
RANLIB = @RANLIB@
SET_MAKE = @SET_MAKE@
SF_COUNT_MAX = @SF_COUNT_MAX@
SHARED_VERSION_INFO = @SHARED_VERSION_INFO@
SHELL = @SHELL@
SHLIB_VERSION_ARG = @SHLIB_VERSION_ARG@
SIZEOF_SF_COUNT_T = @SIZEOF_SF_COUNT_T@
STRIP = @STRIP@
TYPEOF_SF_COUNT_T = @TYPEOF_SF_COUNT_T@
VERSION = @VERSION@
ac_ct_AR = @ac_ct_AR@
ac_ct_CC = @ac_ct_CC@
ac_ct_CXX = @ac_ct_CXX@
ac_ct_F77 = @ac_ct_F77@
ac_ct_GETCONF = @ac_ct_GETCONF@
ac_ct_RANLIB = @ac_ct_RANLIB@
ac_ct_STRIP = @ac_ct_STRIP@
am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
am__include = @am__include@
am__leading_dot = @am__leading_dot@
am__quote = @am__quote@
autogen = @autogen@
bindir = @bindir@
build = @build@
build_alias = @build_alias@
build_cpu = @build_cpu@
build_os = @build_os@
build_vendor = @build_vendor@
datadir = @datadir@
exec_prefix = @exec_prefix@
host = @host@
host_alias = @host_alias@
host_cpu = @host_cpu@
host_os = @host_os@
host_vendor = @host_vendor@
htmldocdir = @htmldocdir@
includedir = @includedir@
infodir = @infodir@
install_sh = @install_sh@
libdir = @libdir@
libexecdir = @libexecdir@
localstatedir = @localstatedir@
mandir = @mandir@
oldincludedir = @oldincludedir@
prefix = @prefix@
program_transform_name = @program_transform_name@
sbindir = @sbindir@
sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target = @target@
target_alias = @target_alias@
target_cpu = @target_cpu@
target_os = @target_os@
target_vendor = @target_vendor@
EXTRA_DIST = README COPYRIGHT ChangeLog
noinst_HEADERS = gsm.h config.h gsm610_priv.h
noinst_LTLIBRARIES = libgsm.la
CFILES = add.c decode.c gsm_decode.c gsm_encode.c long_term.c preprocess.c \
short_term.c code.c gsm_create.c gsm_destroy.c gsm_option.c lpc.c rpe.c table.c
libgsm_la_SOURCES = $(CFILES) $(noinst_HEADERS)
subdir = src/GSM610
ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
CONFIG_HEADER = $(top_builddir)/src/config.h
CONFIG_CLEAN_FILES =
LTLIBRARIES = $(noinst_LTLIBRARIES)
libgsm_la_LDFLAGS =
libgsm_la_LIBADD =
am__objects_1 = add.lo decode.lo gsm_decode.lo gsm_encode.lo \
long_term.lo preprocess.lo short_term.lo code.lo gsm_create.lo \
gsm_destroy.lo gsm_option.lo lpc.lo rpe.lo table.lo
am__objects_2 =
am_libgsm_la_OBJECTS = $(am__objects_1) $(am__objects_2)
libgsm_la_OBJECTS = $(am_libgsm_la_OBJECTS)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)/src
depcomp = $(SHELL) $(top_srcdir)/depcomp
am__depfiles_maybe = depfiles
@AMDEP_TRUE@DEP_FILES = ./$(DEPDIR)/add.Plo ./$(DEPDIR)/code.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/decode.Plo ./$(DEPDIR)/gsm_create.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_decode.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_destroy.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_encode.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/gsm_option.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/long_term.Plo ./$(DEPDIR)/lpc.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/preprocess.Plo ./$(DEPDIR)/rpe.Plo \
@AMDEP_TRUE@ ./$(DEPDIR)/short_term.Plo ./$(DEPDIR)/table.Plo
COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
$(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) \
$(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
CCLD = $(CC)
LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
$(AM_LDFLAGS) $(LDFLAGS) -o $@
DIST_SOURCES = $(libgsm_la_SOURCES)
HEADERS = $(noinst_HEADERS)
DIST_COMMON = README $(noinst_HEADERS) $(srcdir)/Makefile.in ChangeLog \
Makefile.am
SOURCES = $(libgsm_la_SOURCES)
all: all-am
.SUFFIXES:
.SUFFIXES: .c .lo .o .obj
$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.ac $(ACLOCAL_M4)
cd $(top_srcdir) && \
$(AUTOMAKE) --gnu src/GSM610/Makefile
Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)
clean-noinstLTLIBRARIES:
-test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
@list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
test "$$dir" = "$$p" && dir=.; \
echo "rm -f \"$${dir}/so_locations\""; \
rm -f "$${dir}/so_locations"; \
done
libgsm.la: $(libgsm_la_OBJECTS) $(libgsm_la_DEPENDENCIES)
$(LINK) $(libgsm_la_LDFLAGS) $(libgsm_la_OBJECTS) $(libgsm_la_LIBADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT) core *.core
distclean-compile:
-rm -f *.tab.c
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/add.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/code.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_create.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_decode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_destroy.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_encode.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsm_option.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/long_term.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/lpc.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/preprocess.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/rpe.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/short_term.Plo@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/table.Plo@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `test -f '$<' || echo '$(srcdir)/'`$<
.c.obj:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Po' tmpdepfile='$(DEPDIR)/$*.TPo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(COMPILE) -c `if test -f '$<'; then $(CYGPATH_W) '$<'; else $(CYGPATH_W) '$(srcdir)/$<'; fi`
.c.lo:
@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" \
@am__fastdepCC_TRUE@ -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<; \
@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; \
@am__fastdepCC_TRUE@ else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; \
@am__fastdepCC_TRUE@ fi
@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ depfile='$(DEPDIR)/$*.Plo' tmpdepfile='$(DEPDIR)/$*.TPlo' @AMDEPBACKSLASH@
@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ `test -f '$<' || echo '$(srcdir)/'`$<
mostlyclean-libtool:
-rm -f *.lo
clean-libtool:
-rm -rf .libs _libs
distclean-libtool:
-rm -f libtool
uninstall-info-am:
ETAGS = etags
ETAGSFLAGS =
CTAGS = ctags
CTAGSFLAGS =
tags: TAGS
ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
mkid -fID $$unique
TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(ETAGS_ARGS)$$tags$$unique" \
|| $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
$$tags $$unique
ctags: CTAGS
CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
$(TAGS_FILES) $(LISP)
tags=; \
here=`pwd`; \
list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
unique=`for i in $$list; do \
if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
done | \
$(AWK) ' { files[$$0] = 1; } \
END { for (i in files) print i; }'`; \
test -z "$(CTAGS_ARGS)$$tags$$unique" \
|| $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
$$tags $$unique
GTAGS:
here=`$(am__cd) $(top_builddir) && pwd` \
&& cd $(top_srcdir) \
&& gtags -i $(GTAGS_ARGS) $$here
distclean-tags:
-rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
top_distdir = ../..
distdir = $(top_distdir)/$(PACKAGE)-$(VERSION)
distdir: $(DISTFILES)
@srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
list='$(DISTFILES)'; for file in $$list; do \
case $$file in \
$(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
$(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
esac; \
if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
if test "$$dir" != "$$file" && test "$$dir" != "."; then \
dir="/$$dir"; \
$(mkinstalldirs) "$(distdir)$$dir"; \
else \
dir=''; \
fi; \
if test -d $$d/$$file; then \
if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
fi; \
cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
else \
test -f $(distdir)/$$file \
|| cp -p $$d/$$file $(distdir)/$$file \
|| exit 1; \
fi; \
done
check-am: all-am
check: check-am
all-am: Makefile $(LTLIBRARIES) $(HEADERS)
installdirs:
install: install-am
install-exec: install-exec-am
install-data: install-data-am
uninstall: uninstall-am
install-am: all-am
@$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
installcheck: installcheck-am
install-strip:
$(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
`test -z '$(STRIP)' || \
echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
mostlyclean-generic:
clean-generic:
distclean-generic:
-rm -f $(CONFIG_CLEAN_FILES)
maintainer-clean-generic:
@echo "This command is intended for maintainers to use"
@echo "it deletes files that may require special tools to rebuild."
clean: clean-am
clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
mostlyclean-am
distclean: distclean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
distclean-am: clean-am distclean-compile distclean-generic \
distclean-libtool distclean-tags
dvi: dvi-am
dvi-am:
info: info-am
info-am:
install-data-am:
install-exec-am:
install-info: install-info-am
install-man:
installcheck-am:
maintainer-clean: maintainer-clean-am
-rm -rf ./$(DEPDIR)
-rm -f Makefile
maintainer-clean-am: distclean-am maintainer-clean-generic
mostlyclean: mostlyclean-am
mostlyclean-am: mostlyclean-compile mostlyclean-generic \
mostlyclean-libtool
pdf: pdf-am
pdf-am:
ps: ps-am
ps-am:
uninstall-am: uninstall-info-am
.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
clean-libtool clean-noinstLTLIBRARIES ctags distclean \
distclean-compile distclean-generic distclean-libtool \
distclean-tags distdir dvi dvi-am info info-am install \
install-am install-data install-data-am install-exec \
install-exec-am install-info install-info-am install-man \
install-strip installcheck installcheck-am installdirs \
maintainer-clean maintainer-clean-generic mostlyclean \
mostlyclean-compile mostlyclean-generic mostlyclean-libtool pdf \
pdf-am ps ps-am tags uninstall uninstall-am uninstall-info-am
# Tell versions [3.59,3.63) of GNU make to not export all variables.
# Otherwise a system limit (for SysV at least) may be exceeded.
.NOEXPORT:

View 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

View file

@ -0,0 +1,248 @@
/*
* 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"
#include "gsm.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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a7398579-e2e1-4733-aa2d-4c6efc0c58ff
*/

View file

@ -0,0 +1,97 @@
/*
* 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 "config.h"
#include "gsm610_priv.h"
#include "gsm.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, 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) );
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: ae8ef1b2-5a1e-4263-94cd-42b15dca81a3
*/

View file

@ -0,0 +1,33 @@
/*
* 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 5338dfef-8e59-4f51-af47-627c9ea85353
*/

View file

@ -0,0 +1,67 @@
/*
* 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"
#include "gsm.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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 11ae5b90-2e8b-400b-ac64-a69a1fc6cc41
*/

View file

@ -0,0 +1,58 @@
/*
* 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8cfc7698-5433-4b6f-aeca-967c6fda4dec
*/

View file

@ -0,0 +1,304 @@
/*
* 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
/* 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8bc5fdf2-e8c8-4686-9bd7-a30b512bef0c
*/

View file

@ -0,0 +1,44 @@
/*
* 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 ;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 9fedb6b3-ed99-40c2-aac1-484c536261fe
*/

View file

@ -0,0 +1,366 @@
/*
* 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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 6a9b6628-821c-4a96-84c1-485ebd35f170
*/

View file

@ -0,0 +1,31 @@
/*
* 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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f423d09b-6ccc-47e0-9b18-ee1cf7a8e473
*/

View file

@ -0,0 +1,456 @@
/*
* 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);
}
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: cfe9c43d-d97c-4216-b5e5-ccd6a25b582b
*/

View file

@ -0,0 +1,74 @@
/*
* 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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 963ff156-506f-4359-9145-371e9060b030
*/

View file

@ -0,0 +1,951 @@
/*
* 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"
#include "gsm.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);
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);
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 ];
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b369b90d-0284-42a0-87b0-99a25bbd93ac
*/

View file

@ -0,0 +1,341 @@
/*
* 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"
#include "gsm.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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 63146664-a002-4e1e-8b7b-f0cc8a6a53da
*/

View file

@ -0,0 +1,115 @@
/*
* 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"
#include "gsm.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;
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b760b0d9-3a05-4da3-9dc9-441ffb905d87
*/

View file

@ -0,0 +1,490 @@
/*
* 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"
#include "gsm.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 );
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 82005b9e-1560-4e94-9ddb-00cb14867295
*/

View file

@ -0,0 +1,427 @@
/*
* 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"
#include "gsm.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);
}
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 019ac7ba-c6dd-4540-abf0-8644b6c4a633
*/

View file

@ -0,0 +1,69 @@
/*
* 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"
#include "gsm.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 };
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8957c531-e6b0-4097-9202-da7ca42729ca
*/

View file

@ -0,0 +1,34 @@
# Auto-generated by create_symbols_file.py
_sf_command
_sf_open
_sf_close
_sf_seek
_sf_error
_sf_perror
_sf_error_str
_sf_error_number
_sf_format_check
_sf_read_raw
_sf_readf_short
_sf_readf_int
_sf_readf_float
_sf_readf_double
_sf_read_short
_sf_read_int
_sf_read_float
_sf_read_double
_sf_write_raw
_sf_writef_short
_sf_writef_int
_sf_writef_float
_sf_writef_double
_sf_write_short
_sf_write_int
_sf_write_float
_sf_write_double
_sf_strerror
_sf_get_string
_sf_set_string
_sf_open_fd

View file

@ -0,0 +1,40 @@
# Auto-generated by create_symbols_file.py
libsndfile.so.1.0
{
global:
sf_command ;
sf_open ;
sf_close ;
sf_seek ;
sf_error ;
sf_perror ;
sf_error_str ;
sf_error_number ;
sf_format_check ;
sf_read_raw ;
sf_readf_short ;
sf_readf_int ;
sf_readf_float ;
sf_readf_double ;
sf_read_short ;
sf_read_int ;
sf_read_float ;
sf_read_double ;
sf_write_raw ;
sf_writef_short ;
sf_writef_int ;
sf_writef_float ;
sf_writef_double ;
sf_write_short ;
sf_write_int ;
sf_write_float ;
sf_write_double ;
sf_strerror ;
sf_get_string ;
sf_set_string ;
sf_open_fd ;
local:
* ;
} ;

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,544 @@
/*
** Copyright (C) 1999-2004 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 "sndfile.h"
#include "float_cast.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, short *ptr, sf_count_t len) ;
static sf_count_t alaw_write_i2alaw (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t alaw_write_f2alaw (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t alaw_write_d2alaw (SF_PRIVATE *psf, 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 (short *buffer, int count, unsigned char *ptr) ;
static void i2alaw_array (int *buffer, int count, unsigned char *ptr) ;
static void f2alaw_array (float *buffer, int count, unsigned char *ptr, float normfact) ;
static void d2alaw_array (double *buffer, int count, unsigned char *ptr, double normfact) ;
int
alaw_init (SF_PRIVATE *psf)
{
if (psf->mode == SFM_READ || psf->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->mode == SFM_WRITE || psf->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->datalength / psf->blockwidth ;
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 (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 (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 (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 (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, 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, 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, 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, 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 289ccfc2-42a6-4f1f-a29f-4dcc9bfa8752
*/

View file

@ -0,0 +1,495 @@
/*
** Copyright (C) 1999-2004 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 "config.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#include "au.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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = au_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AU)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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->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 :
if (psf->mode == SFM_READ)
error = au_g72x_reader_init (psf, AU_H_G721_32) ;
else if (psf->mode == SFM_WRITE)
error = au_g72x_writer_init (psf, AU_H_G721_32) ;
psf->sf.seekable = SF_FALSE ;
break ;
case SF_FORMAT_G723_24 :
if (psf->mode == SFM_READ)
error = au_g72x_reader_init (psf, AU_H_G723_24) ;
else if (psf->mode == SFM_WRITE)
error = au_g72x_writer_init (psf, AU_H_G723_24) ;
psf->sf.seekable = SF_FALSE ;
break ;
case SF_FORMAT_G723_40 :
if (psf->mode == SFM_READ)
error = au_g72x_reader_init (psf, AU_H_G723_40) ;
else if (psf->mode == SFM_WRITE)
error = au_g72x_writer_init (psf, AU_H_G723_40) ;
psf->sf.seekable = SF_FALSE ;
break ;
/* Lite remove end */
default : break ;
} ;
return error ;
} /* au_open */
int
au_nh_open (SF_PRIVATE *psf)
{
if (psf->mode == SFM_RDWR)
return SFE_BAD_OPEN_FORMAT ;
if (psf_fseek (psf, psf->dataoffset, SEEK_SET))
return SFE_BAD_SEEK ;
psf_log_printf (psf, "Header-less u-law encoded file.\n") ;
psf_log_printf (psf, "Setting up for 8kHz, mono, u-law.\n") ;
psf->sf.format = SF_FORMAT_AU | SF_FORMAT_ULAW ;
psf->dataoffset = 0 ;
psf->endian = 0 ; /* Irrelevant but it must be something. */
psf->sf.samplerate = 8000 ;
psf->sf.channels = 1 ;
psf->bytewidth = 1 ; /* Before decoding */
ulaw_init (psf) ;
psf->close = au_close ;
psf->blockwidth = 1 ;
psf->sf.frames = psf->filelength ;
psf->datalength = psf->filelength - AU_DATA_OFFSET ;
return 0 ;
} /* au_nh_open */
/*------------------------------------------------------------------------------
*/
static int
au_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->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 (psf->sf.format & SF_FORMAT_SUBMASK) ;
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 ;
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->close = au_close ;
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 = psf->sf.format & SF_FORMAT_ENDMASK ;
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) ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 31f691b1-cde9-4ed2-9469-6bca60fb9cd0
*/

View file

@ -0,0 +1,39 @@
/*
** Copyright (C) 1999-2004 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 AU_HEADER_FILE
#define AU_HEADER_FILE
enum
{ AU_H_G721_32 = 200,
AU_H_G723_24 = 201,
AU_H_G723_40 = 202
} ;
int au_g72x_reader_init (SF_PRIVATE *psf, int codec) ;
int au_g72x_writer_init (SF_PRIVATE *psf, int codec) ;
#endif /* AU_HEADER_FILE */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 63affc81-e204-4468-9705-60abe4d10689
*/

View file

@ -0,0 +1,634 @@
/*
** Copyright (C) 1999-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
#include "au.h"
#include "G72x/g72x.h"
static int au_g72x_read_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len) ;
static int au_g72x_write_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len) ;
static int au_g72x_decode_block (SF_PRIVATE *psf, G72x_DATA *pg72x) ;
static int au_g72x_encode_block (SF_PRIVATE *psf, G72x_DATA *pg72x) ;
static sf_count_t au_g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t au_g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t au_g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t au_g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t au_g72x_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t au_g72x_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t au_g72x_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t au_g72x_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t au_g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int au_g72x_close (SF_PRIVATE *psf) ;
/*============================================================================================
** WAV G721 Reader initialisation function.
*/
int
au_g72x_reader_init (SF_PRIVATE *psf, int codec)
{ G72x_DATA *pg72x ;
int bitspersample ;
psf->sf.seekable = SF_FALSE ;
if (psf->sf.channels != 1)
return SFE_G72X_NOT_MONO ;
if (! (pg72x = malloc (sizeof (G72x_DATA))))
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pg72x ;
pg72x->blockcount = 0 ;
pg72x->samplecount = 0 ;
switch (codec)
{ case AU_H_G721_32 :
g72x_reader_init (pg72x, G721_32_BITS_PER_SAMPLE) ;
pg72x->bytesperblock = G721_32_BYTES_PER_BLOCK ;
bitspersample = G721_32_BITS_PER_SAMPLE ;
break ;
case AU_H_G723_24:
g72x_reader_init (pg72x, G723_24_BITS_PER_SAMPLE) ;
pg72x->bytesperblock = G723_24_BYTES_PER_BLOCK ;
bitspersample = G723_24_BITS_PER_SAMPLE ;
break ;
case AU_H_G723_40:
g72x_reader_init (pg72x, G723_40_BITS_PER_SAMPLE) ;
pg72x->bytesperblock = G723_40_BYTES_PER_BLOCK ;
bitspersample = G723_40_BITS_PER_SAMPLE ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
psf->read_short = au_g72x_read_s ;
psf->read_int = au_g72x_read_i ;
psf->read_float = au_g72x_read_f ;
psf->read_double = au_g72x_read_d ;
psf->seek = au_g72x_seek ;
psf->close = au_g72x_close ;
psf->blockwidth = psf->bytewidth = 1 ;
psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->datalength % pg72x->blocksize)
pg72x->blocks = (psf->datalength / pg72x->blocksize) + 1 ;
else
pg72x->blocks = psf->datalength / pg72x->blocksize ;
psf->sf.frames = (8 * psf->datalength) / bitspersample ;
if ((psf->sf.frames * bitspersample) / 8 != psf->datalength)
psf_log_printf (psf, "*** Warning : weird psf->datalength.\n") ;
au_g72x_decode_block (psf, pg72x) ;
return 0 ;
} /* au_g72x_reader_init */
/*============================================================================================
** WAV G721 writer initialisation function.
*/
int
au_g72x_writer_init (SF_PRIVATE *psf, int codec)
{ G72x_DATA *pg72x ;
int bitspersample ;
psf->sf.seekable = SF_FALSE ;
if (psf->sf.channels != 1)
return SFE_G72X_NOT_MONO ;
if (! (pg72x = malloc (sizeof (G72x_DATA))))
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pg72x ;
pg72x->blockcount = 0 ;
pg72x->samplecount = 0 ;
switch (codec)
{ case AU_H_G721_32 :
g72x_writer_init (pg72x, G721_32_BITS_PER_SAMPLE) ;
pg72x->bytesperblock = G721_32_BYTES_PER_BLOCK ;
bitspersample = G721_32_BITS_PER_SAMPLE ;
break ;
case AU_H_G723_24:
g72x_writer_init (pg72x, G723_24_BITS_PER_SAMPLE) ;
pg72x->bytesperblock = G723_24_BYTES_PER_BLOCK ;
bitspersample = G723_24_BITS_PER_SAMPLE ;
break ;
case AU_H_G723_40:
g72x_writer_init (pg72x, G723_40_BITS_PER_SAMPLE) ;
pg72x->bytesperblock = G723_40_BYTES_PER_BLOCK ;
bitspersample = G723_40_BITS_PER_SAMPLE ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
psf->write_short = au_g72x_write_s ;
psf->write_int = au_g72x_write_i ;
psf->write_float = au_g72x_write_f ;
psf->write_double = au_g72x_write_d ;
psf->close = au_g72x_close ;
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->datalength % pg72x->blocksize)
pg72x->blocks = (psf->datalength / pg72x->blocksize) + 1 ;
else
pg72x->blocks = 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") ;
return 0 ;
} /* au_g72x_writer_init */
/*============================================================================================
** G721 Read Functions.
*/
static int
au_g72x_decode_block (SF_PRIVATE *psf, G72x_DATA *pg72x)
{ int k ;
pg72x->blockcount ++ ;
pg72x->samplecount = 0 ;
if (pg72x->samplecount > pg72x->blocksize)
{ 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) ;
return 1 ;
} /* au_g72x_decode_block */
static int
au_g72x_read_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ if (pg72x->blockcount >= pg72x->blocks && pg72x->samplecount >= pg72x->samplesperblock)
{ memset (&(ptr [indx]), 0, (len - indx) * sizeof (short)) ;
return total ;
} ;
if (pg72x->samplecount >= pg72x->samplesperblock)
au_g72x_decode_block (psf, pg72x) ;
count = pg72x->samplesperblock - pg72x->samplecount ;
count = (len - indx > count) ? count : len - indx ;
memcpy (&(ptr [indx]), &(pg72x->samples [pg72x->samplecount]), count * sizeof (short)) ;
indx += count ;
pg72x->samplecount += count ;
total = indx ;
} ;
return total ;
} /* au_g72x_read_block */
static sf_count_t
au_g72x_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
int readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = au_g72x_read_block (psf, pg72x, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* au_g72x_read_s */
static sf_count_t
au_g72x_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = SF_BUFFER_LEN / sizeof (short) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = au_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 ;
} /* au_g72x_read_i */
static sf_count_t
au_g72x_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
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 = au_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 ;
} /* au_g72x_read_f */
static sf_count_t
au_g72x_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
short *sptr ;
int k, bufferlen, readcount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
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 = au_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 ;
} /* au_g72x_read_d */
static sf_count_t
au_g72x_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{
/* Prevent compiler warnings. */
mode ++ ;
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_DATA *pg72x ;
** int newblock, newsample, samplecount ;
**
** if (! psf->fdata)
** return 0 ;
** pg72x = (G72x_DATA*) psf->fdata ;
**
** if (! (psf->datalength && psf->dataoffset))
** { psf->error = SFE_BAD_SEEK ;
** return ((sf_count_t) -1) ;
** } ;
**
** samplecount = (8 * psf->datalength) / G721_32_BITS_PER_SAMPLE ;
**
** switch (whence)
** { case SEEK_SET :
** if (offset < 0 || offset > samplecount)
** { psf->error = SFE_BAD_SEEK ;
** return ((sf_count_t) -1) ;
** } ;
** newblock = offset / pg72x->samplesperblock ;
** newsample = offset % pg72x->samplesperblock ;
** break ;
**
** case SEEK_CUR :
** if (psf->current + offset < 0 || psf->current + offset > samplecount)
** { psf->error = SFE_BAD_SEEK ;
** return ((sf_count_t) -1) ;
** } ;
** newblock = (8 * (psf->current + offset)) / pg72x->samplesperblock ;
** newsample = (8 * (psf->current + offset)) % pg72x->samplesperblock ;
** break ;
**
** case SEEK_END :
** if (offset > 0 || samplecount + offset < 0)
** { psf->error = SFE_BAD_SEEK ;
** return ((sf_count_t) -1) ;
** } ;
** newblock = (samplecount + offset) / pg72x->samplesperblock ;
** newsample = (samplecount + offset) % pg72x->samplesperblock ;
** break ;
**
** default :
** psf->error = SFE_BAD_SEEK ;
** return ((sf_count_t) -1) ;
** } ;
**
** if (psf->mode == SFM_READ)
** { psf_fseek (psf, psf->dataoffset + newblock * pg72x->blocksize, SEEK_SET) ;
** pg72x->blockcount = newblock ;
** au_g72x_decode_block (psf, pg72x) ;
** pg72x->samplecount = newsample ;
** }
** else
** { /+* What to do about write??? *+/
** psf->error = SFE_BAD_SEEK ;
** return ((sf_count_t) -1) ;
** } ;
**
** psf->current = newblock * pg72x->samplesperblock + newsample ;
** return psf->current ;
**
*/
} /* au_g72x_seek */
/*==========================================================================================
** G72x Write Functions.
*/
static int
au_g72x_encode_block (SF_PRIVATE *psf, G72x_DATA *pg72x)
{ int k ;
/* Encode the samples. */
g72x_encode_block (pg72x) ;
/* 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->samplecount = 0 ;
pg72x->blockcount ++ ;
/* Set samples to zero for next block. */
memset (pg72x->samples, 0, G72x_BLOCK_SIZE * sizeof (short)) ;
return 1 ;
} /* au_g72x_encode_block */
static int
au_g72x_write_block (SF_PRIVATE *psf, G72x_DATA *pg72x, short *ptr, int len)
{ int count, total = 0, indx = 0 ;
while (indx < len)
{ count = pg72x->samplesperblock - pg72x->samplecount ;
if (count > len - indx)
count = len - indx ;
memcpy (&(pg72x->samples [pg72x->samplecount]), &(ptr [indx]), count * sizeof (short)) ;
indx += count ;
pg72x->samplecount += count ;
total = indx ;
if (pg72x->samplecount >= pg72x->samplesperblock)
au_g72x_encode_block (psf, pg72x) ;
} ;
return total ;
} /* au_g72x_write_block */
static sf_count_t
au_g72x_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
while (len > 0)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = au_g72x_write_block (psf, pg72x, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* au_g72x_write_s */
static sf_count_t
au_g72x_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
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 = au_g72x_write_block (psf, pg72x, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* au_g72x_write_i */
static sf_count_t
au_g72x_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
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 = au_g72x_write_block (psf, pg72x, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* au_g72x_write_f */
static sf_count_t
au_g72x_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ G72x_DATA *pg72x ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
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 = au_g72x_write_block (psf, pg72x, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* au_g72x_write_d */
static int
au_g72x_close (SF_PRIVATE *psf)
{ G72x_DATA *pg72x ;
if (! psf->fdata)
return 0 ;
pg72x = (G72x_DATA*) psf->fdata ;
if (psf->mode == SFM_WRITE)
{ /* If a block has been partially assembled, write it out
** as the final block.
*/
if (pg72x->samplecount && pg72x->samplecount < G72x_BLOCK_SIZE)
au_g72x_encode_block (psf, pg72x) ;
if (psf->write_header)
psf->write_header (psf, SF_FALSE) ;
} ;
return 0 ;
} /* au_g72x_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 3cc5439e-7247-486b-b2e6-11a4affa5744
*/

View file

@ -0,0 +1,262 @@
/*
** Copyright (C) 2004 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 "config.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 subformat ;
int error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = avr_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_AVR)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
psf->endian = SF_ENDIAN_BIG ;
if (avr_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = avr_write_header ;
} ;
psf->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 ;
break ;
} ;
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->close = avr_close ;
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, 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) ;
} ;
/* 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) ;
datalength = (int) (psf->datalength & 0x7FFFFFFF) ;
psf_binheader_writef (psf, "Emz22", TWOBIT_MARKER, (size_t) 8,
psf->sf.channels == 2 ? 0xFFFF : 0, psf->bytewidth * 8) ;
sign = ((psf->sf.format & SF_FORMAT_SUBMASK) == 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, (size_t) 20, (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->mode == SFM_WRITE || psf->mode == SFM_RDWR)
avr_write_header (psf, SF_TRUE) ;
return 0 ;
} /* avr_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0823d454-f39a-4a28-a776-607f1ef33b52
*/

View file

@ -0,0 +1,325 @@
/*
** Copyright (C) 2001-2004 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 <stdio.h>
#include <string.h>
#include <math.h>
#include "sndfile.h"
#include "config.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_RAW | SF_FORMAT_VOX_ADPCM,
"OKI Dialogic VOX ADPCM", "vox"
},
{ 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_CONTROL_CMD ;
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_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_PAF, "PAF (Ensoniq PARIS)", "paf" },
{ SF_FORMAT_PVF, "PVF (Portable Voice Format)", "pvf" },
{ SF_FORMAT_RAW, "RAW (header-less)", "raw" },
{ SF_FORMAT_SDS, "SDS (Midi Sample Dump Standard)", "sds" },
/* Not ready for mainstream use yet.
{ SF_FORMAT_SD2, "SD2 (Sound Designer II)", "sd2" },
*/
{ 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_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_CONTROL_CMD ;
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 },
} ; /* 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_CONTROL_CMD ;
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 (data->format & SF_FORMAT_TYPEMASK)
{ format = data->format & SF_FORMAT_TYPEMASK ;
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 (data->format & SF_FORMAT_SUBMASK)
{ format = data->format & SF_FORMAT_SUBMASK ;
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_CONTROL_CMD ;
} /* 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0aae0d9d-ab2b-4d70-ade3-47a534666f8e
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,691 @@
/*
** Copyright (C) 1999-2004 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 COMMON_H_INCLUDED
#define COMMON_H_INCLUDED
#include "config.h"
#ifndef SNDFILE_H
#include <sndfile.h>
#endif
#if HAVE_STDINT_H
#include <stdint.h>
#endif
#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_HEADER_LEN (4096)
#define SF_TEXT_LEN (1024)
#define SF_SYSERR_LEN (256)
#define SF_MAX_STRINGS (16)
#define SF_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 SF_MAX(a,b) ((a) > (b) ? (a) : (b))
#define SF_MIN(a,b) ((a) < (b) ? (a) : (b))
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. */
/* Formats supported read only. */
SF_FORMAT_WVE = 0x4020000, /* Psion ALaw Sound File */
SF_FORMAT_TXW = 0x4030000, /* Yamaha TX16 sampler file */
SF_FORMAT_DWD = 0x4040000, /* DiamondWare Digirized */
/* Following are detected but not supported. */
SF_FORMAT_OGG = 0x4090000,
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. */
SF_FORMAT_FLAC = 0x4120000,
/* Unsupported encodings. */
SF_FORMAT_VORBIS = 0x1001,
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
{ float value ; /* signed value of peak */
unsigned int position ; /* the sample frame for the peak */
} PEAK_POS ;
typedef struct
{ unsigned int version ; /* version of the PEAK chunk */
unsigned int timestamp ; /* secs since 1/1/1970 */
#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 ike 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_CHUNK ;
typedef struct
{ int type ;
int flags ;
char *str ;
} STR_DATA ;
/*=======================================================================================
** 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 sf_private_tag
{ /* 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 ;
char filepath [SF_FILENAME_LEN] ;
char rsrcpath [SF_FILENAME_LEN] ;
char filename [SF_FILENAME_LEN / 4] ;
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_BUFFER_LEN] ;
char *str_end ;
int str_flags ;
/* Guard value. If this changes the buffers above have overflowed. */
int Magick ;
/* Index variables for maintaining logbuffer and header above. */
int logindex ;
int headindex, headend ;
int has_text ;
int do_not_close_descriptor ;
/* File descriptors for the file and (possibly) the resource fork. */
int filedes, rsrcdes ;
int end_of_file ;
int error ;
int mode ; /* Open mode : SFM_READ, SFM_WRITE or SFM_RDWR. */
int endian ; /* File endianness : SF_ENDIAN_LITTLE or SF_ENDIAN_BIG. */
int float_endswap ; /* Need to endswap float32s? */
/*
** Maximum float value for calculating the multiplier for
** float/double to short/int conversions.
*/
int float_int_mult ;
float float_max ;
/* 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? */
int has_peak ; /* Has a PEAK chunk (AIFF and WAVE) been read? */
int peak_loc ; /* Write a PEAK chunk at the start or end of the file? */
PEAK_CHUNK *pchunk ;
/* Loop Info */
SF_LOOP_INFO *loop_info ;
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 *fdata ; /* This is a pointer to dynamically allocated file 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*, short *ptr, sf_count_t len) ;
sf_count_t (*write_int) (struct sf_private_tag*, int *ptr, sf_count_t len) ;
sf_count_t (*write_float) (struct sf_private_tag*, float *ptr, sf_count_t len) ;
sf_count_t (*write_double) (struct sf_private_tag*, 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) ;
int (*close) (struct sf_private_tag*) ;
char *format_desc ;
} SF_PRIVATE ;
enum
{ SFE_NO_ERROR = SF_ERR_NO_ERROR,
SFE_BAD_OPEN_FORMAT = SF_ERR_UNRECOGNISED_FORMAT,
SFE_SYSTEM = SF_ERR_SYSTEM,
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_LOG_OVERRUN,
SFE_BAD_CONTROL_CMD,
SFE_BAD_ENDIAN,
SFE_CHANNEL_COUNT,
SFE_BAD_RDWR_FORMAT,
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_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_FMT_SHORT,
SFE_WAV_FMT_TOO_BIG,
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_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_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_FMT,
SFE_W64_NO_DATA,
SFE_W64_FMT_SHORT,
SFE_W64_FMT_TOO_BIG,
SFE_W64_ADPCM_NOT4BIT,
SFE_W64_ADPCM_CHANNELS,
SFE_W64_GSM610_FORMAT,
SFE_MAT4_BAD_NAME,
SFE_MAT4_NO_SAMPLERATE,
SFE_MAT4_ZERO_CHANNELS,
SFE_MAT5_BAD_ENDIAN,
SFE_MAT5_NO_BLOCK,
SFE_MAT5_SAMPLE_RATE,
SFE_MAT5_ZERO_CHANNELS,
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_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) ;
void psf_hexdump (void *ptr, int len) ;
/* 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) ;
/* 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) ;
/* 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) ;
/* Generate the currebt date as a string. */
void psf_get_date_str (char *str, int maxlen) ;
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, const char *pathname, int flags) ;
int psf_set_stdio (SF_PRIVATE *psf, int mode) ;
int psf_filedes_valid (SF_PRIVATE *psf) ;
void psf_set_file (SF_PRIVATE *psf, int fd) ;
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) ;
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 mode) ;
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 au_nh_open (SF_PRIVATE *psf) ; /* Headerless version of AU. */
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) ;
/* In progress. Do not currently work. */
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 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) ;
/*------------------------------------------------------------------------------------
** Other helper functions.
*/
void *psf_memset (void *s, int c, sf_count_t n) ;
/*------------------------------------------------------------------------------------
** Here's how we fix systems which don't snprintf / vsnprintf.
** Systems without these functions should use the
*/
#if (defined (WIN32) || defined (_WIN32))
#define LSF_SNPRINTF _snprintf
#elif (HAVE_SNPRINTF && ! FORCE_MISSING_SNPRINTF)
#define LSF_SNPRINTF snprintf
#else
int missing_snprintf (char *str, size_t n, char const *fmt, ...) ;
#define LSF_SNPRINTF missing_snprintf
#endif
#if (defined (WIN32) || defined (_WIN32))
#define LSF_VSNPRINTF _vsnprintf
#elif (HAVE_VSNPRINTF && ! FORCE_MISSING_SNPRINTF)
#define LSF_VSNPRINTF vsnprintf
#else
int missing_vsnprintf (char *str, size_t n, const char *fmt, ...) ;
#define LSF_VSNPRINTF missing_vsnprintf
#endif
#endif /* COMMON_H_INCLUDED */
/*------------------------------------------------------------------------------------
** 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
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 7b45c0ee-5835-4a18-a4ef-994e4cd95b67
*/

View file

@ -0,0 +1,239 @@
/* src/config.h. Generated by configure. */
/* src/config.h.in. Generated from configure.ac by autoheader. */
//#error WTF
/* 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 1
/* Target processor clips on positive float to int conversion. */
#define CPU_CLIPS_POSITIVE 1
/* Target processor is big endian. */
#define CPU_IS_BIG_ENDIAN 1
/* Target processor is little endian. */
#define CPU_IS_LITTLE_ENDIAN 0
/* Set to 1 to enable experimental code. */
#define ENABLE_EXPERIMENTAL_CODE 0
/* Major version of GCC or 3 otherwise. */
#define GCC_MAJOR_VERSION 3
/* 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. */
#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. */
/* #undef HAVE_ENDIAN_H */
/* Define to 1 if you have the `fdatasync' function. */
/* #undef HAVE_FDATASYNC */
/* 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 `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 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. */
#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 `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 `snprintf' function. */
#define HAVE_SNPRINTF 1
/* 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/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 `write' function. */
#define HAVE_WRITE 1
/* Set to 1 if compiling for MacOSX */
#define OS_IS_MACOSX 1
/* 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 "erikd@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.11"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "libsndfile"
/* Define to the version of this package. */
#define PACKAGE_VERSION "1.0.11"
/* Set to maximum allowed value of sf_count_t type. */
#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
/* The size of a `double', as computed by sizeof. */
#define SIZEOF_DOUBLE 8
/* The size of a `float', as computed by sizeof. */
#define SIZEOF_FLOAT 4
/* The size of a `int', as computed by sizeof. */
#define SIZEOF_INT 4
/* The size of a `int64_t', as computed by sizeof. */
#define SIZEOF_INT64_T 8
/* The size of a `loff_t', as computed by sizeof. */
/* #undef SIZEOF_LOFF_T */
/* The size of a `long', as computed by sizeof. */
#define SIZEOF_LONG 4
/* The size of a `long long', as computed by sizeof. */
#define SIZEOF_LONG_LONG 8
/* The size of a `off64_t', as computed by sizeof. */
/* #undef SIZEOF_OFF64_T */
/* The size of a `off_t', as computed by sizeof. */
#define SIZEOF_OFF_T 8
/* Set to sizeof (long) if unknown. */
#define SIZEOF_SF_COUNT_T 8
/* The size of a `short', as computed by sizeof. */
#define SIZEOF_SHORT 2
/* The size of a `size_t', as computed by sizeof. */
#define SIZEOF_SIZE_T 4
/* The size of a `ssize_t', as computed by sizeof. */
#define SIZEOF_SSIZE_T 4
/* The size of a `void*', as computed by sizeof. */
#define SIZEOF_VOIDP 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 off_t
/* Version number of package */
#define VERSION "1.0.11"
/* 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 */

View file

@ -0,0 +1,147 @@
#!/usr/bin/python
# Copyright (C) 2003,2004 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.
import re, sys
#----------------------------------------------------------------
# These are all of the public functions exported from libsndfile.
#
# Its important not to change the order they are listed in or
# the ordinal values in the second column.
ALL_SYMBOLS = (
( "sf_command", 1 ),
( "sf_open", 2 ),
( "sf_close", 3 ),
( "sf_seek", 4 ),
( "sf_error", 7 ),
( "sf_perror", 8 ),
( "sf_error_str", 9 ),
( "sf_error_number", 10 ),
( "sf_format_check", 11 ),
( "sf_read_raw", 16 ),
( "sf_readf_short", 17 ),
( "sf_readf_int", 18 ),
( "sf_readf_float", 19 ),
( "sf_readf_double", 20 ),
( "sf_read_short", 21 ),
( "sf_read_int", 22 ),
( "sf_read_float", 23 ),
( "sf_read_double", 24 ),
( "sf_write_raw", 32 ),
( "sf_writef_short", 33 ),
( "sf_writef_int", 34 ),
( "sf_writef_float", 35 ),
( "sf_writef_double", 36 ),
( "sf_write_short", 37 ),
( "sf_write_int", 38 ),
( "sf_write_float", 39 ),
( "sf_write_double", 40 ),
( "sf_strerror", 50 ),
( "sf_get_string", 60 ),
( "sf_set_string", 61 ),
( "sf_open_fd", 70 )
)
#-------------------------------------------------------------------------------
def linux_symbols (progname, version):
print "# Auto-generated by %s\n" %progname
print "libsndfile.so.%s" % version
print "{"
print " global:"
for name, ordinal in ALL_SYMBOLS:
print " %s ;" % name
print " local:"
print " * ;"
print "} ;"
print
return
def darwin_symbols (progname, version):
print "# Auto-generated by %s\n" %progname
for name, ordinal in ALL_SYMBOLS:
print "_%s" % name
print
return
def win32_symbols (progname, version):
print "; Auto-generated by %s\n" %progname
print "LIBRARY libsndfile.dll"
print "EXPORTS\n"
for name, ordinal in ALL_SYMBOLS:
print "%-20s @%s" % (name, ordinal)
print
return
def no_symbols (os_name):
print
print "No known way of restricting exported symbols on '%s'." % os_name
print "If you know a way, please contact the author."
print
return
#-------------------------------------------------------------------------------
progname = re.sub (".*[\\/]", "", sys.argv [0])
if len (sys.argv) != 3:
print
print "Usage : %s <target OS name> <libsndfile version>." % progname
print
print " Currently supported values for target OS are:"
print " linux"
print " darwin (ie MacOSX)"
print " win32 (ie wintendo)"
print
sys.exit (1)
os_name = sys.argv [1]
version = re.sub ("\.[a-z0-9]+$", "", sys.argv [2])
if os_name == "linux":
linux_symbols (progname, version)
elif os_name == "darwin":
darwin_symbols (progname, version)
elif os_name == "win32":
win32_symbols (progname, version)
else:
no_symbols (os_name)
sys.exit (0)
# Do not edit or modify anything in this comment block.
# The arch-tag line is a file identity tag for the GNU Arch
# revision control system.
#
# arch-tag: 5814f35c-318f-4023-a0c3-d9cf7c9e5f6c

View file

@ -0,0 +1,534 @@
/*
** Copyright (C) 2003,2004 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 <stdlib.h>
#include "sndfile.h"
#include "config.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, short *ptr, sf_count_t len) ;
sf_count_t (*write_int) (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
sf_count_t (*write_float) (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
sf_count_t (*write_double) (SF_PRIVATE *psf, 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, short *ptr, sf_count_t len) ;
static sf_count_t dither_write_int (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t dither_write_float (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t dither_write_double (SF_PRIVATE *psf, 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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_DOUBLE :
case SF_FORMAT_FLOAT :
pdither->read_int = psf->read_int ;
psf->read_int = dither_read_int ;
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 ;
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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_DOUBLE :
case SF_FORMAT_FLOAT :
pdither->write_int = psf->write_int ;
psf->write_int = dither_write_int ;
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 :
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 *psf, short *ptr, sf_count_t len)
{ psf = psf ;
ptr = ptr ;
return len ;
} /* dither_read_short */
static sf_count_t
dither_read_int (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ psf = psf ;
ptr = ptr ;
return len ;
} /* dither_read_int */
/*------------------------------------------------------------------------------
*/
static sf_count_t
dither_write_short (SF_PRIVATE *psf, 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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ 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, 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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
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, 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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
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, 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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
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
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 673fad58-5314-421c-9144-9d54bfdf104c
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,209 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
dwd_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 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 subformat, error = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = dwd_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_DWD)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{
/*-psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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->close = dwd_close ;
/*-psf->blockwidth = psf->bytewidth * psf->sf.channels ;-*/
return error ;
} /* dwd_open */
/*------------------------------------------------------------------------------
*/
static int
dwd_close (SF_PRIVATE *psf)
{
psf = 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
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a5e1d2a6-a840-4039-a0e7-e1a43eb05a4f
*/

View file

@ -0,0 +1,665 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "float_cast.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, short *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t dwvw_write_d (SF_PRIVATE *psf, 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, 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 (bitwidth > 24)
return SFE_DWVW_BAD_BITWIDTH ;
if (psf->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if ((pdwvw = calloc (1, sizeof (DWVW_PRIVATE))) == NULL)
return SFE_MALLOC_FAILED ;
psf->fdata = (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->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->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->seek = dwvw_seek ;
psf->close = dwvw_close ;
/* FIXME : This s bogus. */
psf->sf.frames = SF_COUNT_MAX ;
psf->datalength = psf->sf.frames ;
/* EMXIF : This s bogus. */
return 0 ;
} /* dwvw_init */
/*--------------------------------------------------------------------------------------------
*/
static int
dwvw_close (SF_PRIVATE *psf)
{ DWVW_PRIVATE *pdwvw ;
if (psf->fdata == NULL)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
if (psf->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 mode, sf_count_t offset)
{ DWVW_PRIVATE *pdwvw ;
mode = mode ;
if (! psf->fdata)
{ psf->error = SFE_INTERNAL ;
return ((sf_count_t) -1) ;
} ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
if (offset == 0)
{ psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
dwvw_read_reset (pdwvw) ;
return 0 ;
} ;
psf->error = SFE_BAD_SEEK ;
return ((sf_count_t) -1) ;
} /* 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->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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, 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, short *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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, int *ptr, sf_count_t len)
{ DWVW_PRIVATE *pdwvw ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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, 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->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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, 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->fdata)
return 0 ;
pdwvw = (DWVW_PRIVATE*) psf->fdata ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 1ca09552-b01f-4d7f-9bcf-612f834fe41d
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,960 @@
/*
** Copyright (C) 1999-2004 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.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, short *ptr, sf_count_t len) ;
static sf_count_t host_write_i2f (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t host_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t host_write_d2f (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static void float32_peak_update (SF_PRIVATE *psf, float *buffer, int count, int 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, short *ptr, sf_count_t len) ;
static sf_count_t replace_write_i2f (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t replace_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t replace_write_d2f (SF_PRIVATE *psf, 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->mode == SFM_READ || psf->mode == SFM_RDWR)
{ switch (psf->endian + float_caps)
{ case (SF_ENDIAN_BIG + FLOAT_CAN_RW_BE) :
psf->float_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->float_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->float_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->float_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->float_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->float_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->float_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->float_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->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ switch (psf->endian + float_caps)
{ case (SF_ENDIAN_LITTLE + FLOAT_CAN_RW_LE) :
psf->float_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->float_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->float_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->float_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->float_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->float_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->float_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->float_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->datalength / psf->blockwidth ;
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 *= (1 << exponent) ;
else if (exponent < 0)
fvalue /= (1 << 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 *= (1 << exponent) ;
else if (exponent < 0)
fvalue /= (1 << 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 (in == 0.0)
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 (in == 0.0)
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, float *buffer, int count, int 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->pchunk->peaks [chan].value)
{ psf->pchunk->peaks [chan].value = fmaxval ;
psf->pchunk->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 inline void
f2s_array (float *src, int count, short *dest, float scale)
{ while (--count >= 0)
{ dest [count] = lrintf (scale * src [count]) ;
} ;
} /* f2s_array */
static inline void
f2i_array (float *src, int count, int *dest, float scale)
{ while (--count >= 0)
{ dest [count] = lrintf (scale * src [count]) ;
} ;
} /* f2i_array */
static inline void
f2d_array (float *src, int count, double *dest)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* f2d_array */
static inline void
s2f_array (short *src, float *dest, int count)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* s2f_array */
static inline void
i2f_array (int *src, float *dest, int count)
{ while (--count >= 0)
{ dest [count] = src [count] ;
} ;
} /* i2f_array */
static inline void
d2f_array (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)
{ 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) ;
/* Fix me : Need lef2s_array */
if (psf->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
f2s_array (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)
{ int bufferlen, readcount ;
sf_count_t total = 0 ;
float scale ;
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->float_endswap == SF_TRUE)
endswap_int_array (psf->u.ibuf, bufferlen) ;
f2i_array (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->float_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->float_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, short *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 ;
s2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->has_peak)
float32_peak_update (psf, psf->u.fbuf, bufferlen, (int) (total / psf->sf.channels)) ;
if (psf->float_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, int *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 ;
i2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->has_peak)
float32_peak_update (psf, psf->u.fbuf, bufferlen, (int) (total / psf->sf.channels)) ;
if (psf->float_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, float *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
if (psf->has_peak)
float32_peak_update (psf, ptr, len, 0) ;
if (psf->float_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, (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, 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->has_peak)
float32_peak_update (psf, psf->u.fbuf, bufferlen, (int) (total / psf->sf.channels)) ;
if (psf->float_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->float_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->float_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->float_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->float_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, short *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 ;
s2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->has_peak)
float32_peak_update (psf, psf->u.fbuf, bufferlen, (int) (total / psf->sf.channels)) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_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, int *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 ;
i2f_array (ptr + total, psf->u.fbuf, bufferlen) ;
if (psf->has_peak)
float32_peak_update (psf, psf->u.fbuf, bufferlen, (int) (total / psf->sf.channels)) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_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, float *ptr, sf_count_t len)
{ int bufferlen, writecount ;
sf_count_t total = 0 ;
/* FIX THIS */
if (psf->has_peak)
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->float_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, 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->has_peak)
float32_peak_update (psf, psf->u.fbuf, bufferlen, (int) (total / psf->sf.channels)) ;
f2bf_array (psf->u.fbuf, bufferlen) ;
if (psf->float_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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b6c34917-488c-4145-9648-f4371fc4c889
*/

View file

@ -0,0 +1,210 @@
/*
** Copyright (C) 2001-2004 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.
*/
/* Version 1.3 */
/*============================================================================
** On Intel Pentium processors (especially PIII and probably P4), converting
** from float to int is very slow. To meet the C specs, the code produced by
** most C compilers targeting Pentium needs to change the FPU rounding mode
** before the float to int conversion is performed.
**
** Changing the FPU rounding mode causes the FPU pipeline to be flushed. It
** is this flushing of the pipeline which is so slow.
**
** Fortunately the ISO C99 specifications define the functions lrint, lrintf,
** llrint and llrintf which fix this problem as a side effect.
**
** On Unix-like systems, the configure process should have detected the
** presence of these functions. If they weren't found we have to replace them
** here with a standard C cast.
*/
/*
** The C99 prototypes for lrint and lrintf are as follows:
**
** long int lrintf (float x) ;
** long int lrint (double x) ;
*/
#include "config.h"
/*
** The presence of the required functions are detected during the configure
** process and the values HAVE_LRINT and HAVE_LRINTF are set accordingly in
** the config.h file.
*/
#define HAVE_LRINT_REPLACEMENT 0
#if (HAVE_LRINT && HAVE_LRINTF)
/*
** These defines enable functionality introduced with the 1999 ISO C
** standard. They must be defined before the inclusion of math.h to
** engage them. If optimisation is enabled, these functions will be
** inlined. With optimisation switched off, you have to link in the
** maths library using -lm.
*/
#define _ISOC9X_SOURCE 1
#define _ISOC99_SOURCE 1
#define __USE_ISOC9X 1
#define __USE_ISOC99 1
#include <math.h>
#elif (defined (WIN32) || defined (_WIN32))
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
/*
** Win32 doesn't seem to have these functions.
** Therefore implement inline versions of these functions here.
*/
__inline long int
lrint (double flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
__inline long int
lrintf (float flt)
{ int intgr ;
_asm
{ fld flt
fistp intgr
} ;
return intgr ;
}
#elif (defined (__MWERKS__) && defined (macintosh))
/* This MacOS 9 solution was provided by Stephane Letz */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline int
float2int (register float in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* float2int */
inline int
double2int (register double in)
{ long res [2] ;
asm
{ fctiw in, in
stfd in, res
}
return res [1] ;
} /* double2int */
#elif (defined (__MACH__) && defined (__APPLE__))
/* For Apple MacOSX. */
#undef HAVE_LRINT_REPLACEMENT
#define HAVE_LRINT_REPLACEMENT 1
#include <math.h>
#undef lrint
#undef lrintf
#define lrint double2int
#define lrintf float2int
inline static long int
float2int (register float in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrintf */
inline static long int
double2int (register double in)
{ int res [2] ;
__asm__ __volatile__
( "fctiw %1, %1\n\t"
"stfd %1, %0"
: "=m" (res) /* Output */
: "f" (in) /* Input */
: "memory"
) ;
return res [1] ;
} /* lrint */
#else
#ifndef __sgi
#warning "Don't have the functions lrint() and lrintf()."
#warning "Replacing these functions with a standard C cast."
#endif
#include <math.h>
#define lrint(dbl) ((long) (dbl))
#define lrintf(flt) ((long) (flt))
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 42db1693-ff61-4051-bac1-e4d24c4e30b7
*/

View file

@ -0,0 +1,605 @@
/*
** Copyright (C) 1999-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.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] ;
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, short *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t gsm610_write_d (SF_PRIVATE *psf, 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, 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->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
psf->sf.seekable = SF_FALSE ;
if (! (pgsm610 = malloc (sizeof (GSM610_PRIVATE))))
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pgsm610 ;
memset (pgsm610, 0, sizeof (GSM610_PRIVATE)) ;
/*============================================================
Need separate gsm_data structs for encode and decode.
============================================================*/
if (! (pgsm610->gsm_data = gsm_create ()))
return SFE_MALLOC_FAILED ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV ||
(psf->sf.format & SF_FORMAT_TYPEMASK) == 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 ;
}
else
{ pgsm610->encode_block = gsm610_encode_block ;
pgsm610->decode_block = gsm610_decode_block ;
pgsm610->samplesperblock = GSM610_SAMPLES ;
pgsm610->blocksize = GSM610_BLOCKSIZE ;
} ;
if (psf->mode == SFM_READ)
{ if (psf->datalength % pgsm610->blocksize)
{ psf_log_printf (psf, "*** Warning : data chunk seems to be truncated.\n") ;
pgsm610->blocks = psf->datalength / pgsm610->blocksize + 1 ;
}
else
pgsm610->blocks = psf->datalength / pgsm610->blocksize ;
psf->sf.frames = pgsm610->samplesperblock * pgsm610->blocks ;
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->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->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 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 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 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, (size_t) ((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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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 mode, sf_count_t offset)
{ GSM610_PRIVATE *pgsm610 ;
int newblock, newsample ;
mode = mode ;
if (! psf->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
if (psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return ((sf_count_t) -1) ;
} ;
if (offset == 0)
{ int true_flag = 1 ;
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
pgsm610->blockcount = 0 ;
gsm_init (pgsm610->gsm_data) ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_WAV ||
(psf->sf.format & SF_FORMAT_TYPEMASK) == 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 ((sf_count_t) -1) ;
} ;
newblock = offset / pgsm610->samplesperblock ;
newsample = offset % pgsm610->samplesperblock ;
if (psf->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 ((sf_count_t) -1) ;
} /* 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, 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, short *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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, int *ptr, sf_count_t len)
{ GSM610_PRIVATE *pgsm610 ;
short *sptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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, 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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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, 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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pgsm610 = (GSM610_PRIVATE*) psf->fdata ;
if (psf->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 (psf->write_header)
psf->write_header (psf, SF_TRUE) ;
} ;
if (pgsm610->gsm_data)
gsm_destroy (pgsm610->gsm_data) ;
return 0 ;
} /* gsm610_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 8575187d-af4f-4acf-b9dd-6ff705628345
*/

View file

@ -0,0 +1,226 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = htk_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != 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->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->mode == SFM_WRITE || psf->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 ;
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) ;
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->close = htk_close ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: c350e972-082e-4c20-8934-03391a723560
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,306 @@
/*
** Copyright (C) 2002-2004 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 <stdlib.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.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->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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 82314e13-0225-4408-a2f2-e6dab3f38904
*/

View file

@ -0,0 +1,331 @@
/*
** Copyright (C) 2001-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.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 (0x00, 0x02, 0xA3, 0x64))
#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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = ircam_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_IRCAM)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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->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_LE_MASK) != IRCAM_LE_MARKER) &&
((marker & IRCAM_BE_MASK) != IRCAM_BE_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 calc_length)
{ int encoding ;
float samplerate ;
sf_count_t current ;
if (psf->pipeoffset > 0)
return 0 ;
current = psf_ftell (psf) ;
calc_length = calc_length ;
/* This also sets psf->endian. */
encoding = get_encoding (psf->sf.format & SF_FORMAT_SUBMASK) ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f2714ab8-f286-4c94-9740-edaf673a1c71
*/

View file

@ -0,0 +1,37 @@
; Auto-generated by create_symbols_file.py
LIBRARY libsndfile.dll
EXPORTS
sf_command @1
sf_open @2
sf_close @3
sf_seek @4
sf_error @7
sf_perror @8
sf_error_str @9
sf_error_number @10
sf_format_check @11
sf_read_raw @16
sf_readf_short @17
sf_readf_int @18
sf_readf_float @19
sf_readf_double @20
sf_read_short @21
sf_read_int @22
sf_read_float @23
sf_read_double @24
sf_write_raw @32
sf_writef_short @33
sf_writef_int @34
sf_writef_float @35
sf_writef_double @36
sf_write_short @37
sf_write_int @38
sf_write_float @39
sf_write_double @40
sf_strerror @50
sf_get_string @60
sf_set_string @61
sf_open_fd @70

View file

@ -0,0 +1,58 @@
/*
** Copyright (C) 2003,2004 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 "config.h"
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#if (OS_IS_MACOSX == 1)
//#include <CoreServices.h>
int
macbinary3_open (SF_PRIVATE *psf)
{
if (psf)
return 0 ;
return 0 ;
} /* macbinary3_open */
#else
int
macbinary3_open (SF_PRIVATE *psf)
{
psf = psf ;
return 0 ;
} /* macbinary3_open */
#endif /* OS_IS_MACOSX */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: c397a7d7-1a31-4349-9684-bd29ef06211e
*/

View file

@ -0,0 +1,63 @@
/*
** Copyright (C) 2003,2004 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 "config.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 ;
int format ;
psf = psf ;
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 ;
} ;
format = 0 ;
return format ;
} /* macos_guess_file_type */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 5fbf66d7-9547-442a-9c73-92fd164f3a95
*/

View file

@ -0,0 +1,393 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = mat4_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT4)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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->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->mode == SFM_WRITE || psf->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 (psf->sf.format & SF_FORMAT_SUBMASK, 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", 11, samplerate) ;
psf_binheader_writef (psf, "tEm484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
psf_binheader_writef (psf, "E4b", 9, "wavedata", 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", 11, samplerate) ;
psf_binheader_writef (psf, "tem484", encoding, psf->sf.channels, psf->sf.frames, 0) ;
psf_binheader_writef (psf, "e4b", 9, "wavedata", 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, namesize, rows, cols, imag ;
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) ;
LSF_SNPRINTF (psf->u.scbuf, sizeof (psf->u.scbuf), " Value : %f\n", value) ;
psf_log_printf (psf, psf->u.scbuf) ;
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_MAT4_ZERO_CHANNELS ;
} ;
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 ;
LSF_SNPRINTF (str, sizeof (str) - 1, "%08X", marker) ;
return str ;
} /* mat4_marker_to_str */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f7e5f5d6-fc39-452e-bc4a-59627116ff59
*/

View file

@ -0,0 +1,506 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = mat5_read_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_MAT5)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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->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->mode == SFM_WRITE || psf->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 *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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ 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_binheader_writef (psf, "S", "MATLAB 5.0 MAT-file, written by " PACKAGE "-" VERSION ", ") ;
psf_get_date_str (psf->u.scbuf, sizeof (psf->u.scbuf)) ;
psf_binheader_writef (psf, "jS", -1, psf->u.scbuf) ;
memset (psf->u.scbuf, ' ', 124 - psf->headindex) ;
psf_binheader_writef (psf, "b", psf->u.scbuf, 124 - psf->headindex) ;
psf->rwf_endian = psf->endian ;
if (psf->rwf_endian == SF_ENDIAN_BIG)
psf_binheader_writef (psf, "2b", 0x0100, "MI", 2) ;
else
psf_binheader_writef (psf, "2b", 0x0100, "IM", 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, 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, size, flags1, flags2, rows, cols ;
psf_binheader_readf (psf, "pb", 0, psf->u.scbuf, 124) ;
psf->u.scbuf [125] = 0 ;
if (strlen (psf->u.scbuf) >= 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) ;
LSF_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_MAT5_ZERO_CHANNELS ;
} ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: dfdb6742-b2be-4be8-b390-d0c674e8bc8e
*/

View file

@ -0,0 +1,834 @@
/*
** Copyright (C) 1999-2004 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "float_cast.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
unsigned short dummydata [] ; /* ISO C99 struct flexible array. */
#else
unsigned 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, 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, short *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t msadpcm_write_d (SF_PRIVATE *psf, 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->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->fdata = malloc (pmssize)))
return SFE_MALLOC_FAILED ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
memset (pms, 0, pmssize) ;
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 (psf->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, "*** Warning : samplesperblock shoud be %d.\n", count) ;
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->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->seek = msadpcm_seek ;
psf->close = msadpcm_close ;
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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
if (psf->datalength < 0 || psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return ((sf_count_t) -1) ;
} ;
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 ((sf_count_t) -1) ;
} ;
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 ((sf_count_t) -1) ;
} ;
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, "e22", 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, 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, short *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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, int *ptr, sf_count_t len)
{ MSADPCM_PRIVATE *pms ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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, 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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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, 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->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
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 ;
if (! psf->fdata)
return 0 ;
pms = (MSADPCM_PRIVATE*) psf->fdata ;
if (psf->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) ;
if (psf->write_header)
psf->write_header (psf, SF_TRUE) ;
} ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a98908a3-5305-4935-872b-77d6a86c330f
*/

View file

@ -0,0 +1,354 @@
/*
** Copyright (C) 1999-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.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 subformat, error ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = nist_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_NIST)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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 ;
if ((error = nist_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = nist_write_header ;
} ;
psf->close = nist_close ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ 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, bytes = 0, count, encoding ;
char str [64], *cptr ;
long samples ;
psf->sf.format = SF_FORMAT_NIST ;
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 1024\n") != psf_header)
{ psf_log_printf (psf, "Not a NIST file.\n") ;
return SFE_NIST_BAD_HEADER ;
} ;
/* 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)
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 ")))
sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ;
if ((cptr = strstr (psf_header, "sample_rate -i ")))
sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ;
if ((cptr = strstr (psf_header, "sample_count -i ")))
{ sscanf (psf_header, "sample_count -i %ld", &samples) ;
psf->sf.frames = samples ;
} ;
if ((cptr = strstr (psf_header, "sample_n_bytes -i ")))
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%d %8s", &bytes, str) ;
if (bytes > 1)
{ if (psf->bytewidth == 0)
psf->bytewidth = bytes ;
else if (psf->bytewidth != bytes)
{ psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ;
return SFE_NIST_BAD_ENCODING ;
} ;
if (strstr (str, "01") == str)
psf->endian = SF_ENDIAN_LITTLE ;
else if (strstr (str, "10"))
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->dataoffset = NIST_HEADER_LENGTH ;
psf->blockwidth = psf->sf.channels * psf->bytewidth ;
psf->datalength = psf->filelength - psf->dataoffset ;
psf->close = nist_close ;
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 ;
return 0 ;
} /* nist_read_header */
static int
nist_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->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) ;
/* Prevent compiler warning. */
calc_length = calc_length ;
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 (psf->sf.format & SF_FORMAT_SUBMASK)
{ 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: b45ed85d-9e22-4ad9-b78c-4b58b67152a8
*/

View file

@ -0,0 +1,898 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
ogg_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 0) ;
} /* ogg_open */
#else
#define SFE_OGG_NOT_OGG 666
/*------------------------------------------------------------------------------
** Macros to handle big/little endian issues.
*/
#define ALAW_MARKER MAKE_MARKER ('A', 'L', 'a', 'w')
#define SOUN_MARKER MAKE_MARKER ('S', 'o', 'u', 'n')
#define DFIL_MARKER MAKE_MARKER ('d', 'F', 'i', 'l')
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int ogg_read_header (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
ogg_open (SF_PRIVATE *psf)
{ OGG_PRIVATE *pogg ;
int subformat, error = 0 ;
if (psf->mode == SFM_RDWR)
return SFE_UNIMPLEMENTED ;
psf->sf.sections = 1 ;
psf->datalength = psf->filelength ;
psf->dataoffset = 0 ;
psf->blockwidth = 0 ;
psf->bytewidth = 1 ;
if (! (pogg = calloc (1, sizeof (OGG_PRIVATE))))
return SFE_MALLOC_FAILED ;
psf->fdata = pogg ;
if (psf->mode == SFM_READ)
{ if ((error = pogg_read_header (psf)))
return error ;
} ;
if (psf->mode == SFM_WRITE)
{ psf->str_flags = SF_STR_ALLOW_START ;
if ((error = pogg_write_header (psf)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) == 0)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (subformat == 0)
return SFE_BAD_OPEN_FORMAT ;
return pogg_init (psf) ;
} /* ogg_open */
/*------------------------------------------------------------------------------
** Private functions
*/
static int
pogg_init (SF_PRIVATE * psf)
{
psf->close = pogg_close ;
if (psf->mode == SFM_READ)
{ /* set the virtual functions for reading */
psf->read_short = pogg_read_s ;
psf->read_int = pogg_read_i ;
psf->read_float = pogg_read_f ;
psf->read_double = pogg_read_d ;
/* set the virtual function for seeking */
psf->seek = pogg_seek ;
} ;
if (psf->mode == SFM_WRITE)
{ /* set the virtual functions for writing */
psf->write_short = pogg_write_s ;
psf->write_int = pogg_write_i ;
psf->write_float = pogg_write_f ;
psf->write_double = pogg_write_d ;
} ;
return 0 ;
} /* pogg_init */
static int
pogg_close (SF_PRIVATE * psf)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
long n ;
if (psf->mode == SFM_READ)
{ if (pogg->cache_pcm != NULL)
free (pogg->cache_pcm) ;
/* MUST NOT free pogg->ptr, it is a pointer into the user's buffers */
} ;
if (psf->mode == SFM_WRITE)
{ fish_sound_flush (pogg->fsound) ;
while ((n = oggz_write (pogg->oggz, 1024)) > 0) ;
} ;
if (pogg->oggz)
oggz_close (pogg->oggz) ;
if (pogg->fsound)
fish_sound_delete (pogg->fsound) ;
return 0 ;
} /* pogg_close */
/*------------------------------------------------------------------------------
** OggzIO methods
*/
static size_t
pogg_io_read (void * user_handle, void * buf, size_t n)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;
return (size_t) psf_fread (buf, 1, n, psf) ;
} /* pogg_io_read */
static int
pogg_io_seek (void * user_handle, long offset, int whence)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;
return (size_t) psf_fseek (psf, offset, whence) ;
} /* pogg_io_seek */
static long
pogg_io_tell (void * user_handle)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;
return (size_t) psf_ftell (psf) ;
} /* pogg_io_tell */
static size_t
pogg_io_write (void * user_handle, void * buf, size_t n)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_handle ;
return (size_t) psf_fwrite (buf, 1, n, psf) ;
} /* pogg_io_write */
/*------------------------------------------------------------------------------
** Read last packet -- set the number of frames to be the last recorded
** granulepos.
*/
static int
pogg_read_last_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * data)
{ SF_PRIVATE * psf = (SF_PRIVATE *) data ;
/* Avoid compiler warning. */
oggz = NULL ;
serialno = 0 ;
if (op->granulepos == -1)
return OGGZ_CONTINUE ;
psf->sf.frames = op->granulepos ;
return OGGZ_STOP_OK ;
} /* pogg_read_least_packet */
/*------------------------------------------------------------------------------
** Decode header -- by the time FishSound calls this, all header codebooks etc.
** have been parsed and the Oggz is ready for seeking.
*/
static int
pogg_decode_header (FishSound * fsound, float ** pcm, long frames, void * user_data)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_data ;
FishSoundInfo fsinfo ;
const FishSoundComment * comment ;
/* Avoid compiler warnings. */
pcm = NULL ;
frames = 0 ;
fish_sound_command (fsound, FISH_SOUND_GET_INFO, &fsinfo, sizeof (FishSoundInfo)) ;
switch (fsinfo.format)
{ case FISH_SOUND_VORBIS :
psf_log_printf (psf, "Vorbis\n") ;
psf->sf.format |= SF_FORMAT_VORBIS ;
break ;
case FISH_SOUND_SPEEX :
psf_log_printf (psf, "Speex\n") ;
psf->sf.format |= SF_FORMAT_SPEEX ;
break ;
default :
psf_log_printf (psf, "Unknown Ogg codec\n") ;
break ;
} ;
psf->sf.samplerate = fsinfo.samplerate ;
psf->sf.channels = fsinfo.channels ;
/* Get comments */
for (comment = fish_sound_comment_first (fsound) ; comment ;
comment = fish_sound_comment_next (fsound, comment))
{ psf_log_printf (psf, "%s : %s\n", comment->name, comment->value) ;
if (strcasecmp (comment->name, "TITLE") == 0)
psf_store_string (psf, SF_STR_TITLE, comment->value) ;
else if (strcasecmp (comment->name, "COPYRIGHT") == 0)
psf_store_string (psf, SF_STR_COPYRIGHT, comment->value) ;
else if (strcasecmp (comment->name, "ENCODER") == 0)
psf_store_string (psf, SF_STR_SOFTWARE, comment->value) ;
else if (strcasecmp (comment->name, "ARTIST") == 0)
psf_store_string (psf, SF_STR_ARTIST, comment->value) ;
else if (strcasecmp (comment->name, "DATE") == 0)
psf_store_string (psf, SF_STR_DATE, comment->value) ;
else if (strcasecmp (comment->name, "author") == 0)
{ /* speexenc provides this */
psf_store_string (psf, SF_STR_ARTIST, comment->value) ;
} ;
} ;
puts (psf->logbuffer) ;
return 1 ;
} /* pogg_decode_header */
static int
pogg_read_header_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * data)
{ SF_PRIVATE * psf = (SF_PRIVATE *) data ;
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
int format ;
/* Avoid compiler warning. */
oggz = NULL ;
if (pogg->serialno == -1)
psf_log_printf (psf, "Read Ogg packet header : [%s]\n", op->packet) ;
if (pogg->serialno == -1 && op->bytes >= 8)
{ format = fish_sound_identify (op->packet, 8) ;
if (format == FISH_SOUND_VORBIS || format == FISH_SOUND_SPEEX)
{ /*
** Detect this is (probably) the audio stream. Don't set the subformat
** yet, do that in the decoded callback, once FishSound has had a proper
** look at all the headers and codebooks etc. and the file is ready for
** decoding and seeking. We use the value of (psf->sf.format & _SUBMASK)
** below to determine whether the headers have all been read or not.
*/
pogg->serialno = serialno ;
}
else if (strncmp (op->packet, "Annodex", 8) == 0)
{ /* The overall stream encpasulation is Annodex */
psf->sf.format = SF_FORMAT_ANX ;
} ;
} ;
if (serialno == pogg->serialno)
fish_sound_decode (pogg->fsound, op->packet, op->bytes) ;
if ((psf->sf.format & SF_FORMAT_SUBMASK) == 0)
return OGGZ_CONTINUE ;
return OGGZ_STOP_OK ;
} /* pogg_read_header_packet */
static int
pogg_read_header (SF_PRIVATE *psf)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
unsigned char buf [1024] ;
OGGZ * oggz ;
FishSound * fsound ;
FishSoundInfo fsinfo ;
int nread = 1024 ;
psf->sf.format = SF_FORMAT_OGG ;
psf->sf.frames = 0 ;
oggz = oggz_new (OGGZ_READ|OGGZ_AUTO) ;
oggz_io_set_read (oggz, pogg_io_read, psf) ;
oggz_io_set_seek (oggz, pogg_io_seek, psf) ;
oggz_io_set_tell (oggz, pogg_io_tell, psf) ;
fsound = fish_sound_new (FISH_SOUND_DECODE, &fsinfo) ;
fish_sound_set_interleave (fsound, 1) ;
fish_sound_set_decoded_callback (fsound, pogg_decode_header, psf) ;
pogg->oggz = oggz ;
pogg->fsound = fsound ;
pogg->serialno = -1 ;
pogg->cache_pcm = NULL ;
pogg->cache_size = 0 ;
pogg->cache_granulepos = 0 ; /* We set this to a known value of zero to begin */
pogg->cache_frames = 0 ;
pogg->cache_remaining = 0 ;
pogg->ptr = NULL ;
pogg->pcmtype = POGG_PCM_SHORT ;
pogg->remaining = 0 ;
pogg->seek_from_start = 0 ;
/* Set position to start of file to begin reading header. */
psf_binheader_readf (psf, "p", 0) ;
/* Get the header info */
oggz_set_read_callback (oggz, -1, pogg_read_header_packet, psf) ;
while (nread > 0 && ((psf->sf.format & SF_FORMAT_SUBMASK) == 0))
{ nread = psf_binheader_readf (psf, "b", buf, sizeof (buf)) ;
oggz_read_input (oggz, buf, nread) ;
} ;
/* Get the duration */
oggz_set_read_callback (oggz, -1, NULL, NULL) ;
oggz_set_read_callback (oggz, pogg->serialno, pogg_read_last_packet, psf) ;
oggz_seek_units (oggz, 0, SEEK_END) ;
nread = 1024 ;
while (nread > 0)
nread = oggz_read (oggz, 1024) ;
/* reset to the beginning of the audio data */
oggz_seek_units (oggz, 0, SEEK_SET) ;
psf->dataoffset = oggz_tell (oggz) ;
psf->datalength = psf->filelength - psf->dataoffset ;
/* set the Oggz and FishSound up for decoding */
oggz_set_read_callback (oggz, -1, NULL, NULL) ;
oggz_set_read_callback (oggz, pogg->serialno, pogg_read_packet, psf) ;
fish_sound_set_decoded_callback (fsound, pogg_decode, psf) ;
return 0 ;
} /* pogg_read_header */
/*------------------------------------------------------------------------------
** Decode functions
*/
static int
pogg_copyout (SF_PRIVATE * psf)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
size_t frame_size, bytes, cache_offset ;
long cache_usable, i ;
unsigned char * src ;
if (pogg->seek_from_start > 0)
{ /* If we've seeked and don't know where we are, don't do anything yet */
if (pogg->cache_granulepos == -1)
return -1 ;
/* If we've seeked and are before the seek point, don't do anything yet */
else if (pogg->cache_granulepos < pogg->seek_from_start)
return -1 ;
/* If this block contains the seek point, adjust the cache offset accordingly */
else if (pogg->cache_granulepos - pogg->cache_frames <= pogg->seek_from_start)
{ pogg->cache_remaining = pogg->cache_granulepos - pogg->seek_from_start ;
pogg->seek_from_start = 0 ; /* bingo */
} ;
} ;
frame_size = psf->sf.channels * sizeof (float) ;
cache_usable = SF_MIN (pogg->remaining, pogg->cache_remaining) ;
if (cache_usable <= 0)
return 0 ;
bytes = cache_usable * frame_size ;
cache_offset = (pogg->cache_frames - pogg->cache_remaining) * frame_size ;
src = (unsigned char *) pogg->cache_pcm + cache_offset ;
switch (pogg->pcmtype)
{ case POGG_PCM_SHORT :
for (i = 0 ; i < cache_usable ; i++)
((short *) pogg->ptr) [i] = (short) (((float *) src) [i] * SHRT_MAX) ;
break ;
case POGG_PCM_INT :
for (i = 0 ; i < cache_usable ; i++)
((double *) pogg->ptr) [i] = (double) (((float *) src) [i] * INT_MAX) ;
break ;
case POGG_PCM_FLOAT :
memcpy (pogg->ptr, src, bytes) ;
break ;
case POGG_PCM_DOUBLE :
for (i = 0 ; i < cache_usable ; i++)
((double *) pogg->ptr) [i] = (double) ((float *) src) [i] ;
break ;
} ;
pogg->ptr += bytes ;
pogg->cache_remaining -= cache_usable ;
pogg->remaining -= cache_usable ;
return 0 ;
} /* pogg_copyout*/
static int
pogg_decode (FishSound * fsound, float ** pcm, long frames, void * user_data)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_data ;
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
size_t bytes ;
float ** new_block ;
/* Avoid compiler warning. */
fsound = NULL ;
bytes = sizeof (float) * psf->sf.channels * frames ;
if (bytes > pogg->cache_size)
{ new_block = realloc (pogg->cache_pcm, bytes) ;
if (new_block == NULL)
/* XXX : SFE_MALLOC_FAILED */
return -1 ;
pogg->cache_pcm = new_block ;
pogg->cache_size = bytes ;
} ;
memcpy (pogg->cache_pcm, pcm, bytes) ;
pogg->cache_frames = frames ;
pogg->cache_remaining = frames ;
if (pogg->cache_granulepos != -1)
pogg->cache_granulepos += frames ;
pogg_copyout (psf) ;
return 0 ;
} /* pogg_decode */
static int
pogg_read_packet (OGGZ * oggz, ogg_packet * op, long serialno, void * data)
{ SF_PRIVATE * psf = (SF_PRIVATE *) data ;
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
FishSound * fsound = pogg->fsound ;
/* Avoid warning message. */
oggz = NULL ;
serialno = 0 ;
fish_sound_decode (fsound, op->packet, op->bytes) ;
if (op->granulepos != -1)
pogg->cache_granulepos = op->granulepos ;
if (pogg->remaining == 0)
return OGGZ_STOP_OK ;
return OGGZ_CONTINUE ;
} /* pogg_read_packet */
static sf_count_t
pogg_read_loop (SF_PRIVATE *psf, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
long nread = 1024 ;
sf_count_t ret = len ;
/** Calculate nr. frames remaining */
pogg->remaining = len / psf->sf.channels ;
/** Serve out any remaining cached data first */
pogg_copyout (psf) ;
while (nread > 0 && pogg->remaining > 0)
nread = oggz_read (pogg->oggz, 1024) ;
if (nread == 0)
ret -= pogg->remaining * psf->sf.channels ;
return ret ;
} /* pogg_read_loop */
static sf_count_t
pogg_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
pogg->ptr = ptr ;
pogg->pcmtype = POGG_PCM_SHORT ;
return pogg_read_loop (psf, len) ;
} /* pogg_read_s */
static sf_count_t
pogg_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
pogg->ptr = ptr ;
pogg->pcmtype = POGG_PCM_INT ;
return pogg_read_loop (psf, len) ;
} /* pogg_read_i */
static sf_count_t
pogg_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
pogg->ptr = ptr ;
pogg->pcmtype = POGG_PCM_FLOAT ;
return pogg_read_loop (psf, len) ;
} /* pogg_read_f */
static sf_count_t
pogg_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
pogg->ptr = ptr ;
pogg->pcmtype = POGG_PCM_DOUBLE ;
return pogg_read_loop (psf, len) ;
} /* pogg_read_d */
/*------------------------------------------------------------------------------
** Seek functions
*/
static sf_count_t
pogg_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
ogg_int64_t units = seek_from_start * 1000 / psf->sf.samplerate ;
if (mode != SFM_READ)
{ psf->error = SFE_BAD_SEEK ;
return SF_SEEK_ERROR ;
} ;
oggz_seek_units (pogg->oggz, units, SEEK_SET) ;
/* Invalidate cache and set the desired seek position */
pogg->cache_remaining = 0 ;
pogg->cache_granulepos = -1 ;
pogg->seek_from_start = seek_from_start ;
return seek_from_start ;
} /* pogg_seek */
/*------------------------------------------------------------------------------
** Write functions
*/
static int
pogg_encoded (FishSound * fsound, unsigned char * buf, long bytes, void * user_data)
{ SF_PRIVATE * psf = (SF_PRIVATE *) user_data ;
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
ogg_packet op ;
int err ;
op.packet = buf ;
op.bytes = bytes ;
op.b_o_s = pogg->b_o_s ;
op.e_o_s = 0 ;
op.granulepos = fish_sound_get_frameno (fsound) ;
op.packetno = -1 ;
err = oggz_write_feed (pogg->oggz, &op, pogg->serialno, 0, NULL) ;
pogg->b_o_s = 0 ;
return OGGZ_CONTINUE ;
} /* pogg_encoded */
static int
pogg_write_anx_headers (SF_PRIVATE *psf, int format)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
unsigned char buf [128] ;
long anx_serialno ;
int headers_len = 0 ;
const char * content_type ;
ogg_packet op ;
int err ;
anx_serialno = oggz_serialno_new (pogg->oggz) ;
/* Write Annodex header */
memset (buf, 0, 48) ;
snprintf (buf, 8, "Annodex") ;
/* Version */
*(ogg_int16_t *) &buf [8] = (ogg_int16_t) POGG_ANX_VERSION_MAJOR ;
*(ogg_int16_t *) &buf [10] = (ogg_int16_t) POGG_ANX_VERSION_MINOR ;
if (CPU_IS_BIG_ENDIAN)
endswap_short_array ((short *) &buf [8], 2) ;
/* Timebase numerator */
*(ogg_int64_t *) &buf [12] = (ogg_int64_t) 0 ;
/* Timebase denominator */
*(ogg_int64_t *) &buf [20] = (ogg_int64_t) 1 ;
if (CPU_IS_BIG_ENDIAN)
endswap_long_array ((long *) &buf [12], 2) ;
op.packet = buf ;
op.bytes = 48 ;
op.b_o_s = 1 ;
op.e_o_s = 0 ;
op.granulepos = 0 ;
op.packetno = -1 ;
err = oggz_write_feed (pogg->oggz, &op, anx_serialno, 0, NULL) ;
pogg->b_o_s = 0 ;
/* Write AnxData header */
memset (buf, 0, 48) ;
snprintf (buf, 8, "AnxData") ;
/* Granule rate numerator */
*(ogg_int64_t *) &buf [8] = (ogg_int64_t) psf->sf.samplerate ;
/* Granule rate denominator */
*(ogg_int64_t *) &buf [16] = (ogg_int64_t) 1 ;
if (CPU_IS_BIG_ENDIAN)
endswap_long_array ((long *) &buf [8], 2) ;
/* Number of secondary header pages */
*(ogg_int32_t *) &buf [24] = (ogg_int32_t) 3 ;
if (CPU_IS_BIG_ENDIAN)
endswap_int_array ((int *) &buf [24], 1) ;
/* Headers */
if (format == FISH_SOUND_VORBIS)
content_type = POGG_VORBIS_CONTENT_TYPE ;
else
content_type = POGG_SPEEX_CONTENT_TYPE ;
headers_len = snprintf ((char *) &buf [28], 100, "Content-Type : %s\r\n", content_type) ;
op.packet = buf ;
op.bytes = 28 + headers_len + 1 ;
op.b_o_s = 1 ;
op.e_o_s = 0 ;
op.granulepos = 0 ;
op.packetno = -1 ;
err = oggz_write_feed (pogg->oggz, &op, pogg->serialno, 0, NULL) ;
/* Write Annodex eos packet */
op.packet = NULL ;
op.bytes = 0 ;
op.b_o_s = 0 ;
op.e_o_s = 1 ;
op.granulepos = 0 ;
op.packetno = -1 ;
err = oggz_write_feed (pogg->oggz, &op, anx_serialno, 0, NULL) ;
return 0 ;
} /* pogg_write_anx_headers */
static int
pogg_write_header (SF_PRIVATE *psf)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
OGGZ * oggz ;
FishSound * fsound ;
FishSoundInfo fsinfo ;
oggz = oggz_new (OGGZ_WRITE) ;
oggz_io_set_write (oggz, pogg_io_write, psf) ;
fsinfo.samplerate = psf->sf.samplerate ;
fsinfo.channels = psf->sf.channels ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_VORBIS :
fsinfo.format = FISH_SOUND_VORBIS ;
break ;
case SF_FORMAT_SPEEX :
fsinfo.format = FISH_SOUND_SPEEX ;
break ;
} ;
fsound = fish_sound_new (FISH_SOUND_ENCODE, &fsinfo) ;
fish_sound_set_interleave (fsound, 1) ;
fish_sound_set_encoded_callback (fsound, pogg_encoded, psf) ;
pogg->oggz = oggz ;
pogg->fsound = fsound ;
pogg->serialno = oggz_serialno_new (oggz) ;
pogg->b_o_s = 1 ;
pogg->comments_written = 0 ;
pogg->granulepos = 0 ;
pogg->fptr = (float *) malloc (sizeof (float) * 1024) ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) == SF_FORMAT_ANX)
pogg_write_anx_headers (psf, fsinfo.format) ;
return 0 ;
} /* pogg_write_header */
static void
pogg_write_comments (SF_PRIVATE *psf)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
int k ;
int err ;
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
{ printf ("hrumf comment : %d => %s\n", psf->strings [k].type, psf->strings [k].str) ;
/*
if (psf->strings [k].type == 0)
break ;
*/
if (psf->strings [k].type != 0)
{ printf ("adding comment : %d => %s\n", psf->strings [k].type, psf->strings [k].str) ;
switch (psf->strings [k].type)
{ case SF_STR_SOFTWARE :
err = fish_sound_comment_add_byname (pogg->fsound, "ENCODER", psf->strings [k].str) ;
break ;
case SF_STR_TITLE :
err = fish_sound_comment_add_byname (pogg->fsound, "TITLE", psf->strings [k].str) ;
break ;
case SF_STR_COPYRIGHT :
err = fish_sound_comment_add_byname (pogg->fsound, "COPYRIGHT", psf->strings [k].str) ;
break ;
case SF_STR_ARTIST :
err = fish_sound_comment_add_byname (pogg->fsound, "ARTIST", psf->strings [k].str) ;
break ;
/*
case SF_STR_COMMENT :
fish_sound_comment_add_byname (pogg->fsound, "COMMENT", psf->strings [k].str) ;
break ;
*/
case SF_STR_DATE :
err = fish_sound_comment_add_byname (pogg->fsound, "DATE", psf->strings [k].str) ;
break ;
} ;
} ; /* if type !0 */
} ;
pogg->comments_written = 1 ;
return ;
} /* pogg_write_comments*/
static sf_count_t
pogg_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
long n, i, remaining = len / psf->sf.channels ;
if (pogg->comments_written == 0)
pogg_write_comments (psf) ;
while (remaining > 0)
{ n = SF_MIN (remaining, 1024) ;
for (i = 0 ; i < n * psf->sf.channels ; i++)
pogg->fptr [i] = (float) ptr [i] ;
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
while (oggz_write (pogg->oggz, 1024) > 0) ;
ptr += n * psf->sf.channels ;
remaining -= n ;
} ;
return len ;
} /* pogg_write_s */
static sf_count_t
pogg_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{
OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
long n, i, remaining = len / psf->sf.channels ;
if (pogg->comments_written == 0)
pogg_write_comments (psf) ;
while (remaining > 0)
{ n = SF_MIN (remaining, 1024) ;
for (i = 0 ; i < n * psf->sf.channels ; i++)
pogg->fptr [i] = (float) ptr [i] ;
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
while (oggz_write (pogg->oggz, 1024) > 0) ;
ptr += n * psf->sf.channels ;
remaining -= n ;
} ;
return len ;
} /* pogg_write_i */
static sf_count_t
pogg_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
long n, remaining = len / psf->sf.channels ;
if (pogg->comments_written == 0)
pogg_write_comments (psf) ;
while (remaining > 0)
{ n = SF_MIN (remaining, 1024) ;
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
while (oggz_write (pogg->oggz, 1024) > 0) ;
ptr += n * psf->sf.channels ;
remaining -= n ;
} ;
return len ;
} /* pog_write_f */
static sf_count_t
pogg_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ OGG_PRIVATE * pogg = (OGG_PRIVATE *) psf->fdata ;
long n, i, remaining = len / psf->sf.channels ;
if (pogg->comments_written == 0)
pogg_write_comments (psf) ;
while (remaining > 0)
{ n = SF_MIN (remaining, 1024) ;
for (i = 0 ; i < n * psf->sf.channels ; i++)
pogg->fptr [i] = (float) ptr [i] ;
fish_sound_encode (pogg->fsound, (float **) ptr, n) ;
while (oggz_write (pogg->oggz, 1024) > 0) ;
ptr += n * psf->sf.channels ;
remaining -= n ;
} ;
return len ;
} /* pogg_write_d */
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 9ff1fe9c-629e-4e9c-9ef5-3d0eb1e427a0
*/

View file

@ -0,0 +1,847 @@
/*
** Copyright (C) 1999-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "float_cast.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, short *ptr, sf_count_t len) ;
static sf_count_t paf24_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t paf24_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t paf24_write_d (SF_PRIVATE *psf, 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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = paf_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_PAF)
return SFE_BAD_OPEN_FORMAT ;
endian = psf->sf.format & SF_FORMAT_ENDMASK ;
/* 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 ;
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 (psf->filelength < PAF_HEADER_LENGTH)
return SFE_PAF_SHORT_HEADER ;
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 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 ;
psf->dataoffset = PAF_HEADER_LENGTH ;
/* Prevent compiler warning. */
calc_length = calc_length ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ 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, max_blocks ;
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->fdata = malloc (paf24size)))
return SFE_MALLOC_FAILED ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
memset (ppaf24, 0, paf24size) ;
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->mode == SFM_READ || psf->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->mode == SFM_WRITE || psf->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->close = paf24_close ;
psf->filelength = psf_get_filelen (psf) ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (psf->datalength % PAF24_BLOCK_SIZE)
{ if (psf->mode == SFM_READ)
psf_log_printf (psf, "*** Warning : file seems to be truncated.\n") ;
max_blocks = psf->datalength / ppaf24->blocksize + 1 ;
}
else
max_blocks = psf->datalength / ppaf24->blocksize ;
ppaf24->read_block = 0 ;
if (psf->mode == SFM_RDWR)
ppaf24->write_block = max_blocks ;
else
ppaf24->write_block = 0 ;
psf->sf.frames = ppaf24->samplesperblock * 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->fdata == NULL)
{ psf->error = SFE_INTERNAL ;
return SF_SEEK_ERROR ;
} ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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 (offset > ppaf24->read_block * ppaf24->samplesperblock + ppaf24->read_count)
{ psf->error = SFE_BAD_SEEK ;
return SF_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->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 SF_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 SF_SEEK_ERROR ;
} ;
return newblock * ppaf24->samplesperblock + newsample ;
} /* paf24_seek */
static int
paf24_close (SF_PRIVATE *psf)
{ PAF24_PRIVATE *ppaf24 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
if (psf->mode == SFM_WRITE || psf->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->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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, 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, short *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int *iptr ;
int k, bufferlen, writecount = 0, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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, int *ptr, sf_count_t len)
{ PAF24_PRIVATE *ppaf24 ;
int writecount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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, 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->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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, 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->fdata == NULL)
return 0 ;
ppaf24 = (PAF24_PRIVATE*) psf->fdata ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 477a5308-451e-4bbd-bab4-fab6caa4e884
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,200 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.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->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = pvf_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != 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->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 *psf)
{
psf = psf ;
return 0 ;
} /* pvf_close */
static int
pvf_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
if (psf->pipeoffset > 0)
return 0 ;
calc_length = calc_length ; /* Avoid a compiler warning. */
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) ;
LSF_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 ;
psf->close = pvf_close ;
if (! psf->sf.frames && psf->blockwidth)
psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ;
return 0 ;
} /* pvf_read_header */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 20a26761-8bc1-41d7-b1f3-9793bf3d9864
*/

View file

@ -0,0 +1,110 @@
/*
** Copyright (C) 1999-2004 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 <stdio.h>
#include "sndfile.h"
#include "config.h"
#include "common.h"
/*------------------------------------------------------------------------------
** Public function.
*/
int
raw_open (SF_PRIVATE *psf)
{ int subformat, error = SFE_NO_ERROR ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f0066de7-d6ce-4f36-a1e0-e475c07d4e1a
*/

View file

@ -0,0 +1,325 @@
/*
** Copyright (C) 2001-2004 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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdarg.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
rx2_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 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->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->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
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 7366e813-9fee-4d1f-881e-e4a691469370
*/

View file

@ -0,0 +1,572 @@
/*
** Copyright (C) 2001-2004 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.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 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 saved_filedes, subformat, error = 0 ;
/* SD2 is always big endian. */
psf->endian = SF_ENDIAN_BIG ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->rsrclength > 0))
{ if (psf->rsrcdes < 0)
{ psf_log_printf (psf, "sd2_open : psf->rsrcdes < 0\n") ;
return SFE_SD2_BAD_RSRC ;
} ;
saved_filedes = psf->filedes ;
psf->filedes = psf->rsrcdes ;
error = sd2_parse_rsrc_fork (psf) ;
psf->filedes = saved_filedes ;
if (error)
goto error_cleanup ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SD2)
{ error = SFE_BAD_OPEN_FORMAT ;
goto error_cleanup ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
psf->dataoffset = 0 ;
/* Only open and write the resource in RDWR mode is its current length is zero. */
if (psf->mode == SFM_WRITE || (psf->mode == SFM_RDWR && psf->rsrclength == 0))
{ psf_open_rsrc (psf, psf->mode) ;
saved_filedes = psf->filedes ;
psf->filedes = psf->rsrcdes ;
error = sd2_write_rsrc_fork (psf, SF_FALSE) ;
psf->filedes = saved_filedes ;
if (error)
goto error_cleanup ;
/* Not needed. */
psf->write_header = NULL ;
} ;
psf->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->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 void
write_str (unsigned char * data, int offset, 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 ;
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) ;
LSF_SNPRINTF (str_rsrc [0].value, sizeof (str_rsrc [0].value), "_%d", rsrc.sample_size) ;
LSF_SNPRINTF (str_rsrc [1].value, sizeof (str_rsrc [1].value), "_%d.000000", rsrc.sample_rate) ;
LSF_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->filename)) ;
write_str (rsrc.rsrc_data, 0x31, psf->filename, strlen (psf->filename)) ;
write_short (rsrc.rsrc_data, 0x50, 0) ;
write_int (rsrc.rsrc_data, 0x52, Sd2f_MARKER) ;
write_int (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_int (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_int (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) ;
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_char */
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_char */
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 (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 ;
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) ;
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) ;
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 > len\n") ;
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 ;
} ;
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_int (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 :
if ((void *) rsrc.rsrc_data < (void *) psf || (void *) rsrc.rsrc_data > (void *) (psf + 1))
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, data_offset, data_len, rsrc_id ;
psf_log_printf (psf, "Finding parameters :\n") ;
str_offset = rsrc->string_offset ;
for (k = 0 ; k < rsrc->str_count ; 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, "Bad data offset (%d)\n", data_offset) ;
return SFE_SD2_BAD_DATA_OFFSET ;
} ;
data_len = read_int (rsrc->rsrc_data, data_offset) ;
if (data_len < 0 || data_len > rsrc->rsrc_len)
{ psf_log_printf (psf, "Bad data length (%d).\n", data_len) ;
return SFE_SD2_BAD_RSRC ;
} ;
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, " %-12s 0x%04x %4d %2d %2d '%s'\n", name, data_offset, rsrc_id, data_len, slen, value) ;
if (strcmp (name, "sample-size") == 0 && rsrc->sample_size == 0)
rsrc->sample_size = strtol (value, NULL, 10) ;
else if (strcmp (name, "sample-rate") == 0 && rsrc->sample_rate == 0)
rsrc->sample_rate = strtol (value, NULL, 10) ;
else if (strcmp (name, "channels") == 0 && rsrc->channels == 0)
rsrc->channels = strtol (value, NULL, 10) ;
} ;
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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 1ee183e5-6b9f-4c2c-bd0a-24f35595cefc
*/

View file

@ -0,0 +1,995 @@
/*
** Copyright (C) 2002-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#include "float_cast.h"
/*------------------------------------------------------------------------------
*/
#define SDS_DATA_OFFSET 0x15
#define SDS_BLOCK_SIZE 127
#define SDS_AUDIO_BYTES_PER_BLOCK 120
#define SDS_3BYTE_TO_INT_DECODE(x) (((x) & 0x7F) | (((x) & 0x7F00) >> 1) | (((x) & 0x7F0000) >> 2))
#define SDS_INT_TO_3BYTE_ENCODE(x) (((x) & 0x7F) | (((x) << 1) & 0x7F00) | (((x) << 2) & 0x7F0000))
/*------------------------------------------------------------------------------
** Typedefs.
*/
typedef struct tag_SDS_PRIVATE
{ int bitwidth, frames ;
int samplesperblock, total_blocks ;
int (*reader) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;
int (*writer) (SF_PRIVATE *psf, struct tag_SDS_PRIVATE *psds) ;
int read_block, read_count ;
unsigned char read_data [SDS_BLOCK_SIZE] ;
int read_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
int write_block, write_count ;
unsigned char write_data [SDS_BLOCK_SIZE] ;
int write_samples [SDS_BLOCK_SIZE / 2] ; /* Maximum samples per block */
} SDS_PRIVATE ;
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int sds_close (SF_PRIVATE *psf) ;
static int sds_write_header (SF_PRIVATE *psf, int calc_length) ;
static int sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static sf_count_t sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t sds_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t sds_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t sds_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t sds_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t sds_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
static int sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int readcount) ;
static int sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds) ;
static int sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *iptr, int writecount) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
sds_open (SF_PRIVATE *psf)
{ SDS_PRIVATE *psds ;
int subformat, error = 0 ;
/* Hmmmm, need this here to pass update_header_test. */
psf->sf.frames = 0 ;
if (! (psds = calloc (1, sizeof (SDS_PRIVATE))))
return SFE_MALLOC_FAILED ;
psf->fdata = psds ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = sds_read_header (psf, psds)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SDS)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (sds_write_header (psf, SF_FALSE))
return psf->error ;
psf->write_header = sds_write_header ;
psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;
} ;
if ((error = sds_init (psf, psds)) != 0)
return error ;
psf->seek = sds_seek ;
psf->close = sds_close ;
psf->blockwidth = 0 ;
return error ;
} /* sds_open */
/*------------------------------------------------------------------------------
*/
static int
sds_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ SDS_PRIVATE *psds ;
if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL)
{ psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ;
return SFE_INTERNAL ;
} ;
if (psds->write_count > 0)
{ memset (&(psds->write_data [psds->write_count]), 0, (psds->samplesperblock - psds->write_count) * sizeof (int)) ;
psds->writer (psf, psds) ;
} ;
sds_write_header (psf, SF_TRUE) ;
} ;
return 0 ;
} /* sds_close */
static int
sds_init (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{
if (psds->bitwidth < 8 || psds->bitwidth > 28)
return (psf->error = SFE_SDS_BAD_BIT_WIDTH) ;
if (psds->bitwidth < 14)
{ psds->reader = sds_2byte_read ;
psds->writer = sds_2byte_write ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 2 ;
}
else if (psds->bitwidth < 21)
{ psds->reader = sds_3byte_read ;
psds->writer = sds_3byte_write ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 3 ;
}
else
{ psds->reader = sds_4byte_read ;
psds->writer = sds_4byte_write ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / 4 ;
} ;
if (psf->mode == SFM_READ || psf->mode == SFM_RDWR)
{ psf->read_short = sds_read_s ;
psf->read_int = sds_read_i ;
psf->read_float = sds_read_f ;
psf->read_double = sds_read_d ;
/* Read first block. */
psds->reader (psf, psds) ;
} ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ psf->write_short = sds_write_s ;
psf->write_int = sds_write_i ;
psf->write_float = sds_write_f ;
psf->write_double = sds_write_d ;
} ;
return 0 ;
} /* sds_init */
static int
sds_read_header (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char channel, bitwidth, loop_type, byte ;
unsigned short sample_no, marker ;
unsigned int samp_period, data_length, sustain_loop_start, sustain_loop_end ;
int bytesread, blockcount ;
/* Set position to start of file to begin reading header. */
bytesread = psf_binheader_readf (psf, "pE211", 0, &marker, &channel, &byte) ;
if (marker != 0xF07E || byte != 0x01)
return SFE_SDS_NOT_SDS ;
psf_log_printf (psf, "Midi Sample Dump Standard (.sds)\nF07E\n Midi Channel : %d\n", channel) ;
bytesread += psf_binheader_readf (psf, "e213", &sample_no, &bitwidth, &samp_period) ;
sample_no = SDS_3BYTE_TO_INT_DECODE (sample_no) ;
samp_period = SDS_3BYTE_TO_INT_DECODE (samp_period) ;
psds->bitwidth = bitwidth ;
psf->sf.samplerate = 1000000000 / samp_period ;
psf_log_printf (psf, " Sample Number : %d\n"
" Bit Width : %d\n"
" Sample Rate : %d\n",
sample_no, psds->bitwidth, psf->sf.samplerate) ;
bytesread += psf_binheader_readf (psf, "e3331", &data_length, &sustain_loop_start, &sustain_loop_end, &loop_type) ;
data_length = SDS_3BYTE_TO_INT_DECODE (data_length) ;
sustain_loop_start = SDS_3BYTE_TO_INT_DECODE (sustain_loop_start) ;
sustain_loop_end = SDS_3BYTE_TO_INT_DECODE (sustain_loop_end) ;
psf_log_printf (psf, " Sustain Loop\n"
" Start : %d\n"
" End : %d\n"
" Loop Type : %d\n",
sustain_loop_start, sustain_loop_end, loop_type) ;
psf->dataoffset = SDS_DATA_OFFSET ;
psf->datalength = psf->filelength - psf->dataoffset ;
if (data_length != psf->filelength - psf->dataoffset)
{ psf_log_printf (psf, " Datalength : %d (truncated data??? %d)\n", data_length, psf->filelength - psf->dataoffset) ;
data_length = psf->filelength - psf->dataoffset ;
}
else
psf_log_printf (psf, " Datalength : %d\n", data_length) ;
bytesread += psf_binheader_readf (psf, "1", &byte) ;
if (byte != 0xF7)
psf_log_printf (psf, "bad end : %X\n", byte & 0xFF) ;
for (blockcount = 0 ; bytesread < psf->filelength ; blockcount++)
{
bytesread += psf_fread (&marker, 1, 2, psf) ;
if (marker == 0)
break ;
psf_fseek (psf, SDS_BLOCK_SIZE - 2, SEEK_CUR) ;
bytesread += SDS_BLOCK_SIZE - 2 ;
} ;
psf_log_printf (psf, "\nBlocks : %d\n", blockcount) ;
psds->total_blocks = blockcount ;
psds->samplesperblock = SDS_AUDIO_BYTES_PER_BLOCK / ((psds->bitwidth + 6) / 7) ;
psf_log_printf (psf, "Samples/Block : %d\n", psds->samplesperblock) ;
psf_log_printf (psf, "Frames : %d\n", blockcount * psds->samplesperblock) ;
psf->sf.frames = blockcount * psds->samplesperblock ;
psds->frames = blockcount * psds->samplesperblock ;
/* Always Mono */
psf->sf.channels = 1 ;
psf->sf.sections = 1 ;
/*
** Lie to the user about PCM bit width. Always round up to
** the next multiple of 8.
*/
switch ((psds->bitwidth + 7) / 8)
{ case 1 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_S8 ;
break ;
case 2 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_16 ;
break ;
case 3 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_24 ;
break ;
case 4 :
psf->sf.format = SF_FORMAT_SDS | SF_FORMAT_PCM_32 ;
break ;
default :
psf_log_printf (psf, "*** Weird byte width (%d)\n", (psds->bitwidth + 7) / 8) ;
return SFE_SDS_BAD_BIT_WIDTH ;
} ;
psf_fseek (psf, SDS_DATA_OFFSET, SEEK_SET) ;
return 0 ;
} /* sds_read_header */
static int
sds_write_header (SF_PRIVATE *psf, int calc_length)
{ SDS_PRIVATE *psds ;
sf_count_t current ;
int samp_period, data_length, sustain_loop_start, sustain_loop_end ;
unsigned char loop_type = 0 ;
if ((psds = (SDS_PRIVATE *) psf->fdata) == NULL)
{ psf_log_printf (psf, "*** Bad psf->fdata ptr.\n") ;
return SFE_INTERNAL ;
} ;
if (psf->pipeoffset > 0)
return 0 ;
current = psf_ftell (psf) ;
if (calc_length)
psf->sf.frames = psds->total_blocks * psds->samplesperblock + psds->write_count ;
if (psds->write_count > 0)
{ int current_count = psds->write_count ;
int current_block = psds->write_block ;
psds->writer (psf, psds) ;
psf_fseek (psf, -1 * SDS_BLOCK_SIZE, SEEK_CUR) ;
psds->write_count = current_count ;
psds->write_block = current_block ;
} ;
/* 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) ;
psf_binheader_writef (psf, "E211", 0xF07E, 0, 1) ;
switch (psf->sf.format & SF_FORMAT_SUBMASK)
{ case SF_FORMAT_PCM_S8 :
psds->bitwidth = 8 ;
break ;
case SF_FORMAT_PCM_16 :
psds->bitwidth = 16 ;
break ;
case SF_FORMAT_PCM_24 :
psds->bitwidth = 24 ;
break ;
default:
return SFE_SDS_BAD_BIT_WIDTH ;
} ;
samp_period = SDS_INT_TO_3BYTE_ENCODE (1000000000 / psf->sf.samplerate) ;
psf_binheader_writef (psf, "e213", 0, psds->bitwidth, samp_period) ;
data_length = SDS_INT_TO_3BYTE_ENCODE (psds->total_blocks * SDS_BLOCK_SIZE) ;
sustain_loop_start = SDS_INT_TO_3BYTE_ENCODE (0) ;
sustain_loop_end = SDS_INT_TO_3BYTE_ENCODE (psf->sf.frames) ;
psf_binheader_writef (psf, "e33311", data_length, sustain_loop_start, sustain_loop_end, loop_type, 0xF7) ;
/* 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 ;
psf->datalength = psds->write_block * SDS_BLOCK_SIZE ;
if (current > 0)
psf_fseek (psf, current, SEEK_SET) ;
return psf->error ;
} /* sds_write_header */
/*------------------------------------------------------------------------------
*/
static int
sds_2byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->read_block ++ ;
psds->read_count = 0 ;
if (psds->read_block * psds->samplesperblock > psds->frames)
{ memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
return 1 ;
} ;
if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
if (psds->read_data [0] != 0xF0)
{ printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
} ;
checksum = psds->read_data [1] ;
if (checksum != 0x7E)
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
}
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->read_data [k] ;
checksum &= 0x7F ;
if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
{ psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
} ;
ucptr = psds->read_data + 5 ;
for (k = 0 ; k < 120 ; k += 2)
{ sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) ;
psds->read_samples [k / 2] = (int) (sample - 0x80000000) ;
} ;
return 1 ;
} /* sds_2byte_read */
static int
sds_3byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->read_block ++ ;
psds->read_count = 0 ;
if (psds->read_block * psds->samplesperblock > psds->frames)
{ memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
return 1 ;
} ;
if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
if (psds->read_data [0] != 0xF0)
{ printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
} ;
checksum = psds->read_data [1] ;
if (checksum != 0x7E)
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
}
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->read_data [k] ;
checksum &= 0x7F ;
if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
{ psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
} ;
ucptr = psds->read_data + 5 ;
for (k = 0 ; k < 120 ; k += 3)
{ sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) ;
psds->read_samples [k / 3] = (int) (sample - 0x80000000) ;
} ;
return 1 ;
} /* sds_3byte_read */
static int
sds_4byte_read (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->read_block ++ ;
psds->read_count = 0 ;
if (psds->read_block * psds->samplesperblock > psds->frames)
{ memset (psds->read_samples, 0, psds->samplesperblock * sizeof (int)) ;
return 1 ;
} ;
if ((k = psf_fread (psds->read_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
if (psds->read_data [0] != 0xF0)
{ printf ("Error A : %02X\n", psds->read_data [0] & 0xFF) ;
} ;
checksum = psds->read_data [1] ;
if (checksum != 0x7E)
{ printf ("Error 1 : %02X\n", checksum & 0xFF) ;
}
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->read_data [k] ;
checksum &= 0x7F ;
if (checksum != psds->read_data [SDS_BLOCK_SIZE - 2])
{ psf_log_printf (psf, "Block %d : checksum is %02X should be %02X\n", psds->read_data [4], checksum, psds->read_data [SDS_BLOCK_SIZE - 2]) ;
} ;
ucptr = psds->read_data + 5 ;
for (k = 0 ; k < 120 ; k += 4)
{ sample = (ucptr [k] << 25) + (ucptr [k + 1] << 18) + (ucptr [k + 2] << 11) + (ucptr [k + 3] << 4) ;
psds->read_samples [k / 4] = (int) (sample - 0x80000000) ;
} ;
return 1 ;
} /* sds_4byte_read */
static sf_count_t
sds_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = sds_read (psf, psds, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = iptr [k] >> 16 ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* sds_read_s */
static sf_count_t
sds_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int total ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
total = sds_read (psf, psds, ptr, len) ;
return total ;
} /* sds_read_i */
static sf_count_t
sds_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_float == SF_TRUE)
normfact = 1.0 / 0x80000000 ;
else
normfact = 1.0 / (1 << psds->bitwidth) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = sds_read (psf, psds, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * iptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* sds_read_f */
static sf_count_t
sds_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_double == SF_TRUE)
normfact = 1.0 / 0x80000000 ;
else
normfact = 1.0 / (1 << psds->bitwidth) ;
iptr = psf->u.ibuf ;
bufferlen = ARRAY_LEN (psf->u.ibuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = sds_read (psf, psds, iptr, readcount) ;
for (k = 0 ; k < readcount ; k++)
ptr [total + k] = normfact * iptr [k] ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* sds_read_d */
static int
sds_read (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len)
{ int count, total = 0 ;
while (total < len)
{ if (psds->read_block * psds->samplesperblock >= psds->frames)
{ memset (&(ptr [total]), 0, (len - total) * sizeof (int)) ;
return total ;
} ;
if (psds->read_count >= psds->samplesperblock)
psds->reader (psf, psds) ;
count = (psds->samplesperblock - psds->read_count) ;
count = (len - total > count) ? count : len - total ;
memcpy (&(ptr [total]), &(psds->read_samples [psds->read_count]), count * sizeof (int)) ;
total += count ;
psds->read_count += count ;
} ;
return total ;
} /* sds_read */
/*==============================================================================
*/
static sf_count_t
sds_seek (SF_PRIVATE *psf, int mode, sf_count_t seek_from_start)
{ SDS_PRIVATE *psds ;
sf_count_t file_offset ;
int newblock, newsample ;
if ((psds = psf->fdata) == NULL)
{ psf->error = SFE_INTERNAL ;
return SF_SEEK_ERROR ;
} ;
if (psf->datalength < 0 || psf->dataoffset < 0)
{ psf->error = SFE_BAD_SEEK ;
return SF_SEEK_ERROR ;
} ;
if (seek_from_start < 0 || seek_from_start > psf->sf.frames)
{ psf->error = SFE_BAD_SEEK ;
return SF_SEEK_ERROR ;
} ;
if (mode == SFM_READ && psds->write_count > 0)
psds->writer (psf, psds) ;
newblock = seek_from_start / psds->samplesperblock ;
newsample = seek_from_start % psds->samplesperblock ;
switch (mode)
{ case SFM_READ :
if (newblock > psds->total_blocks)
{ psf->error = SFE_BAD_SEEK ;
return SF_SEEK_ERROR ;
} ;
file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ;
if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset)
{ psf->error = SFE_SEEK_FAILED ;
return SF_SEEK_ERROR ;
} ;
psds->read_block = newblock ;
psds->reader (psf, psds) ;
psds->read_count = newsample ;
break ;
case SFM_WRITE :
if (newblock > psds->total_blocks)
{ psf->error = SFE_BAD_SEEK ;
return SF_SEEK_ERROR ;
} ;
file_offset = psf->dataoffset + newblock * SDS_BLOCK_SIZE ;
if (psf_fseek (psf, file_offset, SEEK_SET) != file_offset)
{ psf->error = SFE_SEEK_FAILED ;
return SF_SEEK_ERROR ;
} ;
psds->write_block = newblock ;
psds->reader (psf, psds) ;
psds->write_count = newsample ;
break ;
default :
psf->error = SFE_BAD_SEEK ;
return SF_SEEK_ERROR ;
break ;
} ;
return seek_from_start ;
} /* sds_seek */
/*==============================================================================
*/
static int
sds_2byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->write_data [0] = 0xF0 ;
psds->write_data [1] = 0x7E ;
psds->write_data [2] = 0 ; /* Channel number */
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
ucptr = psds->write_data + 5 ;
for (k = 0 ; k < 120 ; k += 2)
{ sample = psds->write_samples [k / 2] ;
sample += 0x80000000 ;
ucptr [k] = (sample >> 25) & 0x7F ;
ucptr [k + 1] = (sample >> 18) & 0x7F ;
} ;
checksum = psds->write_data [1] ;
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->write_data [k] ;
checksum &= 0x7F ;
psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
psds->write_block ++ ;
psds->write_count = 0 ;
if (psds->write_block > psds->total_blocks)
psds->total_blocks = psds->write_block ;
psds->frames = psds->total_blocks * psds->samplesperblock ;
return 1 ;
} /* sds_2byte_write */
static int
sds_3byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->write_data [0] = 0xF0 ;
psds->write_data [1] = 0x7E ;
psds->write_data [2] = 0 ; /* Channel number */
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
ucptr = psds->write_data + 5 ;
for (k = 0 ; k < 120 ; k += 3)
{ sample = psds->write_samples [k / 3] ;
sample += 0x80000000 ;
ucptr [k] = (sample >> 25) & 0x7F ;
ucptr [k + 1] = (sample >> 18) & 0x7F ;
ucptr [k + 2] = (sample >> 11) & 0x7F ;
} ;
checksum = psds->write_data [1] ;
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->write_data [k] ;
checksum &= 0x7F ;
psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
psds->write_block ++ ;
psds->write_count = 0 ;
if (psds->write_block > psds->total_blocks)
psds->total_blocks = psds->write_block ;
psds->frames = psds->total_blocks * psds->samplesperblock ;
return 1 ;
} /* sds_3byte_write */
static int
sds_4byte_write (SF_PRIVATE *psf, SDS_PRIVATE *psds)
{ unsigned char *ucptr, checksum ;
unsigned int sample ;
int k ;
psds->write_data [0] = 0xF0 ;
psds->write_data [1] = 0x7E ;
psds->write_data [2] = 0 ; /* Channel number */
psds->write_data [3] = psds->write_block & 0x7F ; /* Packet number */
ucptr = psds->write_data + 5 ;
for (k = 0 ; k < 120 ; k += 4)
{ sample = psds->write_samples [k / 4] ;
sample += 0x80000000 ;
ucptr [k] = (sample >> 25) & 0x7F ;
ucptr [k + 1] = (sample >> 18) & 0x7F ;
ucptr [k + 2] = (sample >> 11) & 0x7F ;
ucptr [k + 3] = (sample >> 4) & 0x7F ;
} ;
checksum = psds->write_data [1] ;
for (k = 2 ; k < SDS_BLOCK_SIZE - 3 ; k ++)
checksum ^= psds->write_data [k] ;
checksum &= 0x7F ;
psds->write_data [SDS_BLOCK_SIZE - 2] = checksum ;
psds->write_data [SDS_BLOCK_SIZE - 1] = 0xF7 ;
if ((k = psf_fwrite (psds->write_data, 1, SDS_BLOCK_SIZE, psf)) != SDS_BLOCK_SIZE)
psf_log_printf (psf, "*** Warning : psf_fwrite (%d != %d).\n", k, SDS_BLOCK_SIZE) ;
psds->write_block ++ ;
psds->write_count = 0 ;
if (psds->write_block > psds->total_blocks)
psds->total_blocks = psds->write_block ;
psds->frames = psds->total_blocks * psds->samplesperblock ;
return 1 ;
} /* sds_4byte_write */
static sf_count_t
sds_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
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 = sds_write (psf, psds, iptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* sds_write_s */
static sf_count_t
sds_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int total ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
total = sds_write (psf, psds, ptr, len) ;
return total ;
} /* sds_write_i */
static sf_count_t
sds_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_float == SF_TRUE)
normfact = 1.0 * 0x80000000 ;
else
normfact = 1.0 * (1 << psds->bitwidth) ;
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] = normfact * ptr [total + k] ;
count = sds_write (psf, psds, iptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* sds_write_f */
static sf_count_t
sds_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ SDS_PRIVATE *psds ;
int *iptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->fdata == NULL)
return 0 ;
psds = (SDS_PRIVATE*) psf->fdata ;
if (psf->norm_double == SF_TRUE)
normfact = 1.0 * 0x80000000 ;
else
normfact = 1.0 * (1 << psds->bitwidth) ;
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] = normfact * ptr [total + k] ;
count = sds_write (psf, psds, iptr, writecount) ;
total += count ;
len -= writecount ;
} ;
return total ;
} /* sds_write_d */
static int
sds_write (SF_PRIVATE *psf, SDS_PRIVATE *psds, int *ptr, int len)
{ int count, total = 0 ;
while (total < len)
{ count = psds->samplesperblock - psds->write_count ;
if (count > len - total)
count = len - total ;
memcpy (&(psds->write_samples [psds->write_count]), &(ptr [total]), count * sizeof (int)) ;
total += count ;
psds->write_count += count ;
if (psds->write_count >= psds->samplesperblock)
psds->writer (psf, psds) ;
} ;
return total ;
} /* sds_write */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: d5d26aa3-368c-4ca6-bb85-377e5a2578cc
*/

View file

@ -0,0 +1,67 @@
/*
** Copyright (C) 2002-2004 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
#define S_IRWXG 0000070 /* rwx, group */
#define S_IRGRP 0000040 /* read permission, group */
#define S_IWGRP 0000020 /* write permission, grougroup */
#define S_IXGRP 0000010 /* execute/search permission, group */
#define S_IRWXO 0000007 /* rwx, other */
#define S_IROTH 0000004 /* read permission, other */
#define S_IWOTH 0000002 /* write permission, other */
#define S_IXOTH 0000001 /* 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
*/
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 253aea6d-6299-46fd-8d06-bc5f6224c8fe
*/

View file

@ -0,0 +1,258 @@
/*
** Copyright (C) 1999-2004 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 "config.h"
#if HAVE_STDINT_H
#include <stdint.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
#undef HAVE_BYTESWAP_H
#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/config.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)
#define H2LE_SHORT(x) (x)
#define H2LE_INT(x) (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 H2BE_SHORT(x) (x)
#define H2BE_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/config.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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: f0c5cd54-42d3-4237-90ec-11fe24995de7
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,491 @@
/*
** Copyright (C) 1999-2004 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.
*/
/*
** 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>
/* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */
#if (defined (__MWERKS__))
#include <unix.h>
#else
#include <sys/types.h>
#endif
#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). */
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 */
/* 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) */
/* 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_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_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_SET_ADD_PEAK_CHUNK = 0x1050,
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,
/* 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
} ;
/*
** 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_DATE
enum
{ /* True and false */
SF_FALSE = 0,
SF_TRUE = 1,
/* Modes for opening files. */
SFM_READ = 0x10,
SFM_WRITE = 0x20,
SFM_RDWR = 0x30
} ;
/* 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
} ;
/* 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 can be one of loff_t (Linux), off_t (*BSD),
** off64_t (Solaris), __int64_t (Win32) etc.
*/
typedef off_t sf_count_t ;
#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL
/* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in.
** On write, the SF_INFO structure is filled in by the user and passed into
** sf_open_write ().
*/
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 ;
/* Struct used to retrieve music sample information from a file.
*/
typedef struct
{ int basenote ;
int gain ;
int sustain_mode ;
int sustain_start, sustain_end ;
int release_mode ;
int release_start, reslease_end ;
} SF_INSTRUMENT ;
/* sustain_mode and release_mode will be one of the following. */
enum
{ SF_LOOP_NONE = 800,
SF_LOOP_FORWARD,
SF_LOOP_BACKWARD
} ;
/* 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 ;
/* 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_perror () or sf_error_str ().
** 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_perror () or sf_error_str ().
** 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) ;
/* 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 three 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) ;
/* 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, 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, 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, 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, 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, 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, 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, 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, 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, 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) ;
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif /* SNDFILE_H */

View file

@ -0,0 +1,203 @@
/*
** Copyright (C) 2001-2004 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 <stdio.h>
#include <string.h>
#include <math.h>
#include "sndfile.h"
#include "config.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)
{ static char lsf_name [] = PACKAGE "-" VERSION ;
static char bracket_name [] = " (" PACKAGE "-" VERSION ")" ;
int k, str_len, len_remaining, str_flags ;
if (str == NULL)
return SFE_STR_BAD_STRING ;
str_len = strlen (str) ;
/* A few extra checks for write mode. */
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->str_flags & SF_STR_ALLOW_START) == 0)
return SFE_STR_NO_SUPPORT ;
if ((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 ;
} ;
/* Determine flags */
str_flags = SF_STR_LOCATE_START ;
if (psf->have_written)
{ if ((psf->str_flags & SF_STR_ALLOW_END) == 0)
return SFE_STR_NO_ADD_END ;
str_flags = SF_STR_LOCATE_END ;
} ;
/* Find next free slot in table. */
for (k = 0 ; k < SF_MAX_STRINGS ; k++)
if (psf->strings [k].type == 0)
break ;
/* 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 ;
#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 (storage) : %d\n", SIGNED_SIZEOF (psf->str_storage)) ;
#endif
len_remaining = SIGNED_SIZEOF (psf->str_storage) - (psf->str_end - psf->str_storage) ;
if (len_remaining < str_len + 2)
return SFE_STR_MAX_DATA ;
switch (str_type)
{ case SF_STR_SOFTWARE :
/* In write mode, want to append libsndfile-version to string. */
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ 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) ;
psf->str_end += str_len ;
/*
** If the supplied string does not already contain a
** libsndfile-X.Y.Z component, then add it.
*/
if (strstr (str, PACKAGE) == NULL && len_remaining > (int) (strlen (bracket_name) + str_len + 2))
{ if (strlen (str) == 0)
strncat (psf->str_end, lsf_name, len_remaining) ;
else
strncat (psf->str_end, bracket_name, len_remaining) ;
psf->str_end += strlen (psf->str_end) ;
} ;
/* Plus one to catch string terminator. */
psf->str_end += 1 ;
break ;
} ;
/* Fall though if not write mode. */
case SF_STR_TITLE :
case SF_STR_COPYRIGHT :
case SF_STR_ARTIST :
case SF_STR_COMMENT :
case SF_STR_DATE :
psf->strings [k].type = str_type ;
psf->strings [k].str = psf->str_end ;
psf->strings [k].flags = str_flags ;
/* Plus one to catch string terminator. */
memcpy (psf->str_end, str, str_len + 1) ;
psf->str_end += str_len + 1 ;
break ;
default :
return SFE_STR_BAD_TYPE ;
} ;
psf->str_flags |= (psf->have_written) ? SF_STR_LOCATE_END : SF_STR_LOCATE_START ;
#if STRINGS_DEBUG
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->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 */
#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", isprint (ptr [k]) ? ptr [k] : '.') ;
puts ("") ;
ptr += 16 ;
len -= 16 ;
} ;
} /* hexdump */
#endif
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 04393aa1-9389-46fe-baf2-58a7bd544fd6
*/

View file

@ -0,0 +1,410 @@
/*
** Copyright (C) 1999-2004 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 "config.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, subformat ;
if (psf->mode == SFM_READ || (psf->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) ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_SVX)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = psf->sf.format & SF_FORMAT_ENDMASK ;
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->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 ;
psf_binheader_readf (psf, "p", 0) ;
/* Set default number of channels. */
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->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->filename) != dword)
{ if (dword > sizeof (psf->filename) - 1)
return SFE_SVX_BAD_NAME_LENGTH ;
psf_binheader_readf (psf, "b", psf->filename, dword) ;
psf->filename [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) ;
psf_log_printf (psf, " Channels : %d => %d\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 (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF)
&& isprint ((marker >> 8) & 0xFF) && 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->mode == SFM_WRITE || psf->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) ;
/* Filename and annotation strings. */
psf_binheader_writef (psf, "Emsms", NAME_MARKER, psf->filename, 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 */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: a80ab6fb-7d75-4d32-a6b0-0061a3f05d95
*/

View file

@ -0,0 +1,233 @@
/*
** Copyright (C) 2002-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include "common.h"
#include "sfendian.h"
static void test_endswap_short (void) ;
static void test_endswap_int (void) ;
static void test_endswap_int64_t (void) ;
int
main (void)
{
test_endswap_short () ;
test_endswap_int () ;
test_endswap_int64_t () ;
return 0 ;
} /* main */
/*==============================================================================
** Actual test functions.
*/
static void
dump_short_array (const char * name, short * data, int datalen)
{ int k ;
printf ("%-6s : ", name) ;
for (k = 0 ; k < datalen ; k++)
printf ("0x%04x ", data [k]) ;
putchar ('\n') ;
} /* dump_short_array */
static void
test_endswap_short (void)
{ short orig [4], first [4], second [4] ;
int k ;
printf (" %-24s : ", "test_endswap_short") ;
fflush (stdout) ;
for (k = 0 ; k < ARRAY_LEN (orig) ; k++)
orig [k] = 0x3210 + k ;
endswap_short_copy (first, orig, ARRAY_LEN (first)) ;
endswap_short_copy (second, first, ARRAY_LEN (second)) ;
if (memcmp (orig, first, sizeof (orig)) == 0)
{ printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ;
dump_short_array ("orig", orig, ARRAY_LEN (orig));
dump_short_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
if (memcmp (orig, second, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ;
dump_short_array ("orig", orig, ARRAY_LEN (orig));
dump_short_array ("second", second, ARRAY_LEN (second));
exit (1) ;
} ;
endswap_short_array (first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ;
dump_short_array ("orig", orig, ARRAY_LEN (orig));
dump_short_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
endswap_short_copy (first, orig, ARRAY_LEN (first)) ;
endswap_short_copy (first, first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ;
dump_short_array ("orig", orig, ARRAY_LEN (orig));
dump_short_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
puts ("ok") ;
} /* test_endswap_short */
static void
dump_int_array (const char * name, int * data, int datalen)
{ int k ;
printf ("%-6s : ", name) ;
for (k = 0 ; k < datalen ; k++)
printf ("0x%08x ", data [k]) ;
putchar ('\n') ;
} /* dump_int_array */
static void
test_endswap_int (void)
{ int orig [4], first [4], second [4] ;
int k ;
printf (" %-24s : ", "test_endswap_int") ;
fflush (stdout) ;
for (k = 0 ; k < ARRAY_LEN (orig) ; k++)
orig [k] = 0x76543210 + k ;
endswap_int_copy (first, orig, ARRAY_LEN (first)) ;
endswap_int_copy (second, first, ARRAY_LEN (second)) ;
if (memcmp (orig, first, sizeof (orig)) == 0)
{ printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ;
dump_int_array ("orig", orig, ARRAY_LEN (orig));
dump_int_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
if (memcmp (orig, second, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ;
dump_int_array ("orig", orig, ARRAY_LEN (orig));
dump_int_array ("second", second, ARRAY_LEN (second));
exit (1) ;
} ;
endswap_int_array (first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ;
dump_int_array ("orig", orig, ARRAY_LEN (orig));
dump_int_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
endswap_int_copy (first, orig, ARRAY_LEN (first)) ;
endswap_int_copy (first, first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ;
dump_int_array ("orig", orig, ARRAY_LEN (orig));
dump_int_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
puts ("ok") ;
} /* test_endswap_int */
static void
dump_int64_t_array (const char * name, int64_t * data, int datalen)
{ int k ;
printf ("%-6s : ", name) ;
for (k = 0 ; k < datalen ; k++)
printf ("0x%016llx ", data [k]) ;
putchar ('\n') ;
} /* dump_int64_t_array */
static void
test_endswap_int64_t (void)
{ int64_t orig [4], first [4], second [4] ;
int k ;
printf (" %-24s : ", "test_endswap_int64_t") ;
fflush (stdout) ;
for (k = 0 ; k < ARRAY_LEN (orig) ; k++)
orig [k] = 0x0807050540302010LL + k ;
endswap_int64_t_copy (first, orig, ARRAY_LEN (first)) ;
endswap_int64_t_copy (second, first, ARRAY_LEN (second)) ;
if (memcmp (orig, first, sizeof (orig)) == 0)
{ printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ;
dump_int64_t_array ("orig", orig, ARRAY_LEN (orig));
dump_int64_t_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
if (memcmp (orig, second, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ;
dump_int64_t_array ("orig", orig, ARRAY_LEN (orig));
dump_int64_t_array ("second", second, ARRAY_LEN (second));
exit (1) ;
} ;
endswap_int64_t_array (first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ;
dump_int64_t_array ("orig", orig, ARRAY_LEN (orig));
dump_int64_t_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
endswap_int64_t_copy (first, orig, ARRAY_LEN (first)) ;
endswap_int64_t_copy (first, first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ;
dump_int64_t_array ("orig", orig, ARRAY_LEN (orig));
dump_int64_t_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
puts ("ok") ;
} /* test_endswap_int64_t */

View file

@ -0,0 +1,28 @@
autogen definitions test_endswap.tpl;
int_type = {
name = short ;
value = 0x3210 ;
format = "0x%04x" ;
} ;
int_type = {
name = int ;
value = 0x76543210 ;
format = "0x%08x" ;
} ;
int_type = {
name = int64_t ;
value = "0x0807050540302010LL" ;
format = "0x%016llx" ;
} ;
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 098c07e0-2d3f-4f62-ad93-f3f4b91c5211
*/

View file

@ -0,0 +1,126 @@
[+ AutoGen5 template c +]
/*
** Copyright (C) 2002-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include "common.h"
#include "sfendian.h"
[+ FOR int_type
+]static void test_endswap_[+ (get "name") +] (void) ;
[+ ENDFOR int_type
+]
int
main (void)
{
[+ FOR int_type
+] test_endswap_[+ (get "name") +] () ;
[+ ENDFOR int_type
+]
return 0 ;
} /* main */
/*==============================================================================
** Actual test functions.
*/
[+ FOR int_type
+]static void
dump_[+ (get "name") +]_array (const char * name, [+ (get "name") +] * data, int datalen)
{ int k ;
printf ("%-6s : ", name) ;
for (k = 0 ; k < datalen ; k++)
printf ("[+ (get "format") +] ", data [k]) ;
putchar ('\n') ;
} /* dump_[+ (get "name") +]_array */
static void
test_endswap_[+ (get "name") +] (void)
{ [+ (get "name") +] orig [4], first [4], second [4] ;
int k ;
printf (" %-24s : ", "test_endswap_[+ (get "name") +]") ;
fflush (stdout) ;
for (k = 0 ; k < ARRAY_LEN (orig) ; k++)
orig [k] = [+ (get "value") +] + k ;
endswap_[+ (get "name") +]_copy (first, orig, ARRAY_LEN (first)) ;
endswap_[+ (get "name") +]_copy (second, first, ARRAY_LEN (second)) ;
if (memcmp (orig, first, sizeof (orig)) == 0)
{ printf ("\n\nLine %d : test 1 : these two array should not be the same:\n\n", __LINE__) ;
dump_[+ (get "name") +]_array ("orig", orig, ARRAY_LEN (orig));
dump_[+ (get "name") +]_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
if (memcmp (orig, second, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 2 : these two array should be the same:\n\n", __LINE__) ;
dump_[+ (get "name") +]_array ("orig", orig, ARRAY_LEN (orig));
dump_[+ (get "name") +]_array ("second", second, ARRAY_LEN (second));
exit (1) ;
} ;
endswap_[+ (get "name") +]_array (first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 3 : these two array should be the same:\n\n", __LINE__) ;
dump_[+ (get "name") +]_array ("orig", orig, ARRAY_LEN (orig));
dump_[+ (get "name") +]_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
endswap_[+ (get "name") +]_copy (first, orig, ARRAY_LEN (first)) ;
endswap_[+ (get "name") +]_copy (first, first, ARRAY_LEN (first)) ;
if (memcmp (orig, first, sizeof (orig)) != 0)
{ printf ("\n\nLine %d : test 4 : these two array should be the same:\n\n", __LINE__) ;
dump_[+ (get "name") +]_array ("orig", orig, ARRAY_LEN (orig));
dump_[+ (get "name") +]_array ("first", first, ARRAY_LEN (first));
exit (1) ;
} ;
puts ("ok") ;
} /* test_endswap_[+ (get "name") +] */
[+ ENDFOR int_type
+]
[+ COMMENT
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: fd8887e8-8202-4f30-a419-0cf01a0e799b
*/
+]

View file

@ -0,0 +1,448 @@
/*
** Copyright (C) 2002-2004 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 "config.h"
#include <stdio.h>
#include <stdlib.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <string.h>
#include <errno.h>
#include "common.h"
static void make_data (int *data, int len, int seed) ;
static void file_open_test (const char *filename) ;
static void file_read_write_test (const char *filename) ;
static void file_truncate_test (const char *filename) ;
static void test_open_or_die (SF_PRIVATE *psf, int linenum) ;
static void test_close_or_die (SF_PRIVATE *psf, int linenum) ;
static void test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
static void test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum) ;
static void test_equal_or_die (int *array1, int *array2, int len, int linenum) ;
static void test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum) ;
int
main (void)
{ const char *filename = "file_io.dat" ;
file_open_test (filename) ;
file_read_write_test (filename) ;
file_truncate_test (filename) ;
unlink (filename) ;
return 0 ;
} /* main */
/*==============================================================================
** Actual test functions.
*/
static void
file_open_test (const char *filename)
{ SF_PRIVATE sf_data, *psf ;
int error ;
printf (" %-24s : ", "file_open_test") ;
fflush (stdout) ;
memset (&sf_data, 0, sizeof (sf_data)) ;
psf = &sf_data ;
/* Ensure that the file doesn't already exist. */
if (unlink (filename) != 0 && errno != ENOENT)
{ printf ("\n\nLine %d: unlink failed (%d) : %s\n\n", __LINE__, errno, strerror (errno)) ;
exit (1) ;
} ;
strncpy (psf->filename, filename, sizeof (psf->filename)) ;
/* Test that open for read fails if the file doesn't exist. */
error = psf_fopen (psf, psf->filename, SFM_READ) ;
if (error == 0)
{ printf ("\n\nLine %d: psf_fopen() should have failed.\n\n", __LINE__) ;
exit (1) ;
} ;
/* Reset error to zero. */
psf->error = SFE_NO_ERROR ;
/* Test file open in write mode. */
psf->mode = SFM_WRITE ;
test_open_or_die (psf, __LINE__) ;
test_close_or_die (psf, __LINE__) ;
unlink (psf->filename) ;
/* Test file open in read/write mode for a non-existant file. */
psf->mode = SFM_RDWR ;
test_open_or_die (psf, __LINE__) ;
test_close_or_die (psf, __LINE__) ;
/* Test file open in read/write mode for an existing file. */
psf->mode = SFM_RDWR ;
test_open_or_die (psf, __LINE__) ;
test_close_or_die (psf, __LINE__) ;
unlink (psf->filename) ;
puts ("ok") ;
} /* file_open_test */
static void
file_read_write_test (const char *filename)
{ static int data_out [512] ;
static int data_in [512] ;
SF_PRIVATE sf_data, *psf ;
sf_count_t retval ;
/*
** Open a new file and write two blocks of data to the file. After each
** write, test that psf_get_filelen() returns the new length.
*/
printf (" %-24s : ", "file_write_test") ;
fflush (stdout) ;
memset (&sf_data, 0, sizeof (sf_data)) ;
psf = &sf_data ;
strncpy (psf->filename, filename, sizeof (psf->filename)) ;
/* Test file open in write mode. */
psf->mode = SFM_WRITE ;
test_open_or_die (psf, __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 1) ;
test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), sizeof (data_out), __LINE__) ;
if ((retval = psf_get_filelen (psf)) != sizeof (data_out))
{ printf ("\n\nLine %d: file length after write is not correct (%ld should be %d).\n\n", __LINE__, (long) retval, (int) sizeof (data_out)) ;
if (retval == 0)
printf ("An fsync() may be necessary before fstat() in psf_get_filelen().\n\n") ;
exit (1) ;
} ;
make_data (data_out, ARRAY_LEN (data_out), 2) ;
test_write_or_die (psf, data_out, ARRAY_LEN (data_out), sizeof (data_out [0]), 2 * sizeof (data_out), __LINE__) ;
if ((retval = psf_get_filelen (psf)) != 2 * sizeof (data_out))
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 2 * ((int) sizeof (data_out))) ;
exit (1) ;
} ;
test_close_or_die (psf, __LINE__) ;
puts ("ok") ;
/*
** Now open the file in read mode, check the file length and check
** that the data is correct.
*/
printf (" %-24s : ", "file_read_test") ;
fflush (stdout) ;
/* Test file open in write mode. */
psf->mode = SFM_READ ;
test_open_or_die (psf, __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 1) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 2) ;
test_read_or_die (psf, data_in, sizeof (data_in [0]), ARRAY_LEN (data_in), 2 * sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
test_close_or_die (psf, __LINE__) ;
puts ("ok") ;
/*
** Open the file in read/write mode, seek around a bit and then seek to
** the end of the file and write another block of data (3rd block). Then
** go back and check that all three blocks are correct.
*/
printf (" %-24s : ", "file_seek_test") ;
fflush (stdout) ;
/* Test file open in read/write mode. */
psf->mode = SFM_RDWR ;
test_open_or_die (psf, __LINE__) ;
test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
test_seek_or_die (psf, 0, SEEK_END, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
test_seek_or_die (psf, -1 * SIGNED_SIZEOF (data_out), SEEK_CUR, (sf_count_t) sizeof (data_out), __LINE__) ;
test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_CUR, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 3) ;
test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 3 * sizeof (data_out), __LINE__) ;
test_seek_or_die (psf, 0, SEEK_SET, 0, __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 1) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
test_seek_or_die (psf, 2 * SIGNED_SIZEOF (data_out), SEEK_SET, 2 * SIGNED_SIZEOF (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 3) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 2) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
test_close_or_die (psf, __LINE__) ;
puts ("ok") ;
/*
** Now test operations with a non-zero psf->fileoffset field. This field
** sets an artificial file start positions so that a seek to the start of
** the file will actually be a seek to the value given by psf->fileoffset.
*/
printf (" %-24s : ", "file_offset_test") ;
fflush (stdout) ;
/* Test file open in read/write mode. */
psf->mode = SFM_RDWR ;
psf->fileoffset = sizeof (data_out [0]) * ARRAY_LEN (data_out) ;
test_open_or_die (psf, __LINE__) ;
if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 3 * ((int) sizeof (data_out))) ;
exit (1) ;
} ;
test_seek_or_die (psf, SIGNED_SIZEOF (data_out), SEEK_SET, SIGNED_SIZEOF (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 5) ;
test_write_or_die (psf, data_out, sizeof (data_out [0]), ARRAY_LEN (data_out), 2 * sizeof (data_out), __LINE__) ;
test_close_or_die (psf, __LINE__) ;
/* final test with psf->fileoffset == 0. */
psf->mode = SFM_RDWR ;
psf->fileoffset = 0 ;
test_open_or_die (psf, __LINE__) ;
if ((retval = psf_get_filelen (psf)) != 3 * sizeof (data_out))
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %d)\n\n", __LINE__, (long) retval, 3 * ((int) sizeof (data_out))) ;
exit (1) ;
} ;
make_data (data_out, ARRAY_LEN (data_out), 1) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 2) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), 2 * sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
make_data (data_out, ARRAY_LEN (data_out), 5) ;
test_read_or_die (psf, data_in, 1, sizeof (data_in), 3 * sizeof (data_in), __LINE__) ;
test_equal_or_die (data_out, data_in, ARRAY_LEN (data_out), __LINE__) ;
test_close_or_die (psf, __LINE__) ;
puts ("ok") ;
} /* file_read_write_test */
static void
file_truncate_test (const char *filename)
{ SF_PRIVATE sf_data, *psf ;
unsigned char buffer [256] ;
int k ;
/*
** Open a new file and write two blocks of data to the file. After each
** write, test that psf_get_filelen() returns the new length.
*/
printf (" %-24s : ", "file_truncate_test") ;
fflush (stdout) ;
memset (&sf_data, 0, sizeof (sf_data)) ;
memset (buffer, 0xEE, sizeof (buffer)) ;
psf = &sf_data ;
strncpy (psf->filename, filename, sizeof (psf->filename)) ;
/*
** Open the file write mode, write 0xEE data and then extend the file
** using truncate (the extended data should be 0x00).
*/
psf->mode = SFM_WRITE ;
test_open_or_die (psf, __LINE__) ;
test_write_or_die (psf, buffer, sizeof (buffer) / 2, 1, sizeof (buffer) / 2, __LINE__) ;
psf_ftruncate (psf, sizeof (buffer)) ;
test_close_or_die (psf, __LINE__) ;
/* Open the file in read mode and check the data. */
psf->mode = SFM_READ ;
test_open_or_die (psf, __LINE__) ;
test_read_or_die (psf, buffer, sizeof (buffer), 1, sizeof (buffer), __LINE__) ;
test_close_or_die (psf, __LINE__) ;
for (k = 0 ; k < SIGNED_SIZEOF (buffer) / 2 ; k++)
if (buffer [k] != 0xEE)
{ printf ("\n\nLine %d : buffer [%d] = %d (should be 0xEE)\n\n", __LINE__, k, buffer [k]) ;
exit (1) ;
} ;
for (k = SIGNED_SIZEOF (buffer) / 2 ; k < SIGNED_SIZEOF (buffer) ; k++)
if (buffer [k] != 0)
{ printf ("\n\nLine %d : buffer [%d] = %d (should be 0)\n\n", __LINE__, k, buffer [k]) ;
exit (1) ;
} ;
/* Open the file in read/write and shorten the file using truncate. */
psf->mode = SFM_RDWR ;
test_open_or_die (psf, __LINE__) ;
psf_ftruncate (psf, sizeof (buffer) / 4) ;
test_close_or_die (psf, __LINE__) ;
/* Check the file length. */
psf->mode = SFM_READ ;
test_open_or_die (psf, __LINE__) ;
test_seek_or_die (psf, 0, SEEK_END, SIGNED_SIZEOF (buffer) / 4, __LINE__) ;
test_close_or_die (psf, __LINE__) ;
puts ("ok") ;
} /* file_truncate_test */
/*==============================================================================
** Testing helper functions.
*/
static void
test_open_or_die (SF_PRIVATE *psf, int linenum)
{ int error ;
/* Test that open for read fails if the file doesn't exist. */
error = psf_fopen (psf, psf->filename, psf->mode) ;
if (error)
{ printf ("\n\nLine %d: psf_fopen() failed : %s\n\n", linenum, strerror (errno)) ;
exit (1) ;
} ;
} /* test_open_or_die */
static void
test_close_or_die (SF_PRIVATE *psf, int linenum)
{
psf_fclose (psf) ;
if (psf->filedes >= 0)
{ printf ("\n\nLine %d: psf->filedes should be < 0.\n\n", linenum) ;
exit (1) ;
} ;
} /* test_close_or_die */
static void
test_write_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
{ sf_count_t retval ;
retval = psf_fwrite (data, bytes, items, psf) ;
if (retval != items)
{ printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ;
exit (1) ;
} ;
if ((retval = psf_ftell (psf)) != new_position)
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ;
exit (1) ;
} ;
return ;
} /* test_write_or_die */
static void
test_read_or_die (SF_PRIVATE *psf, void *data, sf_count_t bytes, sf_count_t items, sf_count_t new_position, int linenum)
{ sf_count_t retval ;
retval = psf_fread (data, bytes, items, psf) ;
if (retval != items)
{ printf ("\n\nLine %d: psf_write() returned %ld (should be %ld)\n\n", linenum, (long) retval, (long) items) ;
exit (1) ;
} ;
if ((retval = psf_ftell (psf)) != new_position)
{ printf ("\n\nLine %d: file length after write is not correct. (%ld should be %ld)\n\n", linenum, (long) retval, (long) new_position) ;
exit (1) ;
} ;
return ;
} /* test_write_or_die */
static void
test_seek_or_die (SF_PRIVATE *psf, sf_count_t offset, int whence, sf_count_t new_position, int linenum)
{ sf_count_t retval ;
retval = psf_fseek (psf, offset, whence) ;
if (retval != new_position)
{ printf ("\n\nLine %d: psf_fseek() failed. New position is %ld (should be %ld).\n\n",
linenum, (long) retval, (long) new_position) ;
exit (1) ;
} ;
} /* test_seek_or_die */
static void
test_equal_or_die (int *array1, int *array2, int len, int linenum)
{ int k ;
for (k = 0 ; k < len ; k++)
if (array1 [k] != array2 [k])
printf ("\n\nLine %d: error at index %d (%d != %d).\n\n",
linenum, k, array1 [k], array2 [k]) ;
return ;
} /* test_equal_or_die */
static void
make_data (int *data, int len, int seed)
{ int k ;
srand (seed * 3333333 + 14756123) ;
for (k = 0 ; k < len ; k++)
data [k] = rand () ;
} /* make_data */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 0a21fb93-78dd-4f72-8338-4bca9e77b8c8
*/

View file

@ -0,0 +1,138 @@
/*
** Copyright (C) 2003,2004 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 <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <errno.h>
#include "config.h"
/*
** This is a bit rough, but it is the nicest way to do it.
*/
#define PSF_LOG_PRINTF_ONLY
#include "common.c"
#define CMP_0_ARGS(line,err,fmt) \
{ psf->logindex = 0 ; \
LSF_SNPRINTF (buffer, sizeof (buffer), (fmt)) ; \
psf_log_printf (psf, (fmt)) ; \
err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \
}
#define CMP_2_ARGS(line,err,fmt,a) \
{ psf->logindex = 0 ; \
LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a)) ; \
psf_log_printf (psf, (fmt), (a), (a)) ; \
err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \
}
#define CMP_4_ARGS(line,err,fmt,a) \
{ psf->logindex = 0 ; \
LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a), (a), (a)) ; \
psf_log_printf (psf, (fmt), (a), (a), (a), (a)) ; \
err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \
}
#define CMP_5_ARGS(line,err,fmt,a) \
{ psf->logindex = 0 ; \
LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a), (a), (a), (a)) ; \
psf_log_printf (psf, (fmt), (a), (a), (a), (a), (a)) ; \
err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \
}
#define CMP_6_ARGS(line,err,fmt,a) \
{ psf->logindex = 0 ; \
LSF_SNPRINTF (buffer, sizeof (buffer), (fmt), (a), (a), (a), (a), (a), (a)) ; \
psf_log_printf (psf, (fmt), (a), (a), (a), (a), (a), (a)) ; \
err += compare_strings_or_die (line, fmt, buffer, psf->logbuffer) ; \
}
static int compare_strings_or_die (int linenum, const char *fmt, const char* s1, const char* s3) ;
int
main (void)
{ static char buffer [2048] ;
SF_PRIVATE sf_private, *psf ;
int k, errors = 0 ;
int int_values [] = { 0, 1, 12, 123, 1234, 123456, -1, -12, -123, -1234, -123456 } ;
printf (" %-24s : ", "psf_log_printf_test") ;
fflush (stdout) ;
psf = &sf_private ;
memset (psf, 0, sizeof (sf_private)) ;
CMP_0_ARGS (__LINE__, errors, " ->%%<- ") ;
/* Test printing of ints. */
for (k = 0 ; k < ARRAY_LEN (int_values) ; k++)
CMP_6_ARGS (__LINE__, errors, "int A : %d, % d, %4d, % 4d, %04d, % 04d", int_values [k]) ;
for (k = 0 ; k < ARRAY_LEN (int_values) ; k++)
CMP_5_ARGS (__LINE__, errors, "int B : %+d, %+4d, %+04d, %-d, %-4d", int_values [k]) ;
for (k = 0 ; k < ARRAY_LEN (int_values) ; k++)
CMP_2_ARGS (__LINE__, errors, "int C : %- d, %- 4d", int_values [k]) ;
/* Test printing of unsigned ints. */
for (k = 0 ; k < ARRAY_LEN (int_values) ; k++)
CMP_4_ARGS (__LINE__, errors, "D : %u, %4u, %04u, %0u", int_values [k]) ;
/* Test printing of hex ints. */
for (k = 0 ; k < ARRAY_LEN (int_values) ; k++)
CMP_4_ARGS (__LINE__, errors, "E : %X, %4X, %04X, %0X", int_values [k]) ;
/* Test printing of strings. */
CMP_4_ARGS (__LINE__, errors, "B %s, %3s, %8s, %-8s", "str") ;
if (errors)
{ puts ("\nExiting due to errors.\n") ;
exit (1) ;
} ;
puts ("ok") ;
return 0 ;
} /* main */
static int
compare_strings_or_die (int linenum, const char *fmt, const char* s1, const char* s2)
{ int errors = 0 ;
/*-puts (s1) ;puts (s2) ;-*/
if (strcmp (s1, s2) != 0)
{ printf ("\n\nLine %d: string compare mismatch:\n\t", linenum) ;
printf ("\"%s\"\n", fmt) ;
printf ("\t\"%s\"\n\t\"%s\"\n", s1, s2) ;
errors ++ ;
} ;
return errors ;
} /* compare_strings_or_die */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 45147310-868b-400a-97e8-cc0a572a6270
*/

View file

@ -0,0 +1,378 @@
/*
** Copyright (C) 2002-2004 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 <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
txw_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return (psf && 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->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 ;
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
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 4d0ba7af-b1c5-46b4-a900-7c6f59fd9a89
*/

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,878 @@
/*
** Copyright (C) 2001-2004 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.
*/
/* RANT:
** The VOC file format is the most brain damaged format I have yet had to deal
** with. No one programmer could have bee stupid enough to put this together.
** Instead it looks like a series of manic, dyslexic assembly language programmers
** hacked it to fit their needs.
** Utterly woeful.
*/
#include "config.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
/*------------------------------------------------------------------------------
* Typedefs for file chunks.
*/
#define VOC_MAX_SECTIONS 200
enum
{ VOC_TERMINATOR = 0,
VOC_SOUND_DATA = 1,
VOC_SOUND_CONTINUE = 2,
VOC_SILENCE = 3,
VOC_MARKER = 4,
VOC_ASCII = 5,
VOC_REPEAT = 6,
VOC_END_REPEAT = 7,
VOC_EXTENDED = 8,
VOC_EXTENDED_II = 9
} ;
typedef struct
{ int samples ;
int offset ; /* Offset of zero => silence. */
} SND_DATA_BLOCKS ;
typedef struct
{ unsigned int sections, section_types ;
int samplerate, channels, bitwidth ;
SND_DATA_BLOCKS blocks [VOC_MAX_SECTIONS] ;
} VOC_DATA ;
/*------------------------------------------------------------------------------
* Private static functions.
*/
static int voc_close (SF_PRIVATE *psf) ;
static int voc_write_header (SF_PRIVATE *psf, int calc_length) ;
static int voc_read_header (SF_PRIVATE *psf) ;
static const char* voc_encoding2str (int encoding) ;
#if 0
/* These functions would be required for files with more than one VOC_SOUND_DATA
** segment. Not sure whether to bother implementing this.
*/
static int voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) ;
static int voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len) ;
static int voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len) ;
static int voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len) ;
static int voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len) ;
static int voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len) ;
static int voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len) ;
static int voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len) ;
static int voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len) ;
#endif
/*------------------------------------------------------------------------------
** Public function.
*/
int
voc_open (SF_PRIVATE *psf)
{ int subformat, error = 0 ;
if (psf->is_pipe)
return SFE_VOC_NO_PIPE ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
{ if ((error = voc_read_header (psf)))
return error ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC)
return SFE_BAD_OPEN_FORMAT ;
psf->endian = SF_ENDIAN_LITTLE ;
if ((error = voc_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = voc_write_header ;
} ;
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
psf->close = voc_close ;
switch (subformat)
{ case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
error = pcm_init (psf) ;
break ;
case SF_FORMAT_ALAW :
error = alaw_init (psf) ;
break ;
case SF_FORMAT_ULAW :
error = ulaw_init (psf) ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
return error ;
} /* voc_open */
/*------------------------------------------------------------------------------
*/
static int
voc_read_header (SF_PRIVATE *psf)
{ VOC_DATA *pvoc ;
char creative [20] ;
unsigned char block_type, rate_byte ;
short version, checksum, encoding, dataoffset ;
int offset ;
/* Set position to start of file to begin reading header. */
offset = psf_binheader_readf (psf, "pb", 0, creative, SIGNED_SIZEOF (creative)) ;
if (creative [sizeof (creative) - 1] != 0x1A)
return SFE_VOC_NO_CREATIVE ;
/* Terminate the string. */
creative [sizeof (creative) - 1] = 0 ;
if (strcmp ("Creative Voice File", creative))
return SFE_VOC_NO_CREATIVE ;
psf_log_printf (psf, "%s\n", creative) ;
offset += psf_binheader_readf (psf, "e222", &dataoffset, &version, &checksum) ;
psf->dataoffset = dataoffset ;
psf_log_printf (psf, "dataoffset : %d\n"
"version : 0x%X\n"
"checksum : 0x%X\n", psf->dataoffset, version, checksum) ;
if (version != 0x010A && version != 0x0114)
return SFE_VOC_BAD_VERSION ;
if (! (psf->fdata = malloc (sizeof (VOC_DATA))))
return SFE_MALLOC_FAILED ;
pvoc = (VOC_DATA*) psf->fdata ;
memset (pvoc, 0, sizeof (VOC_DATA)) ;
/* Set the default encoding now. */
psf->sf.format = SF_FORMAT_VOC ; /* Major format */
encoding = SF_FORMAT_PCM_U8 ; /* Minor format */
psf->endian = SF_ENDIAN_LITTLE ;
while (1)
{ offset += psf_binheader_readf (psf, "1", &block_type) ;
switch (block_type)
{ case VOC_ASCII :
{ int size ;
offset += psf_binheader_readf (psf, "e3", &size) ;
psf_log_printf (psf, " ASCII : %d\n", size) ;
offset += psf_binheader_readf (psf, "b", psf->header, size) ;
psf->header [size] = 0 ;
psf_log_printf (psf, " text : %s\n", psf->header) ;
} ;
continue ;
case VOC_SOUND_DATA :
case VOC_EXTENDED :
case VOC_EXTENDED_II :
break ;
default : psf_log_printf (psf, "*** Weird block marker (%d)\n", block_type) ;
} ;
break ;
} ;
if (block_type == VOC_SOUND_DATA)
{ unsigned char compression ;
int size ;
offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ;
psf->sf.samplerate = 1000000 / (256 - (rate_byte & 0xFF)) ;
psf_log_printf (psf, " Sound Data : %d\n sr : %d => %dHz\n comp : %d\n",
size, rate_byte, psf->sf.samplerate, compression) ;
if (offset + size - 1 > psf->filelength)
{ psf_log_printf (psf, "Seems to be a truncated file.\n") ;
psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
return SFE_VOC_BAD_SECTIONS ;
}
else if (offset + size - 1 < psf->filelength)
{ psf_log_printf (psf, "Seems to be a multi-segment file (#1).\n") ;
psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
return SFE_VOC_BAD_SECTIONS ;
} ;
psf->dataoffset = offset ;
psf->dataend = psf->filelength - 1 ;
psf->sf.channels = 1 ;
psf->bytewidth = 1 ;
psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;
return 0 ;
} ;
if (block_type == VOC_EXTENDED)
{ unsigned char pack, stereo, compression ;
unsigned short rate_short ;
int size ;
offset += psf_binheader_readf (psf, "e3211", &size, &rate_short, &pack, &stereo) ;
psf_log_printf (psf, " Extended : %d\n", size) ;
if (size == 4)
psf_log_printf (psf, " size : 4\n") ;
else
psf_log_printf (psf, " size : %d (should be 4)\n", size) ;
psf_log_printf (psf, " pack : %d\n"
" stereo : %s\n", pack, (stereo ? "yes" : "no")) ;
if (stereo)
{ psf->sf.channels = 2 ;
psf->sf.samplerate = 128000000 / (65536 - rate_short) ;
}
else
{ psf->sf.channels = 1 ;
psf->sf.samplerate = 256000000 / (65536 - rate_short) ;
} ;
psf_log_printf (psf, " sr : %d => %dHz\n", (rate_short & 0xFFFF), psf->sf.samplerate) ;
offset += psf_binheader_readf (psf, "1", &block_type) ;
if (block_type != VOC_SOUND_DATA)
{ psf_log_printf (psf, "*** Expecting VOC_SOUND_DATA section.\n") ;
return SFE_VOC_BAD_FORMAT ;
} ;
offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ;
psf_log_printf (psf, " Sound Data : %d\n"
" sr : %d\n"
" comp : %d\n", size, rate_byte, compression) ;
if (offset + size - 1 > psf->filelength)
{ psf_log_printf (psf, "Seems to be a truncated file.\n") ;
psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
return SFE_VOC_BAD_SECTIONS ;
}
else if (offset + size - 1 < psf->filelength)
{ psf_log_printf (psf, "Seems to be a multi-segment file (#2).\n") ;
psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
return SFE_VOC_BAD_SECTIONS ;
} ;
psf->dataoffset = offset ;
psf->dataend = psf->filelength - 1 ;
psf->bytewidth = 1 ;
psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;
return 0 ;
}
if (block_type == VOC_EXTENDED_II)
{ unsigned char bitwidth, channels ;
int size, fourbytes ;
offset += psf_binheader_readf (psf, "e341124", &size, &psf->sf.samplerate,
&bitwidth, &channels, &encoding, &fourbytes) ;
if (size * 2 == psf->filelength - 39)
{ int temp_size = psf->filelength - 31 ;
psf_log_printf (psf, " Extended II : %d (SoX bug: should be %d)\n", size, temp_size) ;
size = temp_size ;
}
else
psf_log_printf (psf, " Extended II : %d\n", size) ;
psf_log_printf (psf, " sample rate : %d\n"
" bit width : %d\n"
" channels : %d\n", psf->sf.samplerate, bitwidth, channels) ;
if (bitwidth == 16 && encoding == 0)
{ encoding = 4 ;
psf_log_printf (psf, " encoding : 0 (SoX bug: should be 4 for 16 bit signed PCM)\n") ;
}
else
psf_log_printf (psf, " encoding : %d => %s\n", encoding, voc_encoding2str (encoding)) ;
psf_log_printf (psf, " fourbytes : %X\n", fourbytes) ;
psf->sf.channels = channels ;
psf->dataoffset = offset ;
psf->dataend = psf->filelength - 1 ;
if (size + 31 == psf->filelength + 1)
{ /* Hack for reading files produced using
** sf_command (SFC_UPDATE_HEADER_NOW).
*/
psf_log_printf (psf, "Missing zero byte at end of file.\n") ;
size = psf->filelength - 30 ;
psf->dataend = 0 ;
}
else if (size + 31 > psf->filelength)
{ psf_log_printf (psf, "Seems to be a truncated file.\n") ;
size = psf->filelength - 31 ;
}
else if (size + 31 < psf->filelength)
psf_log_printf (psf, "Seems to be a multi-segment file (#3).\n") ;
switch (encoding)
{ case 0 :
psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;
psf->bytewidth = 1 ;
break ;
case 4 :
psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_16 ;
psf->bytewidth = 2 ;
break ;
case 6 :
psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ALAW ;
psf->bytewidth = 1 ;
break ;
case 7 :
psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ULAW ;
psf->bytewidth = 1 ;
break ;
default : /* Unknown */
return SFE_UNKNOWN_FORMAT ;
break ;
} ;
} ;
return 0 ;
} /* voc_read_header */
/*====================================================================================
*/
static int
voc_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t current ;
int rate_const, subformat ;
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) ;
} ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
/* Reset the current header length to zero. */
psf->header [0] = 0 ;
psf->headindex = 0 ;
psf_fseek (psf, 0, SEEK_SET) ;
/* VOC marker and 0x1A byte. */
psf_binheader_writef (psf, "eb1", "Creative Voice File", 19, 0x1A) ;
/* Data offset, version and other. */
psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ;
/* Use same logic as SOX.
** If the file is mono 8 bit data, use VOC_SOUND_DATA.
** If the file is mono 16 bit data, use VOC_EXTENED.
** Otherwise use VOC_EXTENED_2.
*/
if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 1)
{ /* samplerate = 1000000 / (256 - rate_const) ; */
rate_const = 256 - 1000000 / psf->sf.samplerate ;
/* First type marker, length, rate_const and compression */
psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ;
}
else if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 2)
{ /* sample_rate = 128000000 / (65536 - rate_short) ; */
rate_const = 65536 - 128000000 / psf->sf.samplerate ;
/* First write the VOC_EXTENDED section
** marker, length, rate_const and compression
*/
psf_binheader_writef (psf, "e13211", VOC_EXTENDED, 4, rate_const, 0, 1) ;
/* samplerate = 1000000 / (256 - rate_const) ; */
rate_const = 256 - 1000000 / psf->sf.samplerate ;
/* Now write the VOC_SOUND_DATA section
** marker, length, rate_const and compression
*/
psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ;
}
else
{ int length ;
if (psf->sf.channels < 1 || psf->sf.channels > 2)
return SFE_CHANNEL_COUNT ;
switch (subformat)
{ case SF_FORMAT_PCM_U8 :
psf->bytewidth = 1 ;
length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
/* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */
psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ;
break ;
case SF_FORMAT_PCM_16 :
psf->bytewidth = 2 ;
length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
/* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */
psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ;
break ;
case SF_FORMAT_ALAW :
psf->bytewidth = 1 ;
length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 6, 0) ;
break ;
case SF_FORMAT_ULAW :
psf->bytewidth = 1 ;
length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 7, 0) ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
} ;
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 ;
} /* voc_write_header */
static int
voc_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ /* Now we know for certain the length of the file we can re-write
** correct values for the FORM, 8SVX and BODY chunks.
*/
unsigned byte = VOC_TERMINATOR ;
psf_fseek (psf, 0, SEEK_END) ;
/* Write terminator */
psf_fwrite (&byte, 1, 1, psf) ;
voc_write_header (psf, SF_TRUE) ;
} ;
return 0 ;
} /* voc_close */
static const char*
voc_encoding2str (int encoding)
{
switch (encoding)
{ case 0 : return "8 bit unsigned PCM" ;
case 4 : return "16 bit signed PCM" ;
case 6 : return "A-law" ;
case 7 : return "u-law" ;
default : break ;
}
return "*** Unknown ***" ;
} /* voc_encoding2str */
/*====================================================================================
*/
#if 0
static int
voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc)
{
psf->sf.frames = 0 ;
if (pvoc->bitwidth == 8)
{ psf->read_short = voc_multi_read_uc2s ;
psf->read_int = voc_multi_read_uc2i ;
psf->read_float = voc_multi_read_uc2f ;
psf->read_double = voc_multi_read_uc2d ;
return 0 ;
} ;
if (pvoc->bitwidth == 16)
{ psf->read_short = voc_multi_read_les2s ;
psf->read_int = voc_multi_read_les2i ;
psf->read_float = voc_multi_read_les2f ;
psf->read_double = voc_multi_read_les2d ;
return 0 ;
} ;
psf_log_printf (psf, "Error : bitwith != 8 && bitwidth != 16.\n") ;
return SFE_UNIMPLEMENTED ;
} /* voc_multi_read_int */
/*------------------------------------------------------------------------------------
*/
static int
voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len)
{
return 0 ;
} /* voc_multi_read_uc2s */
static int
voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len)
{
return 0 ;
} /* voc_multi_read_les2s */
static int
voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len)
{
return 0 ;
} /* voc_multi_read_uc2i */
static int
voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len)
{
return 0 ;
} /* voc_multi_read_les2i */
static int
voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len)
{
return 0 ;
} /* voc_multi_read_uc2f */
static int
voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len)
{
return 0 ;
} /* voc_multi_read_les2f */
static int
voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len)
{
return 0 ;
} /* voc_multi_read_uc2d */
static int
voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len)
{
return 0 ;
} /* voc_multi_read_les2d */
#endif
/*------------------------------------------------------------------------------------
Creative Voice (VOC) file format
--------------------------------
~From: galt@dsd.es.com
(byte numbers are hex!)
HEADER (bytes 00-19)
Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
- ---------------------------------------------------------------
HEADER:
=======
byte # Description
------ ------------------------------------------
00-12 "Creative Voice File"
13 1A (eof to abort printing of file)
14-15 Offset of first datablock in .voc file (std 1A 00
in Intel Notation)
16-17 Version number (minor,major) (VOC-HDR puts 0A 01)
18-19 1's Comp of Ver. # + 1234h (VOC-HDR puts 29 11)
- ---------------------------------------------------------------
DATA BLOCK:
===========
Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes)
NOTE: Terminator Block is an exception -- it has only the TYPE byte.
TYPE Description Size (3-byte int) Info
---- ----------- ----------------- -----------------------
00 Terminator (NONE) (NONE)
01 Sound data 2+length of data *
02 Sound continue length of data Voice Data
03 Silence 3 **
04 Marker 2 Marker# (2 bytes)
05 ASCII length of string null terminated string
06 Repeat 2 Count# (2 bytes)
07 End repeat 0 (NONE)
08 Extended 4 ***
*Sound Info Format:
---------------------
00 Sample Rate
01 Compression Type
02+ Voice Data
**Silence Info Format:
----------------------------
00-01 Length of silence - 1
02 Sample Rate
***Extended Info Format:
---------------------
00-01 Time Constant: Mono: 65536 - (256000000/sample_rate)
Stereo: 65536 - (25600000/(2*sample_rate))
02 Pack
03 Mode: 0 = mono
1 = stereo
Marker# -- Driver keeps the most recent marker in a status byte
Count# -- Number of repetitions + 1
Count# may be 1 to FFFE for 0 - FFFD repetitions
or FFFF for endless repetitions
Sample Rate -- SR byte = 256-(1000000/sample_rate)
Length of silence -- in units of sampling cycle
Compression Type -- of voice data
8-bits = 0
4-bits = 1
2.6-bits = 2
2-bits = 3
Multi DAC = 3+(# of channels) [interesting--
this isn't in the developer's manual]
---------------------------------------------------------------------------------
Addendum submitted by Votis Kokavessis:
After some experimenting with .VOC files I found out that there is a Data Block
Type 9, which is not covered in the VOC.TXT file. Here is what I was able to discover
about this block type:
TYPE: 09
SIZE: 12 + length of data
INFO: 12 (twelve) bytes
INFO STRUCTURE:
Bytes 0-1: (Word) Sample Rate (e.g. 44100)
Bytes 2-3: zero (could be that bytes 0-3 are a DWord for Sample Rate)
Byte 4: Sample Size in bits (e.g. 16)
Byte 5: Number of channels (e.g. 1 for mono, 2 for stereo)
Byte 6: Unknown (equal to 4 in all files I examined)
Bytes 7-11: zero
-------------------------------------------------------------------------------------*/
/*=====================================================================================
**=====================================================================================
**=====================================================================================
**=====================================================================================
*/
/*------------------------------------------------------------------------
The following is taken from the Audio File Formats FAQ dated 2-Jan-1995
and submitted by Guido van Rossum <guido@cwi.nl>.
--------------------------------------------------------------------------
Creative Voice (VOC) file format
--------------------------------
From: galt@dsd.es.com
(byte numbers are hex!)
HEADER (bytes 00-19)
Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
- ---------------------------------------------------------------
HEADER:
-------
byte # Description
------ ------------------------------------------
00-12 "Creative Voice File"
13 1A (eof to abort printing of file)
14-15 Offset of first datablock in .voc file (std 1A 00
in Intel Notation)
16-17 Version number (minor,major) (VOC-HDR puts 0A 01)
18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11)
- ---------------------------------------------------------------
DATA BLOCK:
-----------
Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes)
NOTE: Terminator Block is an exception -- it has only the TYPE byte.
TYPE Description Size (3-byte int) Info
---- ----------- ----------------- -----------------------
00 Terminator (NONE) (NONE)
01 Sound data 2+length of data *
02 Sound continue length of data Voice Data
03 Silence 3 **
04 Marker 2 Marker# (2 bytes)
05 ASCII length of string null terminated string
06 Repeat 2 Count# (2 bytes)
07 End repeat 0 (NONE)
08 Extended 4 ***
*Sound Info Format: **Silence Info Format:
--------------------- ----------------------------
00 Sample Rate 00-01 Length of silence - 1
01 Compression Type 02 Sample Rate
02+ Voice Data
***Extended Info Format:
---------------------
00-01 Time Constant: Mono: 65536 - (256000000/sample_rate)
Stereo: 65536 - (25600000/(2*sample_rate))
02 Pack
03 Mode: 0 = mono
1 = stereo
Marker# -- Driver keeps the most recent marker in a status byte
Count# -- Number of repetitions + 1
Count# may be 1 to FFFE for 0 - FFFD repetitions
or FFFF for endless repetitions
Sample Rate -- SR byte = 256-(1000000/sample_rate)
Length of silence -- in units of sampling cycle
Compression Type -- of voice data
8-bits = 0
4-bits = 1
2.6-bits = 2
2-bits = 3
Multi DAC = 3+(# of channels) [interesting--
this isn't in the developer's manual]
Detailed description of new data blocks (VOC files version 1.20 and above):
(Source is fax from Barry Boone at Creative Labs, 405/742-6622)
BLOCK 8 - digitized sound attribute extension, must preceed block 1.
Used to define stereo, 8 bit audio
BYTE bBlockID; // = 8
BYTE nBlockLen[3]; // 3 byte length
WORD wTimeConstant; // time constant = same as block 1
BYTE bPackMethod; // same as in block 1
BYTE bVoiceMode; // 0-mono, 1-stereo
Data is stored left, right
BLOCK 9 - data block that supersedes blocks 1 and 8.
Used for stereo, 16 bit.
BYTE bBlockID; // = 9
BYTE nBlockLen[3]; // length 12 plus length of sound
DWORD dwSamplesPerSec; // samples per second, not time const.
BYTE bBitsPerSample; // e.g., 8 or 16
BYTE bChannels; // 1 for mono, 2 for stereo
WORD wFormat; // see below
BYTE reserved[4]; // pad to make block w/o data
// have a size of 16 bytes
Valid values of wFormat are:
0x0000 8-bit unsigned PCM
0x0001 Creative 8-bit to 4-bit ADPCM
0x0002 Creative 8-bit to 3-bit ADPCM
0x0003 Creative 8-bit to 2-bit ADPCM
0x0004 16-bit signed PCM
0x0006 CCITT a-Law
0x0007 CCITT u-Law
0x02000 Creative 16-bit to 4-bit ADPCM
Data is stored left, right
------------------------------------------------------------------------*/
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 40a50167-a81c-463a-9e1d-3282ff84e09d
*/

View file

@ -0,0 +1,537 @@
/*
** Copyright (C) 2002-2004 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 is the OKI / Dialogic ADPCM encoder/decoder. It converts from
** 12 bit linear sample data to a 4 bit ADPCM.
**
** Implemented from the description found here:
**
** http://www.comptek.ru:8100/telephony/tnotes/tt1-13.html
**
** and compared against the encoder/decoder found here:
**
** http://ibiblio.org/pub/linux/apps/sound/convert/vox.tar.gz
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "float_cast.h"
#include "common.h"
#define VOX_DATA_LEN 2048
#define PCM_DATA_LEN (VOX_DATA_LEN *2)
typedef struct
{ short last ;
short step_index ;
int vox_bytes, pcm_samples ;
unsigned char vox_data [VOX_DATA_LEN] ;
short pcm_data [PCM_DATA_LEN] ;
} VOX_ADPCM_PRIVATE ;
static int vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox) ;
static int vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox) ;
static short vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox) ;
static char vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox) ;
static sf_count_t vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t vox_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t vox_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t vox_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t vox_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static int vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) ;
static int vox_write_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len) ;
/*============================================================================================
** Predefined OKI ADPCM encoder/decoder tables.
*/
static short step_size_table [49] =
{ 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, 1408, 1552
} ; /* step_size_table */
static short step_adjust_table [8] =
{ -1, -1, -1, -1, 2, 4, 6, 8
} ; /* step_adjust_table */
/*------------------------------------------------------------------------------
*/
int
vox_adpcm_init (SF_PRIVATE *psf)
{ VOX_ADPCM_PRIVATE *pvox = NULL ;
if (psf->mode == SFM_RDWR)
return SFE_BAD_MODE_RW ;
if (psf->mode == SFM_WRITE && psf->sf.channels != 1)
return SFE_CHANNEL_COUNT ;
if ((pvox = malloc (sizeof (VOX_ADPCM_PRIVATE))) == NULL)
return SFE_MALLOC_FAILED ;
psf->fdata = (void*) pvox ;
memset (pvox, 0, sizeof (VOX_ADPCM_PRIVATE)) ;
if (psf->mode == SFM_WRITE)
{ psf->write_short = vox_write_s ;
psf->write_int = vox_write_i ;
psf->write_float = vox_write_f ;
psf->write_double = vox_write_d ;
}
else
{ psf_log_printf (psf, "Header-less OKI Dialogic ADPCM encoded file.\n") ;
psf_log_printf (psf, "Setting up for 8kHz, mono, Vox ADPCM.\n") ;
psf->read_short = vox_read_s ;
psf->read_int = vox_read_i ;
psf->read_float = vox_read_f ;
psf->read_double = vox_read_d ;
} ;
/* Standard sample rate chennels etc. */
if (psf->sf.samplerate < 1)
psf->sf.samplerate = 8000 ;
psf->sf.channels = 1 ;
psf->sf.frames = psf->filelength * 2 ;
psf->sf.seekable = SF_FALSE ;
/* Seek back to start of data. */
if (psf_fseek (psf, 0 , SEEK_SET) == -1)
return SFE_BAD_SEEK ;
return 0 ;
} /* vox_adpcm_init */
/*------------------------------------------------------------------------------
*/
static char
vox_adpcm_encode (short samp, VOX_ADPCM_PRIVATE *pvox)
{ short code ;
short diff, error, stepsize ;
stepsize = step_size_table [pvox->step_index] ;
code = 0 ;
diff = samp - pvox->last ;
if (diff < 0)
{ code = 0x08 ;
error = -diff ;
}
else
error = diff ;
if (error >= stepsize)
{ code = code | 0x04 ;
error -= stepsize ;
} ;
if (error >= stepsize / 2)
{ code = code | 0x02 ;
error -= stepsize / 2 ;
} ;
if (error >= stepsize / 4)
code = code | 0x01 ;
/*
** To close the feedback loop, the deocder is used to set the
** estimate of last sample and in doing so, also set the step_index.
*/
pvox->last = vox_adpcm_decode (code, pvox) ;
return code ;
} /* vox_adpcm_encode */
static short
vox_adpcm_decode (char code, VOX_ADPCM_PRIVATE *pvox)
{ short diff, error, stepsize, samp ;
stepsize = step_size_table [pvox->step_index] ;
error = stepsize / 8 ;
if (code & 0x01)
error += stepsize / 4 ;
if (code & 0x02)
error += stepsize / 2 ;
if (code & 0x04)
error += stepsize ;
diff = (code & 0x08) ? -error : error ;
samp = pvox->last + diff ;
/*
** Apply clipping.
*/
if (samp > 2048)
samp = 2048 ;
if (samp < -2048)
samp = -2048 ;
pvox->last = samp ;
pvox->step_index += step_adjust_table [code & 0x7] ;
if (pvox->step_index < 0)
pvox->step_index = 0 ;
if (pvox->step_index > 48)
pvox->step_index = 48 ;
return samp ;
} /* vox_adpcm_decode */
static int
vox_adpcm_encode_block (VOX_ADPCM_PRIVATE *pvox)
{ unsigned char code ;
int j, k ;
/* If data_count is odd, add an extra zero valued sample. */
if (pvox->pcm_samples & 1)
pvox->pcm_data [pvox->pcm_samples++] = 0 ;
for (j = k = 0 ; k < pvox->pcm_samples ; j++)
{ code = vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) << 4 ;
code |= vox_adpcm_encode (pvox->pcm_data [k++] / 16, pvox) ;
pvox->vox_data [j] = code ;
} ;
pvox->vox_bytes = j ;
return 0 ;
} /* vox_adpcm_encode_block */
static int
vox_adpcm_decode_block (VOX_ADPCM_PRIVATE *pvox)
{ unsigned char code ;
int j, k ;
for (j = k = 0 ; j < pvox->vox_bytes ; j++)
{ code = pvox->vox_data [j] ;
pvox->pcm_data [k++] = 16 * vox_adpcm_decode ((code >> 4) & 0x0f, pvox) ;
pvox->pcm_data [k++] = 16 * vox_adpcm_decode (code & 0x0f, pvox) ;
} ;
pvox->pcm_samples = k ;
return 0 ;
} /* vox_adpcm_decode_block */
/*==============================================================================
*/
static int
vox_read_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len)
{ int indx = 0, k ;
while (indx < len)
{ pvox->vox_bytes = (len - indx > PCM_DATA_LEN) ? VOX_DATA_LEN : (len - indx + 1) / 2 ;
if ((k = psf_fread (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes)
{ if (psf_ftell (psf) + k != psf->filelength)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ;
if (k == 0)
break ;
} ;
pvox->vox_bytes = k ;
vox_adpcm_decode_block (pvox) ;
memcpy (&(ptr [indx]), pvox->pcm_data, pvox->pcm_samples * sizeof (short)) ;
indx += pvox->pcm_samples ;
} ;
return indx ;
} /* vox_read_block */
static sf_count_t
vox_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
int readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
while (len > 0)
{ readcount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = vox_read_block (psf, pvox, ptr, readcount) ;
total += count ;
len -= count ;
if (count != readcount)
break ;
} ;
return total ;
} /* vox_read_s */
static sf_count_t
vox_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
short *sptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
sptr = psf->u.sbuf ;
bufferlen = ARRAY_LEN (psf->u.sbuf) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : (int) len ;
count = vox_read_block (psf, pvox, 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 ;
} /* vox_read_i */
static sf_count_t
vox_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
short *sptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
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 = vox_read_block (psf, pvox, 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 ;
} /* vox_read_f */
static sf_count_t
vox_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
short *sptr ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
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 = vox_read_block (psf, pvox, 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 ;
} /* vox_read_d */
/*------------------------------------------------------------------------------
*/
static int
vox_write_block (SF_PRIVATE *psf, VOX_ADPCM_PRIVATE *pvox, short *ptr, int len)
{ int indx = 0, k ;
while (indx < len)
{ pvox->pcm_samples = (len - indx > PCM_DATA_LEN) ? PCM_DATA_LEN : len - indx ;
memcpy (pvox->pcm_data, &(ptr [indx]), pvox->pcm_samples * sizeof (short)) ;
vox_adpcm_encode_block (pvox) ;
if ((k = psf_fwrite (pvox->vox_data, 1, pvox->vox_bytes, psf)) != pvox->vox_bytes)
psf_log_printf (psf, "*** Warning : short read (%d != %d).\n", k, pvox->vox_bytes) ;
indx += pvox->pcm_samples ;
} ;
return indx ;
} /* vox_write_block */
static sf_count_t
vox_write_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
int writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
while (len)
{ writecount = (len > 0x10000000) ? 0x10000000 : (int) len ;
count = vox_write_block (psf, pvox, ptr, writecount) ;
total += count ;
len -= count ;
if (count != writecount)
break ;
} ;
return total ;
} /* vox_write_s */
static sf_count_t
vox_write_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
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 = vox_write_block (psf, pvox, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* vox_write_i */
static sf_count_t
vox_write_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
float normfact ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
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 = vox_write_block (psf, pvox, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* vox_write_f */
static sf_count_t
vox_write_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ VOX_ADPCM_PRIVATE *pvox ;
short *sptr ;
int k, bufferlen, writecount, count ;
sf_count_t total = 0 ;
double normfact ;
if (! psf->fdata)
return 0 ;
pvox = (VOX_ADPCM_PRIVATE*) psf->fdata ;
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 = vox_write_block (psf, pvox, sptr, writecount) ;
total += count ;
len -= writecount ;
if (count != writecount)
break ;
} ;
return total ;
} /* vox_write_d */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: e15e97fe-ff9d-4b46-a489-7059fb2d0b1e
*/

View file

@ -0,0 +1,581 @@
/*
** Copyright (C) 1999-2004 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 <stdio.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include "sndfile.h"
#include "config.h"
#include "sfendian.h"
#include "common.h"
#include "wav_w64.h"
/*------------------------------------------------------------------------------
** W64 files use 16 byte markers as opposed to the four byte marker of
** WAV files.
** For comparison purposes, an integer is required, so make an integer
** hash for the 16 bytes using MAKE_HASH16 macro, but also create a 16
** byte array containing the complete 16 bytes required when writing the
** header.
*/
#define MAKE_HASH16(x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \
( (x0) ^ ((x1) << 1) ^ ((x2) << 2) ^ ((x3) << 3) ^ \
((x4) << 4) ^ ((x5) << 5) ^ ((x6) << 6) ^ ((x7) << 7) ^ \
((x8) << 8) ^ ((x9) << 9) ^ ((xa) << 10) ^ ((xb) << 11) ^ \
((xc) << 12) ^ ((xd) << 13) ^ ((xe) << 14) ^ ((xf) << 15) )
#define MAKE_MARKER16(name,x0,x1,x2,x3,x4,x5,x6,x7,x8,x9,xa,xb,xc,xd,xe,xf) \
static unsigned char name [16] = { (x0), (x1), (x2), (x3), (x4), (x5), \
(x6), (x7), (x8), (x9), (xa), (xb), (xc), (xd), (xe), (xf) }
#define riff_HASH16 MAKE_HASH16 ('r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11, 0xA5, \
0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00)
#define wave_HASH16 MAKE_HASH16 ('w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11, \
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
#define fmt_HASH16 MAKE_HASH16 ('f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11, \
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
#define fact_HASH16 MAKE_HASH16 ('f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11, \
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
#define data_HASH16 MAKE_HASH16 ('d', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11, \
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A)
#define ACID_HASH16 MAKE_HASH16 (0x6D, 0x07, 0x1C, 0xEA, 0xA3, 0xEF, 0x78, 0x4C, \
0x90, 0x57, 0x7F, 0x79, 0xEE, 0x25, 0x2A, 0xAE)
MAKE_MARKER16 (riff_MARKER16, 'r', 'i', 'f', 'f', 0x2E, 0x91, 0xCF, 0x11,
0xA5, 0xD6, 0x28, 0xDB, 0x04, 0xC1, 0x00, 0x00) ;
MAKE_MARKER16 (wave_MARKER16, 'w', 'a', 'v', 'e', 0xF3, 0xAC, 0xD3, 0x11,
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
MAKE_MARKER16 (fmt_MARKER16, 'f', 'm', 't', ' ', 0xF3, 0xAC, 0xD3, 0x11,
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
MAKE_MARKER16 (fact_MARKER16, 'f', 'a', 'c', 't', 0xF3, 0xAC, 0xD3, 0x11,
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
MAKE_MARKER16 (data_MARKER16, 'd', 'a', 't', 'a', 0xF3, 0xAC, 0xD3, 0x11,
0x8C, 0xD1, 0x00, 0xC0, 0x4F, 0x8E, 0xDB, 0x8A) ;
enum
{ HAVE_riff = 0x01,
HAVE_wave = 0x02,
HAVE_fmt = 0x04,
HAVE_fact = 0x08,
HAVE_data = 0x20
} ;
/*------------------------------------------------------------------------------
* Private static functions.
*/
static int w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ;
static int w64_write_header (SF_PRIVATE *psf, int calc_length) ;
static int w64_close (SF_PRIVATE *psf) ;
/*------------------------------------------------------------------------------
** Public function.
*/
int
w64_open (SF_PRIVATE *psf)
{ int subformat, error, blockalign = 0, framesperblock = 0 ;
if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR &&psf->filelength > 0))
{ if ((error = w64_read_header (psf, &blockalign, &framesperblock)))
return error ;
} ;
if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_W64)
return SFE_BAD_OPEN_FORMAT ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
{ if (psf->is_pipe)
return SFE_NO_PIPE_WRITE ;
psf->endian = SF_ENDIAN_LITTLE ; /* All W64 files are little endian. */
psf->blockwidth = psf->bytewidth * psf->sf.channels ;
if (subformat == SF_FORMAT_IMA_ADPCM || subformat == SF_FORMAT_MS_ADPCM)
{ blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
framesperblock = -1 ;
/* FIXME : This block must go */
psf->filelength = SF_COUNT_MAX ;
psf->datalength = psf->filelength ;
if (psf->sf.frames <= 0)
psf->sf.frames = (psf->blockwidth) ? psf->filelength / psf->blockwidth : psf->filelength ;
/* EMXIF : This block must go */
} ;
if ((error = w64_write_header (psf, SF_FALSE)))
return error ;
psf->write_header = w64_write_header ;
} ;
psf->close = w64_close ;
switch (subformat)
{ 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 ;
/* Lite remove start */
case SF_FORMAT_FLOAT :
error = float32_init (psf) ;
break ;
case SF_FORMAT_DOUBLE :
error = double64_init (psf) ;
break ;
case SF_FORMAT_IMA_ADPCM :
error = wav_w64_ima_init (psf, blockalign, framesperblock) ;
break ;
case SF_FORMAT_MS_ADPCM :
error = wav_w64_msadpcm_init (psf, blockalign, framesperblock) ;
break ;
/* Lite remove end */
case SF_FORMAT_GSM610 :
error = gsm610_init (psf) ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
return error ;
} /* w64_open */
/*=========================================================================
** Private functions.
*/
static int
w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock)
{ WAV_FMT wav_fmt ;
int dword = 0, marker, format = 0 ;
sf_count_t chunk_size, bytesread = 0 ;
int parsestage = 0, error, done = 0 ;
/* Set position to start of file to begin reading header. */
psf_binheader_readf (psf, "p", 0) ;
while (! done)
{ /* Read the 4 byte marker and jump 12 bytes. */
bytesread += psf_binheader_readf (psf, "h", &marker) ;
chunk_size = 0 ;
switch (marker)
{ case riff_HASH16 :
if (parsestage)
return SFE_W64_NO_RIFF ;
bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ;
if (psf->filelength < chunk_size)
psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ;
else
psf_log_printf (psf, "riff : %D\n", chunk_size) ;
parsestage |= HAVE_riff ;
break ;
case ACID_HASH16:
psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ;
return SFE_UNIMPLEMENTED ;
case wave_HASH16 :
if ((parsestage & HAVE_riff) != HAVE_riff)
return SFE_W64_NO_WAVE ;
psf_log_printf (psf, "wave\n") ;
parsestage |= HAVE_wave ;
break ;
case fmt_HASH16 :
if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave))
return SFE_W64_NO_FMT ;
bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ;
psf_log_printf (psf, " fmt : %D\n", chunk_size) ;
/* size of 16 byte marker and 8 byte chunk_size value. */
chunk_size -= 24 ;
if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, (int) chunk_size)))
return error ;
if (chunk_size % 8)
psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ;
format = wav_fmt.format ;
parsestage |= HAVE_fmt ;
break ;
case fact_HASH16:
{ sf_count_t frames ;
psf_binheader_readf (psf, "e88", &chunk_size, &frames) ;
psf_log_printf (psf, " fact : %D\n frames : %D\n",
chunk_size, frames) ;
} ;
break ;
case data_HASH16 :
if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt))
return SFE_W64_NO_DATA ;
psf_binheader_readf (psf, "e8", &chunk_size) ;
psf->dataoffset = psf_ftell (psf) ;
psf->datalength = chunk_size - 24 ;
if (chunk_size % 8)
chunk_size += 8 - (chunk_size % 8) ;
psf_log_printf (psf, "data : %D\n", chunk_size) ;
parsestage |= HAVE_data ;
if (! psf->sf.seekable)
break ;
/* Seek past data and continue reading header. */
psf_fseek (psf, chunk_size, SEEK_CUR) ;
break ;
default :
if (psf_ftell (psf) & 0x0F)
{ 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 = SF_TRUE ;
break ;
} ; /* switch (dword) */
if (psf->sf.seekable == 0 && (parsestage & HAVE_data))
break ;
if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword))))
break ;
if (psf->logindex >= SIGNED_SIZEOF (psf->logbuffer) - 2)
return SFE_LOG_OVERRUN ;
} ; /* while (1) */
if (! psf->dataoffset)
return SFE_W64_NO_DATA ;
psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */
if (psf_ftell (psf) != psf->dataoffset)
psf_fseek (psf, psf->dataoffset, SEEK_SET) ;
psf->close = w64_close ;
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 ;
} ;
switch (format)
{ case WAVE_FORMAT_PCM :
case WAVE_FORMAT_EXTENSIBLE :
/* extensible might be FLOAT, MULAW, etc as well! */
psf->sf.format = SF_FORMAT_W64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ;
break ;
case WAVE_FORMAT_MULAW :
psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ;
break ;
case WAVE_FORMAT_ALAW :
psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ;
break ;
case WAVE_FORMAT_MS_ADPCM :
psf->sf.format = (SF_FORMAT_W64 | 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_W64 | SF_FORMAT_IMA_ADPCM) ;
*blockalign = wav_fmt.ima.blockalign ;
*framesperblock = wav_fmt.ima.samplesperblock ;
break ;
case WAVE_FORMAT_GSM610 :
psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ;
break ;
case WAVE_FORMAT_IEEE_FLOAT :
psf->sf.format = SF_FORMAT_W64 ;
psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
return 0 ;
} /* w64_read_header */
static int
w64_write_header (SF_PRIVATE *psf, int calc_length)
{ sf_count_t fmt_size, current ;
size_t fmt_pad = 0 ;
int subformat, add_fact_chunk = SF_FALSE ;
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)
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) ;
/* riff marker, length, wave and 'fmt ' markers. */
psf_binheader_writef (psf, "eh8hh", riff_MARKER16, psf->filelength - 8, wave_MARKER16, fmt_MARKER16) ;
subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
switch (subformat)
{ case SF_FORMAT_PCM_U8 :
case SF_FORMAT_PCM_16 :
case SF_FORMAT_PCM_24 :
case SF_FORMAT_PCM_32 :
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : format, channels, samplerate */
psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_PCM, psf->sf.channels, psf->sf.samplerate) ;
/* fmt : bytespersec */
psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
/* fmt : blockalign, bitwidth */
psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
break ;
case SF_FORMAT_FLOAT :
case SF_FORMAT_DOUBLE :
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : format, channels, samplerate */
psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_IEEE_FLOAT, psf->sf.channels, psf->sf.samplerate) ;
/* fmt : bytespersec */
psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
/* fmt : blockalign, bitwidth */
psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, psf->bytewidth * 8) ;
add_fact_chunk = SF_TRUE ;
break ;
case SF_FORMAT_ULAW :
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : format, channels, samplerate */
psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_MULAW, psf->sf.channels, psf->sf.samplerate) ;
/* fmt : bytespersec */
psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
/* fmt : blockalign, bitwidth */
psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ;
add_fact_chunk = SF_TRUE ;
break ;
case SF_FORMAT_ALAW :
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : format, channels, samplerate */
psf_binheader_writef (psf, "e8224", fmt_size, WAVE_FORMAT_ALAW, psf->sf.channels, psf->sf.samplerate) ;
/* fmt : bytespersec */
psf_binheader_writef (psf, "e4", psf->sf.samplerate * psf->bytewidth * psf->sf.channels) ;
/* fmt : blockalign, bitwidth */
psf_binheader_writef (psf, "e22", psf->bytewidth * psf->sf.channels, 8) ;
add_fact_chunk = SF_TRUE ;
break ;
/* Lite remove start */
case SF_FORMAT_IMA_ADPCM :
{ int blockalign, framesperblock, bytespersec ;
blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
framesperblock = 2 * (blockalign - 4 * psf->sf.channels) / psf->sf.channels + 1 ;
bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ;
/* fmt chunk. */
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : size, WAV format type, channels. */
psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_IMA_ADPCM, psf->sf.channels) ;
/* fmt : samplerate, bytespersec. */
psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
/* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
psf_binheader_writef (psf, "e2222", blockalign, 4, 2, framesperblock) ;
} ;
add_fact_chunk = SF_TRUE ;
break ;
case SF_FORMAT_MS_ADPCM :
{ int blockalign, framesperblock, bytespersec, extrabytes ;
blockalign = wav_w64_srate2blocksize (psf->sf.samplerate * psf->sf.channels) ;
framesperblock = 2 + 2 * (blockalign - 7 * psf->sf.channels) / psf->sf.channels ;
bytespersec = (psf->sf.samplerate * blockalign) / framesperblock ;
/* fmt chunk. */
extrabytes = 2 + 2 + MSADPCM_ADAPT_COEFF_COUNT * (2 + 2) ;
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + extrabytes ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : size, W64 format type, channels. */
psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_MS_ADPCM, psf->sf.channels) ;
/* fmt : samplerate, bytespersec. */
psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
/* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
psf_binheader_writef (psf, "e22222", blockalign, 4, extrabytes, framesperblock, 7) ;
msadpcm_write_adapt_coeffs (psf) ;
} ;
add_fact_chunk = SF_TRUE ;
break ;
/* Lite remove end */
case SF_FORMAT_GSM610 :
{ int bytespersec ;
bytespersec = (psf->sf.samplerate * WAV_W64_GSM610_BLOCKSIZE) / WAV_W64_GSM610_SAMPLES ;
/* fmt chunk. */
fmt_size = 24 + 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 ;
fmt_pad = (size_t) (8 - (fmt_size & 0x7)) ;
fmt_size += fmt_pad ;
/* fmt : size, WAV format type, channels. */
psf_binheader_writef (psf, "e822", fmt_size, WAVE_FORMAT_GSM610, psf->sf.channels) ;
/* fmt : samplerate, bytespersec. */
psf_binheader_writef (psf, "e44", psf->sf.samplerate, bytespersec) ;
/* fmt : blockalign, bitwidth, extrabytes, framesperblock. */
psf_binheader_writef (psf, "e2222", WAV_W64_GSM610_BLOCKSIZE, 0, 2, WAV_W64_GSM610_SAMPLES) ;
} ;
add_fact_chunk = SF_TRUE ;
break ;
default : return SFE_UNIMPLEMENTED ;
} ;
/* Pad to 8 bytes with zeros. */
if (fmt_pad > 0)
psf_binheader_writef (psf, "z", fmt_pad) ;
if (add_fact_chunk)
psf_binheader_writef (psf, "eh88", fact_MARKER16, 16 + 8 + 8, psf->sf.frames) ;
psf_binheader_writef (psf, "eh8", data_MARKER16, psf->datalength + 24) ;
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 ;
} /* w64_write_header */
static int
w64_close (SF_PRIVATE *psf)
{
if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
w64_write_header (psf, SF_TRUE) ;
return 0 ;
} /* w64_close */
/*
** Do not edit or modify anything in this comment block.
** The arch-tag line is a file identity tag for the GNU Arch
** revision control system.
**
** arch-tag: 9aa4e141-538a-4dd9-99c9-b3f0f2dd4f4a
*/

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more