1
0
mirror of https://github.com/nu774/fdkaac.git synced 2025-06-05 23:29:14 +02:00

19 Commits

Author SHA1 Message Date
a7c2411335 bump version 2014-08-13 15:40:24 +09:00
b54538f79e apply limiter when input is float 2014-08-13 09:26:26 +09:00
a7e00a4219 refactor pcm reader framework 2014-08-12 23:43:19 +09:00
b667da2b01 update ChangeLog 2014-07-30 14:11:04 +09:00
a79a11ef99 win32compat: fix aacenc_printf() not to write junk characters 2014-07-30 14:09:12 +09:00
70554c0791 write INSTALL 2014-05-12 16:46:49 +09:00
a854b113ae update COPYING (patch from darealshinji) 2014-03-14 11:10:15 +09:00
f7a24bf87b update ChangeLog 2014-02-17 13:58:54 +09:00
5063c6dce1 bump version 2014-02-17 13:55:08 +09:00
57aa91419d fix: CAF chan chunk using channel bitmap was not correctly handled 2014-02-17 13:51:20 +09:00
b3dcf08647 update ChangeLog 2014-01-18 17:47:03 +09:00
a7c4895534 bump version 2014-01-18 17:44:51 +09:00
209130e887 fix reading of caf file without chan chunk
Since channel map was not initialized, first channel was copied to every
other channel.
2014-01-18 17:41:57 +09:00
b6ab92a9e7 Merge pull request #9 from rbrito/fix-typo
README: Fix typo in bandwidth to match CLI options.
2013-11-17 22:02:43 -08:00
e18fe91a40 man: Regen manpage with hyphens escaped.
Otherwise, automated verification programs like Debian's lintian complain
about them.

Signed-off-by: Rogério Brito <rbrito@ime.usp.br>
2013-11-18 02:55:18 -02:00
472e82e42f README: Remove trailing whitespaces that end up in the manpages.
Signed-off-by: Rogério Brito <rbrito@ime.usp.br>
2013-11-18 02:52:35 -02:00
ce0833f8e5 README: Fix typo in bandwidth to match CLI options.
Signed-off-by: Rogério Brito <rbrito@ime.usp.br>
2013-11-18 02:48:39 -02:00
661f883dce add genman.sh, update fdkaac.1 2013-11-08 23:18:20 +09:00
b815f858d0 update ChangeLog 2013-11-08 12:49:19 +09:00
25 changed files with 945 additions and 794 deletions

111
COPYING
View File

@ -1,17 +1,108 @@
Copyright (C) 2013 nu774
Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
Upstream-Name: fdkaac
Upstream-Contact: nu774 <honeycomb77@gmail.com>
Source: https://github.com/nu774/fdkaac
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
Files: *
Copyright: 2013-2014 nu774 <honeycomb77@gmail.com>
License: Zlib
1. The origin of this software must not be misrepresented; you must not
Files: missings/getopt.c
Copyright: 2002 Todd C. Miller <Todd.Miller@courtesan.com>
2000 The NetBSD Foundation, Inc.
License: BSD-4-clause
Files: missings/getopt.h
Copyright: 2000 The NetBSD Foundation, Inc.
License: BSD-4-clause
Files: src/parson.*
Copyright: 2012 Krzysztof Gabis
License: MIT
Files: src/lpc.h
Copyright: 1994-2007 the Xiph.Org Foundation
License: BSD
Files: src/lpc.c
Copyright: 1994-2007 the Xiph.Org Foundation
1992, 1993, 1994 Jutta Degener and Carsten Bormann, Technische Universität Berlin
License: BSD-style
License: Zlib
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
.
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
3. This notice may not be removed or altered from any source distribution.
License: MIT
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
.
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
License: BSD-4-clause
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. 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.
3. All advertising materials mentioning features or use of this software
must display the following acknowledgement:
This product includes software developed by the NetBSD
Foundation, Inc. and its contributors.
4. Neither the name of The NetBSD Foundation nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
.
THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
License: BSD-style
Any use of this software is permitted provided that this notice is not
removed and that neither the authors nor the Technische Universita"t
Berlin are deemed to have made any representations as to the
suitability of this software for any purpose nor are held responsible
for any defects of this software. THERE IS ABSOLUTELY NO WARRANTY FOR
THIS SOFTWARE.

View File

@ -1,14 +1,74 @@
2013-11-04 nu774 <honeycomb77@gmail.com>
2014-07-30 nu774 <honeycomb77@gmail.com>
* update ChangeLog [HEAD]
* win32compat: fix aacenc_printf() not to write junk characters [v0.5.4]
2014-05-12 nu774 <honeycomb77@gmail.com>
* write INSTALL [origin/master]
2014-03-14 nu774 <honeycomb77@gmail.com>
* update COPYING (patch from darealshinji)
2014-02-17 nu774 <honeycomb77@gmail.com>
* update ChangeLog
* bump version [v0.5.3]
* fix: CAF chan chunk using channel bitmap was not correctly handled
2014-01-18 nu774 <honeycomb77@gmail.com>
* update ChangeLog
* bump version [v0.5.2]
* fix reading of caf file without chan chunk
2013-11-17 nu774 <honeycomb77@gmail.com>
* Merge pull request #9 from rbrito/fix-typo
2013-11-18 Rogério Brito <rbrito@ime.usp.br>
* man: Regen manpage with hyphens escaped.
* README: Remove trailing whitespaces that end up in the manpages.
* README: Fix typo in bandwidth to match CLI options.
2013-11-08 nu774 <honeycomb77@gmail.com>
* add genman.sh, update fdkaac.1
* update ChangeLog
* bump version [v0.5.1]
* fix to use libFDKAAC signaling mode 1
2013-11-05 nu774 <honeycomb77@gmail.com>
* fix README
2013-11-04 nu774 <honeycomb77@gmail.com>
* rename README.md -> README
* Update README -> README.md, generate groff manpage from README.md
* update ChangeLog
* update git2changelog to accept non-ascii output
* add manpage
2013-11-03 nu774 <honeycomb77@gmail.com>
* fix gcc warnings [origin/master]
* fix gcc warnings
* Merge pull request #7 from rbrito/misc-fixes

386
INSTALL
View File

@ -1,370 +1,32 @@
Installation Instructions
*************************
Prerequiste
-----------
Copyright (C) 1994-1996, 1999-2002, 2004-2011 Free Software Foundation,
Inc.
To build fdkaac, you need the followings:
- libfdk-aac (https://github.com/mstorsjo/fdk-aac)
- GNU autoconf, GNU automake
- GNU gettext (for iconv.m4)
Copying and distribution of this file, with or without modification,
are permitted in any medium without royalty provided the copyright
notice and this notice are preserved. This file is offered as-is,
without warranty of any kind.
libfdk-aac is always required, and probably you have to build it yourself.
Others are required only when you build by configure and make on Unix-like
enviromnent (including Cygwin or MinGW), and usually you can install them
through package manager of your system if they are not already present.
Basic Installation
==================
Unix-like environment
---------------------
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package. Some packages provide this
`INSTALL' file but do not implement all of the features documented
below. The lack of an optional feature in a given package is not
necessarily a bug. More recommendations for GNU packages can be found
in *note Makefile Conventions: (standards)Makefile Conventions.
You can build and install libfdkaac and fdkaac in the following step.
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, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
1) extract the source, and cd to the source directory
2) autoreconf -i
3) ./configure
4) make
5) sudo make install
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
Depending on your requirements, you might want to add some extra arguments to
configure script.
You have to install libfdk-aac first, and do the same for fdkaac.
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 you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' 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.
Running `configure' might take a while. 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, generally using the just-built uninstalled binaries.
4. Type `make install' to install the programs and any data files and
documentation. When installing into a prefix owned by root, it is
recommended that the package be configured and built as a regular
user, and only the `make install' phase executed with root
privileges.
5. Optionally, type `make installcheck' to repeat any self-tests, but
this time using the binaries in their final installed location.
This target does not install anything. Running this target as a
regular user, particularly if the prior `make install' required
root privileges, verifies that the installation completed
correctly.
6. 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.
7. Often, you can also type `make uninstall' to remove the installed
files again. In practice, not all packages have tested that
uninstallation works correctly, even though it is required by the
GNU Coding Standards.
8. Some packages, particularly those that use Automake, provide `make
distcheck', which can by used by developers to test that all other
targets like `make install' and `make uninstall' work correctly.
This target is generally not run by end users.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that
the `configure' script does not know about. Run `./configure --help'
for details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
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 can use 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 `..'. This
is known as a "VPATH" build.
With a non-GNU `make', it is safer 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.
On MacOS X 10.5 and later systems, you can create libraries and
executables that work on multiple system types--known as "fat" or
"universal" binaries--by specifying multiple `-arch' options to the
compiler but only a single `-arch' option to the preprocessor. Like
this:
./configure CC="gcc -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CXX="g++ -arch i386 -arch x86_64 -arch ppc -arch ppc64" \
CPP="gcc -E" CXXCPP="g++ -E"
This is not guaranteed to produce working output in all cases, you
may have to build one architecture at a time and combine the results
using the `lipo' tool if you have problems.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX', where PREFIX must be an
absolute file name.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' 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. In general, the
default for these options is expressed in terms of `${prefix}', so that
specifying just `--prefix' will affect all of the other directory
specifications that were not explicitly provided.
The most portable way to affect installation locations is to pass the
correct locations to `configure'; however, many packages provide one or
both of the following shortcuts of passing variable assignments to the
`make install' command line to change installation locations without
having to reconfigure or recompile.
The first method involves providing an override variable for each
affected directory. For example, `make install
prefix=/alternate/directory' will choose an alternate location for all
directory configuration variables that were expressed in terms of
`${prefix}'. Any directories that were specified during `configure',
but not in terms of `${prefix}', must each be overridden at install
time for the entire installation to be relocated. The approach of
makefile variable overrides for each directory variable is required by
the GNU Coding Standards, and ideally causes no recompilation.
However, some platforms have known limitations with the semantics of
shared libraries that end up requiring recompilation when using this
method, particularly noticeable in packages that use GNU Libtool.
The second method involves providing the `DESTDIR' variable. For
example, `make install DESTDIR=/alternate/directory' will prepend
`/alternate/directory' before all installation names. The approach of
`DESTDIR' overrides is not required by the GNU Coding Standards, and
does not work on platforms that have drive letters. On the other hand,
it does better at avoiding recompilation issues, and works well even
when some directory options were not specified in terms of `${prefix}'
at `configure' time.
Optional Features
=================
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'.
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.
Some packages offer the ability to configure how verbose the
execution of `make' will be. For these packages, running `./configure
--enable-silent-rules' sets the default to minimal output, which can be
overridden with `make V=1'; while running `./configure
--disable-silent-rules' sets the default to verbose, which can be
overridden with `make V=0'.
Particular systems
==================
On HP-UX, the default C compiler is not ANSI C compatible. If GNU
CC is not installed, it is recommended to use the following options in
order to use an ANSI C compiler:
./configure CC="cc -Ae -D_XOPEN_SOURCE=500"
and if that doesn't work, install pre-built binaries of GCC for HP-UX.
HP-UX `make' updates targets which have the same time stamps as
their prerequisites, which makes it generally unusable when shipped
generated files such as `configure' are involved. Use GNU `make'
instead.
On OSF/1 a.k.a. Tru64, some versions of the default C compiler cannot
parse its `<wchar.h>' header file. The option `-nodtk' can be used as
a workaround. If GNU CC is not installed, it is therefore recommended
to try
./configure CC="cc"
and if that doesn't work, try
./configure CC="cc -nodtk"
On Solaris, don't put `/usr/ucb' early in your `PATH'. This
directory contains several dysfunctional programs; working variants of
these programs are available in `/usr/bin'. So, if you need `/usr/ucb'
in your `PATH', put it _after_ `/usr/bin'.
On Haiku, software installed for all users goes in `/boot/common',
not `/usr/local'. It is recommended to use the following options:
./configure --prefix=/boot/common
Specifying the System Type
==========================
There may be some features `configure' cannot figure out
automatically, but needs to determine by the type of machine the package
will run on. Usually, assuming the package is built to be run on the
_same_ architectures, `configure' can figure that out, but if it prints
a message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS
KERNEL-OS
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 machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
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.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it
operates.
`--help'
`-h'
Print a summary of all of the options to `configure', and exit.
`--help=short'
`--help=recursive'
Print a summary of the options unique to this package's
`configure', and exit. The `short' variant lists options used
only in the top level, while the `recursive' variant lists options
also present in any nested packages.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--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.
`--prefix=DIR'
Use DIR as the installation prefix. *note Installation Names::
for more details, including other options available for fine-tuning
the installation locations.
`--no-create'
`-n'
Run the configure checks, but stop before creating any output
files.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.
Windows, MSVC
-------------
Extract libfdk-aac under fdkaac directory, and open MSVC/fdkaac.sln.

View File

@ -99,12 +99,14 @@ copy ..\fdk-aac\libSYS\include\machine_type.h include\fdk-aac\ </Command>
<ClCompile Include="..\src\caf_reader.c" />
<ClCompile Include="..\src\compat_win32.c" />
<ClCompile Include="..\src\extrapolater.c" />
<ClCompile Include="..\src\limiter.c" />
<ClCompile Include="..\src\lpc.c" />
<ClCompile Include="..\src\lpcm.c" />
<ClCompile Include="..\src\m4af.c" />
<ClCompile Include="..\src\main.c" />
<ClCompile Include="..\src\metadata.c" />
<ClCompile Include="..\src\parson.c" />
<ClCompile Include="..\src\pcm_float_converter.c" />
<ClCompile Include="..\src\pcm_native_converter.c" />
<ClCompile Include="..\src\pcm_readhelper.c" />
<ClCompile Include="..\src\pcm_sint16_converter.c" />
<ClCompile Include="..\src\progress.c" />
@ -113,7 +115,6 @@ copy ..\fdk-aac\libSYS\include\machine_type.h include\fdk-aac\ </Command>
<ItemGroup>
<ClInclude Include="..\missings\getopt.h" />
<ClInclude Include="..\src\aacenc.h" />
<ClInclude Include="..\src\caf_reader.h" />
<ClInclude Include="..\src\catypes.h" />
<ClInclude Include="..\src\compat.h" />
<ClInclude Include="..\src\lpc.h" />
@ -124,7 +125,6 @@ copy ..\fdk-aac\libSYS\include\machine_type.h include\fdk-aac\ </Command>
<ClInclude Include="..\src\parson.h" />
<ClInclude Include="..\src\pcm_reader.h" />
<ClInclude Include="..\src\progress.h" />
<ClInclude Include="..\src\wav_reader.h" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="fdk-aac.vcxproj">

View File

@ -27,10 +27,10 @@
<ClCompile Include="..\src\extrapolater.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\lpc.c">
<ClCompile Include="..\src\limiter.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\lpcm.c">
<ClCompile Include="..\src\lpc.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\m4af.c">
@ -39,6 +39,12 @@
<ClCompile Include="..\src\main.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pcm_float_converter.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pcm_native_converter.c">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="..\src\pcm_readhelper.c">
<Filter>Source Files</Filter>
</ClCompile>
@ -59,9 +65,6 @@
<ClInclude Include="..\src\aacenc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\caf_reader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\catypes.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -86,9 +89,6 @@
<ClInclude Include="..\src\progress.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\src\wav_reader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="..\missings\getopt.h">
<Filter>Header Files</Filter>
</ClInclude>

View File

@ -7,12 +7,14 @@ fdkaac_SOURCES = \
src/aacenc.c \
src/caf_reader.c \
src/extrapolater.c \
src/limiter.c \
src/lpc.c \
src/lpcm.c \
src/m4af.c \
src/main.c \
src/metadata.c \
src/parson.c \
src/pcm_float_converter.c \
src/pcm_native_converter.c \
src/pcm_readhelper.c \
src/pcm_sint16_converter.c \
src/progress.c \

10
README
View File

@ -5,7 +5,7 @@
NAME
====
fdkaac - command line frontend for libfdk-aac encoder  
fdkaac - command line frontend for libfdk-aac encoder
SYNOPSIS
========
@ -23,7 +23,7 @@ output file is "-", data is written to stdout if one of streamable AAC
transport formats are selected by **-f**.
When CAF input and M4A output is used, tags in CAF file are copied into
the resulting M4A.  
the resulting M4A.
OPTIONS
=======
@ -75,8 +75,8 @@ OPTIONS
1-5
: VBR (higher value -\> higher bitrate)
-w, --bandwith \<n\>
: Frequency bandwith (lowpass cut-off frequency) in Hz. Available on
-w, --bandwidth \<n\>
: Frequency bandwidth (lowpass cut-off frequency) in Hz. Available on
AAC LC only.
-a, --afterburner \<n\>
@ -271,7 +271,7 @@ OPTIONS
: Read tags from JSON. By default, tags are assumed to be direct
children of the root object in JSON. Optionally you can specify
arbitrary dot notation to locate the object containing tags.
 
EXAMPLES
========

2
genman.sh Executable file
View File

@ -0,0 +1,2 @@
#!/bin/sh
pandoc -s -f markdown -t man README >fdkaac.1 && mv -f fdkaac.1 man/fdkaac.1

View File

@ -1,85 +1,84 @@
.TH FDKAAC 1 "November, 2013"
.SH NAME
.PP
fdkaac - command line frontend for libfdk-aac encoder \
fdkaac \- command line frontend for libfdk\-aac encoder
.SH SYNOPSIS
.PP
\f[B]fdkaac\f[] [OPTIONS] [FILE]
\f[B]fdkaac\f[] [OPTIONS][FILE]
.SH DESCRIPTION
.PP
\f[B]fdkaac\f[] reads linear PCM audio in either WAV, raw PCM, or CAF
format, and encodes it into either M4A / AAC file.
.PP
If the input file is "-", data is read from stdin.
Likewise, if the output file is "-", data is written to stdout if one of
streamable AAC transport formats is selected by \f[B]-f\f[].
If the input file is "\-", data is read from stdin.
Likewise, if the output file is "\-", data is written to stdout if one
of streamable AAC transport formats are selected by \f[B]\-f\f[].
.PP
When CAF input and M4A output is used, tags in CAF file are copied into
the resulting M4A.
\
.SH OPTIONS
.TP
.B -h, --help
.B \-h, \-\-help
Show command help
.RS
.RE
.TP
.B -o <FILE>
.B \-o <FILE>
Output filename.
.RS
.RE
.TP
.B -p, --profile <n>
.B \-p, \-\-profile <n>
Target profile (MPEG4 audio object type, AOT)
.RS
.TP
.B 2
MPEG-4 AAC LC (default)
MPEG\-4 AAC LC (default)
.RS
.RE
.TP
.B 5
MPEG-4 HE-AAC (SBR)
MPEG\-4 HE\-AAC (SBR)
.RS
.RE
.TP
.B 29
MPEG-4 HE-AAC v2 (SBR+PS)
MPEG\-4 HE\-AAC v2 (SBR+PS)
.RS
.RE
.TP
.B 23
MPEG-4 AAC LD
MPEG\-4 AAC LD
.RS
.RE
.TP
.B 39
MPEG-4 AAC ELD
MPEG\-4 AAC ELD
.RS
.RE
.TP
.B 129
MPEG-2 AAC LC
MPEG\-2 AAC LC
.RS
.RE
.TP
.B 132
MPEG-2 HE-AAC (SBR)
MPEG\-2 HE\-AAC (SBR)
.RS
.RE
.TP
.B 156
MPEG-2 HE-AAC v2 (SBR+PS)
MPEG\-2 HE\-AAC v2 (SBR+PS)
.RS
.RE
.RE
.TP
.B -b, --bitrate <n>
.B \-b, \-\-bitrate <n>
Target bitrate (for CBR)
.RS
.RE
.TP
.B -m, --bitrate-mode <n>
.B \-m, \-\-bitrate\-mode <n>
Bitrate configuration mode.
Available VBR quality value depends on other parameters such as profile,
sample rate, or number of channels.
@ -90,19 +89,19 @@ CBR (default)
.RS
.RE
.TP
.B 1-5
VBR (higher value -> higher bitrate)
.B 1\-5
VBR (higher value \-> higher bitrate)
.RS
.RE
.RE
.TP
.B -w, --bandwith <n>
Frequency bandwith (lowpass cut-off frequency) in Hz.
.B \-w, \-\-bandwidth <n>
Frequency bandwidth (lowpass cut\-off frequency) in Hz.
Available on AAC LC only.
.RS
.RE
.TP
.B -a, --afterburner <n>
.B \-a, \-\-afterburner <n>
Configure afterburner mode.
When enabled, quality is increased at the expense of additional
computational workload.
@ -119,11 +118,11 @@ On (default)
.RE
.RE
.TP
.B -L, --lowdelay-sbr <n>
.B \-L, \-\-lowdelay\-sbr <n>
Configure SBR activity on AAC ELD.
.RS
.TP
.B -1
.B \-1
Use ELD SBR auto configuration
.RS
.RE
@ -139,7 +138,7 @@ Enable SBR on ELD
.RE
.RE
.TP
.B -s, --sbr-ratio <n>
.B \-s, \-\-sbr\-ratio <n>
Controls activation of downsampled SBR.
.RS
.TP
@ -154,30 +153,30 @@ Use downsampled SBR (default for ELD+SBR)
.RE
.TP
.B 2
Use dual-rate SBR (default for HE-AAC)
Use dual\-rate SBR (default for HE\-AAC)
.RS
.RE
.PP
Dual-rate SBR is what is normally used for HE-AAC, where AAC is encoded
at half the sample rate of SBR, hence "dual rate".
Dual\-rate SBR is what is normally used for HE\-AAC, where AAC is
encoded at half the sample rate of SBR, hence "dual rate".
On the other hand, downsampled SBR uses same sample rate for both of AAC
and SBR (single rate), therefore downsampled SBR typically consumes more
bitrate.
.PP
Downsampled SBR is newly introduced feature in FDK encoder library
version 3.4.12.
When libfdk-aac in the system doesn\[aq]t support this, dual-rate SBR
When libfdk\-aac in the system doesn\[aq]t support this, dual\-rate SBR
will be used.
When available, dual-rate SBR is the default for HE-AAC and downsampled
SBR is the default for ELD+SBR.
When available, dual\-rate SBR is the default for HE\-AAC and
downsampled SBR is the default for ELD+SBR.
.PP
Note that downsampled HE-AAC is not so common as dual-rate one.
When downsampled HE-AAC is selected, \f[B]fdkaac\f[] is forced to choose
explicit hierarchical SBR signaling, which (at least) iTunes doesn\[aq]t
accept.
Note that downsampled HE\-AAC is not so common as dual\-rate one.
When downsampled HE\-AAC is selected, \f[B]fdkaac\f[] is forced to
choose explicit hierarchical SBR signaling, which (at least) iTunes
doesn\[aq]t accept.
.RE
.TP
.B -f, --transport-format <n>
.B \-f, \-\-transport\-format <n>
Transport format.
Tagging and gapless playback is only available on M4A.
Streaming to stdout is only available on others.
@ -214,17 +213,17 @@ LOAS/LATM (LATM within LOAS)
.RE
.RE
.TP
.B -C, --adts-crc-check
.B \-C, \-\-adts\-crc\-check
Add CRC protection on ADTS header.
.RS
.RE
.TP
.B -h, --header-period <n>
StreamMuxConfig/PCE repetition period in transport layer.
.B \-h, \-\-header\-period <n>
StreamMuxConfig/PCE repetition period in the transport layer.
.RS
.RE
.TP
.B -G, --gapless-mode <n>
.B \-G, \-\-gapless\-mode <n>
Method to declare amount of encoder delay (and padding) in M4A
container.
These values are mandatory for proper gapless playback on player side.
@ -246,7 +245,7 @@ Both
.RE
.RE
.TP
.B --include-sbr-delay
.B \-\-include\-sbr\-delay
When specified, count SBR decoder delay in encoder delay.
.RS
.PP
@ -262,44 +261,44 @@ playback.
LC doesn\[aq]t have such issues.
.RE
.TP
.B -I, --ignorelength
.B \-I, \-\-ignorelength
Ignore length field of data chunk in input WAV file.
.RS
.RE
.TP
.B -S, --silent
.B \-S, \-\-silent
Don\[aq]t print progress messages.
.RS
.RE
.TP
.B --moov-before-mdat
.B \-\-moov\-before\-mdat
Place moov box before mdat box in M4A container.
This option might be important for some hardware players, that are known
to refuse moov box placed after mdat box.
.RS
.RE
.TP
.B -R, --raw
.B \-R, \-\-raw
Regard input as raw PCM.
.RS
.RE
.TP
.B --raw-channels <n>
.B \-\-raw\-channels <n>
Specify number of channels of raw input (default: 2)
.RS
.RE
.TP
.B --raw-rate <n>
.B \-\-raw\-rate <n>
Specify sample rate of raw input (default: 44100)
.RS
.RE
.TP
.B --raw-format <spec>
.B \-\-raw\-format <spec>
Specify sample format of raw input (default: "S16L").
\f[B]Spec\f[] is as the following (case insensitive):
.RS
.TP
.B 1st char -- type of sample
.B 1st char \-\- type of sample
\f[B]S\f[] (igned) | \f[B]U\f[] (nsigned) | \f[B]F\f[] (loat)
.RS
.RE
@ -309,102 +308,99 @@ bits per channel
.RS
.RE
.TP
.B Last char -- endianness (can be ommited)
.B Last char \-\- endianness (can be omitted)
\f[B]L\f[] (ittle, default) | \f[B]B\f[] (ig)
.RS
.RE
.RE
.TP
.B --title <string>
.B \-\-title <string>
Set title tag.
.RS
.RE
.TP
.B --artist <string>
.B \-\-artist <string>
Set artist tag.
.RS
.RE
.TP
.B --album <string>
.B \-\-album <string>
Set album tag.
.RS
.RE
.TP
.B --genre <string>
.B \-\-genre <string>
Set genre tag.
.RS
.RE
.TP
.B --date <string>
.B \-\-date <string>
Set date tag.
.RS
.RE
.TP
.B --composer <string>
.B \-\-composer <string>
Set composer tag.
.RS
.RE
.TP
.B --grouping <string>
.B \-\-grouping <string>
Set grouping tag.
.RS
.RE
.TP
.B --comment <string>
.B \-\-comment <string>
Set comment tag.
.RS
.RE
.TP
.B --album-artist <string>
.B \-\-album\-artist <string>
Set album artist tag.
.RS
.RE
.TP
.B --track <number[/total]>
.B \-\-track <number[/total]>
Set track tag, with or without number of total tracks.
.RS
.RE
.TP
.B --disk <number[/total]>
.B \-\-disk <number[/total]>
Set disk tag, with or without number of total discs.
.RS
.RE
.TP
.B --tempo <n>
.B \-\-tempo <n>
Set tempo (BPM) tag.
.RS
.RE
.TP
.B --tag <fcc>:<value>
.B \-\-tag <fcc>:<value>
Set iTunes predefined tag with explicit fourcc key and value.
See
https://code.google.com/p/mp4v2/wiki/iTunesMetadata (https://code.google.com/p/mp4v2/wiki/iTunesMetadata)
for known predefined keys.
See <https://code.google.com/p/mp4v2/wiki/iTunesMetadata> for known
predefined keys.
You can omit first char of \f[B]fcc\f[] when it is the copyright sign.
.RS
.RE
.TP
.B --tag-from-file <fcc>:<filename>
Same as --tag, but set content of file as tag value.
.B \-\-tag\-from\-file <fcc>:<filename>
Same as \-\-tag, but set content of file as tag value.
.RS
.RE
.TP
.B --long-tag <name>:<value>
.B \-\-long\-tag <name>:<value>
Set arbitrary tag as iTunes custom metadata.
Stored in com.apple.iTunes field.
.RS
.RE
.TP
.B --tag-from-json <filename[?dot_notation]>
.B \-\-tag\-from\-json <filename[?dot_notation]>
Read tags from JSON.
By default, tags are assumed to be direct children of the root object in
JSON.
Optionary you can speficy arbitrary dot notation to locate the object
Optionally you can specify arbitrary dot notation to locate the object
containing tags.
.RS
.RE
.PP
\
.SH EXAMPLES
.PP
Encode WAV file into a M4A file.
@ -412,16 +408,16 @@ MPEG4 AAC LC, VBR quality 3:
.IP
.nf
\f[C]
fdkaac\ -m3\ foo.wav
fdkaac\ \-m3\ foo.wav
\f[]
.fi
.PP
Encode WAV file into a M4A file.
MPEG4 HE-AAC, bitrate 64kbps:
MPEG4 HE\-AAC, bitrate 64kbps:
.IP
.nf
\f[C]
fdkaac\ -p5\ -b64\ foo.wav
fdkaac\ \-p5\ \-b64\ foo.wav
\f[]
.fi
.PP
@ -429,7 +425,7 @@ Piping from \f[B]ffmpeg\f[] (you need version supporting CAF output):
.IP
.nf
\f[C]
ffmpeg\ -i\ foo.flac\ -f\ caf\ -\ |\ fdkaac\ -b128\ -\ -o\ foo.m4a
ffmpeg\ \-i\ foo.flac\ \-f\ caf\ \-\ |\ fdkaac\ \-b128\ \-\ \-o\ foo.m4a
\f[]
.fi
.PP
@ -437,10 +433,10 @@ Import tags via json:
.IP
.nf
\f[C]
ffprobe\ -v\ 0\ -of\ json\ -show_format\ foo.flac\ >foo.json
ffprobe\ \-v\ 0\ \-of\ json\ \-show_format\ foo.flac\ >foo.json
flac\ -dc\ foo.flac\ |\ \\
fdkaac\ -\ -ox.m4a\ -m2\ --import-tag-from-json=foo.json?format.tags
flac\ \-dc\ foo.flac\ |\ \\
fdkaac\ \-\ \-ox.m4a\ \-m2\ \-\-import\-tag\-from\-json=foo.json?format.tags
\f[]
.fi
.SH NOTES
@ -448,7 +444,7 @@ fdkaac\ -\ -ox.m4a\ -m2\ --import-tag-from-json=foo.json?format.tags
Upto 32bit integer or 64bit floating point format is supported as input.
However, FDK library is implemented based on fixed point math and only
supports 16bit integer PCM.
Therefore, be careful of clipping.
Therefore, be wary of clipping.
You might want to dither/noise shape beforehand when your input has
higher resolution.
.PP

View File

@ -14,7 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "caf_reader.h"
#include "pcm_reader.h"
#include "m4af.h"
typedef struct caf_reader_t {
@ -225,6 +225,7 @@ pcm_reader_t *caf_open(pcm_io_context_t *io,
memcpy(&reader->io, io, sizeof(pcm_io_context_t));
reader->tag_callback = tag_callback;
reader->tag_ctx = tag_ctx;
memcpy(reader->chanmap, "\000\001\002\003\004\005\006\007", 8);
if (caf_parse(reader, &data_length) < 0) {
free(reader);

View File

@ -1,15 +0,0 @@
/*
* Copyright (C) 2013 nu774
* For conditions of distribution and use, see copyright notice in COPYING
*/
#ifndef CAF_READER_H
#define CAF_READER_H
#include "lpcm.h"
#include "pcm_reader.h"
#include "metadata.h"
pcm_reader_t *caf_open(pcm_io_context_t *io,
aacenc_tag_callback_t tag_callback, void *tag_ctx);
#endif

View File

@ -157,7 +157,7 @@ int aacenc_fprintf(FILE *fp, const char *fmt, ...)
codepage_decode_wchar(CP_UTF8, s, &ws);
free(s);
fflush(fp);
WriteConsoleW(fh, ws, cnt, &nw, 0);
WriteConsoleW(fh, ws, wcslen(ws), &nw, 0);
free(ws);
}
return cnt;

View File

@ -86,11 +86,11 @@ static int fetch(extrapolater_t *self, unsigned nframes)
if (realloc_buffer(bp, nframes * sfmt->bytes_per_frame) == 0) {
rc = pcm_read_frames(self->src, bp->data, nframes);
bp->count = rc > 0 ? rc : 0;
if (rc > 0) bp->count = rc;
}
if (rc > 0)
self->nbuffer ^= 1;
return bp->count;
return rc <= 0 ? 0 : bp->count;
}
static int extrapolate(extrapolater_t *self, const buffer_t *bp,
@ -126,7 +126,13 @@ static int process0(extrapolater_t *self, void *buffer, unsigned nframes)
reverse_buffer(buffer, nframes, nchannels);
reverse_buffer(bp->data, bp->count, nchannels);
}
self->process = bp->count ? process1 : process2;
if (bp->count)
self->process = process1;
else {
memset(bp->data, 0, nframes * sfmt->bytes_per_frame);
bp->count = nframes;
self->process = process2;
}
return nframes;
}
@ -137,8 +143,27 @@ static int process1(extrapolater_t *self, void *buffer, unsigned nframes)
assert(bp->count <= nframes);
memcpy(buffer, bp->data, bp->count * sfmt->bytes_per_frame);
if (!fetch(self, nframes))
if (!fetch(self, nframes)) {
buffer_t *bbp = &self->buffer[self->nbuffer];
if (bp->count < 2 * LPC_ORDER) {
size_t total = bp->count + bbp->count;
if (bbp->count &&
realloc_buffer(bbp, total * sfmt->bytes_per_frame) == 0 &&
realloc_buffer(bp, total * sfmt->bytes_per_frame) == 0)
{
memcpy(bbp->data + bbp->count * sfmt->channels_per_frame,
bp->data, bp->count * sfmt->bytes_per_frame);
memcpy(bp->data, bbp->data, total * sfmt->bytes_per_frame);
bp->count = total;
}
}
if (bp->count >= 2 * LPC_ORDER)
extrapolate(self, bp, bbp->data, nframes);
else
memset(bbp->data, 0, nframes * sfmt->bytes_per_frame);
bbp->count = nframes;
self->process = process2;
}
return bp->count;
}
@ -146,27 +171,15 @@ static int process2(extrapolater_t *self, void *buffer, unsigned nframes)
{
const pcm_sample_description_t *sfmt = pcm_get_format(self->src);
buffer_t *bp = &self->buffer[self->nbuffer];
buffer_t *bbp = &self->buffer[self->nbuffer ^ 1];
if (bp->count < 2 * LPC_ORDER) {
size_t total = bp->count + bbp->count;
if (bbp->count &&
realloc_buffer(bbp, total * sfmt->bytes_per_frame) == 0)
{
memcpy(bbp->data + bbp->count * sfmt->channels_per_frame,
bp->data, bp->count * sfmt->bytes_per_frame);
bbp->count = total;
bp->count = 0;
bp = bbp;
self->nbuffer ^= 1;
}
}
if (bp->count < nframes)
nframes = bp->count;
memcpy(buffer, bp->data, nframes * sfmt->bytes_per_frame);
if (bp->count > nframes)
memmove(bp->data, bp->data + nframes * sfmt->channels_per_frame,
(bp->count - nframes) * sfmt->bytes_per_frame);
bp->count -= nframes;
if (bp->count == 0)
self->process = process3;
if (bp->count >= 2 * LPC_ORDER)
extrapolate(self, bp, buffer, nframes);
else
memset(buffer, 0, nframes * sfmt->bytes_per_frame);
return nframes;
}

186
src/limiter.c Normal file
View File

@ -0,0 +1,186 @@
/*
* Copyright (C) 2013 nu774
* For conditions of distribution and use, see copyright notice in COPYING
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <assert.h>
#include "pcm_reader.h"
#include "lpc.h"
typedef struct buffer_t {
void *data;
unsigned count;
unsigned capacity;
unsigned head;
} buffer_t;
typedef struct limiter_t {
pcm_reader_vtbl_t *vtbl;
pcm_reader_t *src;
pcm_sample_description_t format;
int64_t position;
buffer_t buffers[1];
} limiter_t;
static inline pcm_reader_t *get_source(pcm_reader_t *reader)
{
return ((limiter_t *)reader)->src;
}
static const
pcm_sample_description_t *get_format(pcm_reader_t *reader)
{
return pcm_get_format(get_source(reader));
}
static int64_t get_length(pcm_reader_t *reader)
{
return pcm_get_length(get_source(reader));
}
static int64_t get_position(pcm_reader_t *reader)
{
return ((limiter_t *)reader)->position;
}
static int reserve_buffer(buffer_t *bp, size_t required, unsigned unit)
{
if (bp->capacity < required) {
unsigned newsize = 1;
void *p;
while (newsize < required)
newsize <<= 1;
p = realloc(bp->data, newsize * unit);
if (!p) return -1;
bp->data = p;
bp->capacity = newsize;
}
return 0;
}
static int read_frames(pcm_reader_t *reader, void *buffer, unsigned nframes)
{
limiter_t *self = (limiter_t *)reader;
unsigned i, n, res, nch = self->format.channels_per_frame;
size_t bytes = nframes * pcm_get_format(self->src)->bytes_per_frame;
buffer_t *ibp = &self->buffers[nch];
float *obp = buffer;
do {
if (reserve_buffer(ibp, bytes, 1) < 0)
return -1;
res = pcm_read_frames(self->src, ibp->data, nframes);
for (n = 0; n < nch; ++n) {
float *ip = (float *)ibp->data, *x;
buffer_t *bp = &self->buffers[n];
unsigned end, limit;
if (reserve_buffer(bp, bp->count + res, sizeof(float)) < 0)
return -1;
x = bp->data;
for (i = 0; i < res; ++i)
x[bp->count++] = pcm_clip(ip[i * nch + n], -3.0, 3.0);
limit = bp->count;
if (limit > 0 && res > 0) {
float last = x[limit - 1];
for (; limit > 0 && x[limit-1] * last > 0; --limit)
;
}
end = bp->head;
while (end < limit) {
unsigned start, peak_pos;
float peak;
for (peak_pos = end; peak_pos < limit; ++peak_pos)
if (x[peak_pos] > 1.0f || x[peak_pos] < -1.0f)
break;
if (peak_pos == limit)
break;
start = peak_pos;
peak = fabs(x[peak_pos]);
while (start > bp->head && x[peak_pos] * x[start] >= 0.0f)
--start;
++start;
for (end = peak_pos + 1; end < limit; ++end) {
float y;
if (x[peak_pos] * x[end] < 0.0f)
break;
y = fabs(x[end]);
if (y > peak) {
peak = y;
peak_pos = end;
}
}
if (peak < 2.0f) {
float a = (peak - 1.0f) / (peak * peak);
if (x[peak_pos] > 0.0f) a = -a;
for (i = start; i < end; ++i)
x[i] = x[i] + a * x[i] * x[i];
} else {
float u = peak, v = 1.0f;
float a = (u - 2.0f * v) / (u * u * u);
float b = (3.0f * v - 2.0f * u) / (u * u);
if (x[peak_pos] < 0.0f) b = -b;
for (i = start; i < end; ++i)
x[i] = x[i] + b * x[i] * x[i] + a * x[i] * x[i] * x[i];
}
}
bp->head = limit;
}
res = nframes;
for (n = 0; n < nch; ++n)
if (self->buffers[n].head < res)
res = self->buffers[n].head;
for (i = 0; i < res; ++i)
for (n = 0; n < nch; ++n)
*obp++ = ((float *)self->buffers[n].data)[i];
if (res) {
for (n = 0; n < nch; ++n) {
buffer_t *bp = &self->buffers[n];
float *p = bp->data;
memmove(p, p + res, (bp->count - res) * sizeof(float));
bp->count -= res;
bp->head -= res;
}
}
} while (res == 0 && self->buffers[0].count);
self->position += res;
return res;
}
static void teardown(pcm_reader_t **reader)
{
int i;
limiter_t *self = (limiter_t *)*reader;
pcm_teardown(&self->src);
for (i = 0; i < self->format.channels_per_frame + 1; ++i)
free(self->buffers[i].data);
free(self);
*reader = 0;
}
static pcm_reader_vtbl_t my_vtable = {
get_format, get_length, get_position, read_frames, teardown
};
pcm_reader_t *limiter_open(pcm_reader_t *reader)
{
limiter_t *self;
int n = pcm_get_format(reader)->channels_per_frame;
size_t size = sizeof(limiter_t) + offsetof(limiter_t, buffers[n + 1]);
if ((self = calloc(1, size)) == 0)
return 0;
self->src = reader;
self->vtbl = &my_vtable;
self->format = *pcm_get_format(reader);
self->format.bits_per_channel = 32;
return (pcm_reader_t *)self;
}

View File

@ -1,226 +0,0 @@
/*
* Copyright (C) 2013 nu774
* For conditions of distribution and use, see copyright notice in COPYING
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#include <stdlib.h>
#include <math.h>
#include "lpcm.h"
#include "m4af_endian.h"
static
inline float pcm_i2f(int32_t n)
{
union {
int32_t ivalue;
float fvalue;
} u;
u.ivalue = n;
return u.fvalue;
}
static
inline double pcm_i2d(int64_t n)
{
union {
int64_t ivalue;
double fvalue;
} u;
u.ivalue = n;
return u.fvalue;
}
static
inline int16_t pcm_quantize_s32(int32_t n)
{
n = ((n >> 15) + 1) >> 1;
return (n == 0x8000) ? 0x7fff : n;
}
static
inline int16_t pcm_quantize_f64(double v)
{
return (int16_t)lrint(pcm_clip(v * 32768.0, -32768.0, 32767.0));
}
static
inline int16_t pcm_s8_to_s16(int8_t n)
{
return n << 8;
}
static
inline int16_t pcm_u8_to_s16(uint8_t n)
{
return (n << 8) ^ 0x8000;
}
static
inline int16_t pcm_s16le_to_s16(int16_t n)
{
return m4af_ltoh16(n);
}
static
inline int16_t pcm_s16be_to_s16(int16_t n)
{
return m4af_btoh16(n);
}
static
inline int16_t pcm_u16le_to_s16(uint16_t n)
{
return m4af_ltoh16(n) ^ 0x8000;
}
static
inline int16_t pcm_u16be_to_s16(uint16_t n)
{
return m4af_btoh16(n) ^ 0x8000;
}
static
inline int32_t pcm_s24le_to_s32(uint8_t *p)
{
return p[0]<<8 | p[1]<<16 | p[2]<<24;
}
static
inline int32_t pcm_s24be_to_s32(uint8_t *p)
{
return p[0]<<24 | p[1]<<16 | p[2]<<8;
}
static
inline int32_t pcm_u24le_to_s32(uint8_t *p)
{
return pcm_s24le_to_s32(p) ^ 0x80000000;
}
static
inline int32_t pcm_u24be_to_s32(uint8_t *p)
{
return pcm_s24be_to_s32(p) ^ 0x80000000;
}
static
inline int16_t pcm_s24le_to_s16(uint8_t *p)
{
return pcm_quantize_s32(pcm_s24le_to_s32(p));
}
static
inline int16_t pcm_s24be_to_s16(uint8_t *p)
{
return pcm_quantize_s32(pcm_s24be_to_s32(p));
}
static
inline int16_t pcm_u24le_to_s16(uint8_t *p)
{
return pcm_quantize_s32(pcm_u24le_to_s32(p));
}
static
inline int16_t pcm_u24be_to_s16(uint8_t *p)
{
return pcm_quantize_s32(pcm_u24be_to_s32(p));
}
static
inline int16_t pcm_s32le_to_s16(int32_t n)
{
return pcm_quantize_s32(m4af_ltoh32(n));
}
static
inline int16_t pcm_s32be_to_s16(int32_t n)
{
return pcm_quantize_s32(m4af_btoh32(n));
}
static
inline int16_t pcm_u32le_to_s16(int32_t n)
{
return pcm_quantize_s32(m4af_ltoh32(n) ^ 0x80000000);
}
static
inline int16_t pcm_u32be_to_s16(int32_t n)
{
return pcm_quantize_s32(m4af_btoh32(n) ^ 0x80000000);
}
static
inline int16_t pcm_f32le_to_s16(int32_t n)
{
return pcm_quantize_f64(pcm_i2f(m4af_ltoh32(n)));
}
static
inline int16_t pcm_f32be_to_s16(int32_t n)
{
return pcm_quantize_f64(pcm_i2f(m4af_btoh32(n)));
}
static
inline int16_t pcm_f64le_to_s16(int64_t n)
{
return pcm_quantize_f64(pcm_i2d(m4af_ltoh64(n)));
}
static
inline int16_t pcm_f64be_to_s16(int64_t n)
{
return pcm_quantize_f64(pcm_i2d(m4af_btoh64(n)));
}
int pcm_convert_to_native_sint16(const pcm_sample_description_t *format,
const void *input, uint32_t nframes,
int16_t *result)
{
#define CONVERT(type, conv) \
do { \
unsigned i; \
type *ip = (type *)input; \
for (i = 0; i < count; ++i) { \
result[i] = conv(ip[i]); \
} \
} while(0)
#define CONVERT_BYTES(conv) \
do { \
unsigned i, bytes_per_channel; \
uint8_t *ip = (uint8_t *)input; \
bytes_per_channel = PCM_BYTES_PER_CHANNEL(format); \
for (i = 0; i < count; ++i) { \
result[i] = conv(ip); \
ip += bytes_per_channel; \
} \
} while(0)
uint32_t count = nframes * format->channels_per_frame;
if (!count)
return 0;
switch (PCM_BYTES_PER_CHANNEL(format) | format->sample_type<<4) {
case 1 | PCM_TYPE_SINT<<4:
CONVERT(int8_t, pcm_s8_to_s16); break;
case 1 | PCM_TYPE_UINT<<4:
CONVERT(uint8_t, pcm_u8_to_s16); break;
case 2 | PCM_TYPE_SINT<<4:
CONVERT(int16_t, pcm_s16le_to_s16); break;
case 2 | PCM_TYPE_UINT<<4:
CONVERT(uint16_t, pcm_u16le_to_s16); break;
case 2 | PCM_TYPE_SINT_BE<<4:
CONVERT(int16_t, pcm_s16be_to_s16); break;
case 2 | PCM_TYPE_UINT_BE<<4:
CONVERT(int16_t, pcm_u16be_to_s16); break;
case 3 | PCM_TYPE_SINT<<4:
CONVERT_BYTES(pcm_s24le_to_s16); break;
case 3 | PCM_TYPE_UINT<<4:
CONVERT_BYTES(pcm_u24le_to_s16); break;
case 3 | PCM_TYPE_SINT_BE<<4:
CONVERT_BYTES(pcm_s24be_to_s16); break;
case 3 | PCM_TYPE_UINT_BE<<4:
CONVERT_BYTES(pcm_u24be_to_s16); break;
case 4 | PCM_TYPE_SINT<<4:
CONVERT(int32_t, pcm_s32le_to_s16); break;
case 4 | PCM_TYPE_UINT<<4:
CONVERT(uint32_t, pcm_u32le_to_s16); break;
case 4 | PCM_TYPE_FLOAT<<4:
CONVERT(int32_t, pcm_f32le_to_s16); break;
case 4 | PCM_TYPE_SINT_BE<<4:
CONVERT(int32_t, pcm_s32be_to_s16); break;
case 4 | PCM_TYPE_UINT_BE<<4:
CONVERT(uint32_t, pcm_u32be_to_s16); break;
case 4 | PCM_TYPE_FLOAT_BE<<4:
CONVERT(int32_t, pcm_f32be_to_s16); break;
case 8 | PCM_TYPE_FLOAT<<4:
CONVERT(int64_t, pcm_f64le_to_s16); break;
case 8 | PCM_TYPE_FLOAT_BE<<4:
CONVERT(int64_t, pcm_f64be_to_s16); break;
default:
return -1;
}
return 0;
}

View File

@ -61,7 +61,4 @@ inline double pcm_clip(double n, double min_value, double max_value)
return n;
}
int pcm_convert_to_native_sint16(const pcm_sample_description_t *format,
const void *input, uint32_t nframes,
int16_t *result);
#endif

View File

@ -33,8 +33,7 @@
#include <windows.h>
#endif
#include "compat.h"
#include "wav_reader.h"
#include "caf_reader.h"
#include "pcm_reader.h"
#include "aacenc.h"
#include "m4af.h"
#include "progress.h"
@ -699,7 +698,7 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params)
if ((params->input_fp = aacenc_fopen(params->input_filename, "rb")) == 0) {
aacenc_fprintf(stderr, "ERROR: %s: %s\n", params->input_filename,
strerror(errno));
goto END;
goto FAIL;
}
io.cookie = params->input_fp;
if (fstat(fileno(params->input_fp), &stb) == 0
@ -713,7 +712,7 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params)
pcm_sample_description_t desc = { 0 };
if (parse_raw_spec(params->raw_format, &desc) < 0) {
fprintf(stderr, "ERROR: invalid raw-format spec\n");
goto END;
goto FAIL;
}
desc.sample_rate = params->raw_rate;
desc.channels_per_frame = params->raw_channels;
@ -721,7 +720,7 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params)
desc.bytes_per_frame = params->raw_channels * bytes_per_channel;
if ((reader = raw_open(&io, &desc)) == 0) {
fprintf(stderr, "ERROR: failed to open raw input\n");
goto END;
goto FAIL;
}
} else {
int c;
@ -731,7 +730,7 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params)
case 'R':
if ((reader = wav_open(&io, params->ignore_length)) == 0) {
fprintf(stderr, "ERROR: broken / unsupported input file\n");
goto END;
goto FAIL;
}
break;
case 'c':
@ -741,18 +740,21 @@ pcm_reader_t *open_input(aacenc_param_ex_t *params)
aacenc_translate_generic_text_tag,
&params->source_tag_ctx)) == 0) {
fprintf(stderr, "ERROR: broken / unsupported input file\n");
goto END;
goto FAIL;
}
break;
default:
fprintf(stderr, "ERROR: unsupported input file\n");
goto END;
goto FAIL;
}
}
if ((reader = pcm_open_sint16_converter(reader)) != 0)
reader = pcm_open_native_converter(reader);
if (reader && PCM_IS_FLOAT(pcm_get_format(reader)))
reader = limiter_open(reader);
if (reader && (reader = pcm_open_sint16_converter(reader)) != 0)
reader = extrapolater_open(reader);
return reader;
END:
FAIL:
return 0;
}
@ -824,8 +826,7 @@ int main(int argc, char **argv)
goto END;
m4af_set_decoder_specific_info(m4af, 0,
aacinfo.confBuf, aacinfo.confSize);
m4af_set_fixed_frame_duration(m4af, 0,
framelen >> scale_shift);
m4af_set_fixed_frame_duration(m4af, 0, framelen >> scale_shift);
m4af_set_vbr_mode(m4af, 0, params.bitrate_mode);
m4af_set_priming_mode(m4af, params.gapless_mode + 1);
m4af_begin_write(m4af);

85
src/pcm_float_converter.c Normal file
View File

@ -0,0 +1,85 @@
/*
* Copyright (C) 2013 nu774
* For conditions of distribution and use, see copyright notice in COPYING
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#include "pcm_reader.h"
typedef struct pcm_float_converter_t {
pcm_reader_vtbl_t *vtbl;
pcm_reader_t *src;
pcm_sample_description_t format;
} pcm_float_converter_t;
static inline pcm_reader_t *get_source(pcm_reader_t *reader)
{
return ((pcm_float_converter_t *)reader)->src;
}
static const
pcm_sample_description_t *get_format(pcm_reader_t *reader)
{
return &((pcm_float_converter_t *)reader)->format;
}
static int64_t get_length(pcm_reader_t *reader)
{
return pcm_get_length(get_source(reader));
}
static int64_t get_position(pcm_reader_t *reader)
{
return pcm_get_position(get_source(reader));
}
static int read_frames(pcm_reader_t *reader, void *buffer, unsigned nframes)
{
unsigned i;
pcm_float_converter_t *self = (pcm_float_converter_t *)reader;
const pcm_sample_description_t *sfmt = pcm_get_format(self->src);
nframes = pcm_read_frames(self->src, buffer, nframes);
if (!(sfmt->sample_type & PCM_TYPE_FLOAT)) {
int32_t *ip = buffer;
float *op = buffer;
unsigned i, count = nframes * sfmt->channels_per_frame;
for (i = 0; i < count; ++i)
op[i] = ip[i] / 2147483648.0f;
}
return nframes;
}
static void teardown(pcm_reader_t **reader)
{
pcm_float_converter_t *self = (pcm_float_converter_t *)*reader;
pcm_teardown(&self->src);
free(self);
*reader = 0;
}
static pcm_reader_vtbl_t my_vtable = {
get_format, get_length, get_position, read_frames, teardown
};
pcm_reader_t *pcm_open_float_converter(pcm_reader_t *reader)
{
pcm_float_converter_t *self = 0;
pcm_sample_description_t *fmt;
if ((self = calloc(1, sizeof(pcm_float_converter_t))) == 0)
return 0;
self->src = reader;
self->vtbl = &my_vtable;
memcpy(&self->format, pcm_get_format(reader), sizeof(self->format));
fmt = &self->format;
fmt->bits_per_channel = 32;
fmt->sample_type = PCM_TYPE_FLOAT;
fmt->bytes_per_frame = 4 * fmt->channels_per_frame;
return (pcm_reader_t *)self;
}

272
src/pcm_native_converter.c Normal file
View File

@ -0,0 +1,272 @@
/*
* Copyright (C) 2013 nu774
* For conditions of distribution and use, see copyright notice in COPYING
*/
#if HAVE_CONFIG_H
# include "config.h"
#endif
#include <stdlib.h>
#include <string.h>
#if HAVE_STDINT_H
# include <stdint.h>
#endif
#include "m4af_endian.h"
#include "pcm_reader.h"
static
inline float pcm_i2f(int32_t n)
{
union {
int32_t ivalue;
float fvalue;
} u;
u.ivalue = n;
return u.fvalue;
}
static
inline double pcm_i2d(int64_t n)
{
union {
int64_t ivalue;
double fvalue;
} u;
u.ivalue = n;
return u.fvalue;
}
static
inline int32_t pcm_s8_to_s32(int8_t n)
{
return n << 24;
}
static
inline int32_t pcm_u8_to_s32(uint8_t n)
{
return (n << 24) ^ 0x80000000;
}
static
inline int32_t pcm_s16le_to_s32(int16_t n)
{
return m4af_ltoh16(n) << 16;
}
static
inline int32_t pcm_s16be_to_s32(int16_t n)
{
return m4af_btoh16(n) << 16;
}
static
inline int32_t pcm_u16le_to_s32(uint16_t n)
{
return (m4af_ltoh16(n) << 16) ^ 0x80000000;
}
static
inline int32_t pcm_u16be_to_s32(uint16_t n)
{
return (m4af_btoh16(n) << 16) ^ 0x80000000;
}
static
inline int32_t pcm_s24le_to_s32(uint8_t *p)
{
return p[0]<<8 | p[1]<<16 | p[2]<<24;
}
static
inline int32_t pcm_s24be_to_s32(uint8_t *p)
{
return p[0]<<24 | p[1]<<16 | p[2]<<8;
}
static
inline int32_t pcm_u24le_to_s32(uint8_t *p)
{
return pcm_s24le_to_s32(p) ^ 0x80000000;
}
static
inline int32_t pcm_u24be_to_s32(uint8_t *p)
{
return pcm_s24be_to_s32(p) ^ 0x80000000;
}
static
inline int32_t pcm_s32le_to_s32(int32_t n)
{
return m4af_ltoh32(n);
}
static
inline int32_t pcm_s32be_to_s32(int32_t n)
{
return m4af_btoh32(n);
}
static
inline int32_t pcm_u32le_to_s32(int32_t n)
{
return m4af_ltoh32(n) ^ 0x80000000;
}
static
inline int32_t pcm_u32be_to_s32(int32_t n)
{
return m4af_btoh32(n) ^ 0x80000000;
}
static
inline float pcm_f32le_to_f32(int32_t n)
{
return pcm_i2f(m4af_ltoh32(n));
}
static
inline float pcm_f32be_to_f32(int32_t n)
{
return pcm_i2f(m4af_btoh32(n));
}
static
inline float pcm_f64le_to_f32(int64_t n)
{
return pcm_i2d(m4af_ltoh64(n));
}
static
inline float pcm_f64be_to_f32(int64_t n)
{
return pcm_i2d(m4af_btoh64(n));
}
static
int pcm_convert_to_native(const pcm_sample_description_t *format,
const void *input, uint32_t nframes,
void *result)
{
#define CONVERT(type, rtype, conv) \
do { \
unsigned i; \
type *ip = (type *)input; \
for (i = 0; i < count; ++i) { \
((rtype *)result)[i] = conv(ip[i]); \
} \
} while(0)
#define CONVERT_BYTES(rtype, conv) \
do { \
unsigned i, bytes_per_channel; \
uint8_t *ip = (uint8_t *)input; \
bytes_per_channel = PCM_BYTES_PER_CHANNEL(format); \
for (i = 0; i < count; ++i) { \
((rtype *)result)[i] = conv(ip); \
ip += bytes_per_channel; \
} \
} while(0)
uint32_t count = nframes * format->channels_per_frame;
if (!count)
return 0;
switch (PCM_BYTES_PER_CHANNEL(format) | format->sample_type<<4) {
case 1 | PCM_TYPE_SINT<<4:
CONVERT(int8_t, int32_t, pcm_s8_to_s32); break;
case 1 | PCM_TYPE_UINT<<4:
CONVERT(uint8_t, int32_t, pcm_u8_to_s32); break;
case 2 | PCM_TYPE_SINT<<4:
CONVERT(int16_t, int32_t, pcm_s16le_to_s32); break;
case 2 | PCM_TYPE_UINT<<4:
CONVERT(uint16_t, int32_t, pcm_u16le_to_s32); break;
case 2 | PCM_TYPE_SINT_BE<<4:
CONVERT(int16_t, int32_t, pcm_s16be_to_s32); break;
case 2 | PCM_TYPE_UINT_BE<<4:
CONVERT(int16_t, int32_t, pcm_u16be_to_s32); break;
case 3 | PCM_TYPE_SINT<<4:
CONVERT_BYTES(int32_t, pcm_s24le_to_s32); break;
case 3 | PCM_TYPE_UINT<<4:
CONVERT_BYTES(int32_t, pcm_u24le_to_s32); break;
case 3 | PCM_TYPE_SINT_BE<<4:
CONVERT_BYTES(int32_t, pcm_s24be_to_s32); break;
case 3 | PCM_TYPE_UINT_BE<<4:
CONVERT_BYTES(int32_t, pcm_u24be_to_s32); break;
case 4 | PCM_TYPE_SINT<<4:
CONVERT(int32_t, int32_t, pcm_s32le_to_s32); break;
case 4 | PCM_TYPE_UINT<<4:
CONVERT(uint32_t, int32_t, pcm_u32le_to_s32); break;
case 4 | PCM_TYPE_FLOAT<<4:
CONVERT(int32_t, float, pcm_f32le_to_f32); break;
case 4 | PCM_TYPE_SINT_BE<<4:
CONVERT(int32_t, int32_t, pcm_s32be_to_s32); break;
case 4 | PCM_TYPE_UINT_BE<<4:
CONVERT(uint32_t, int32_t, pcm_u32be_to_s32); break;
case 4 | PCM_TYPE_FLOAT_BE<<4:
CONVERT(int32_t, float, pcm_f32be_to_f32); break;
case 8 | PCM_TYPE_FLOAT<<4:
CONVERT(int64_t, float, pcm_f64le_to_f32); break;
case 8 | PCM_TYPE_FLOAT_BE<<4:
CONVERT(int64_t, float, pcm_f64be_to_f32); break;
default:
return -1;
}
return 0;
}
typedef struct pcm_native_converter_t {
pcm_reader_vtbl_t *vtbl;
pcm_reader_t *src;
pcm_sample_description_t format;
void *pivot;
unsigned capacity;
} pcm_native_converter_t;
static inline pcm_reader_t *get_source(pcm_reader_t *reader)
{
return ((pcm_native_converter_t *)reader)->src;
}
static const
pcm_sample_description_t *get_format(pcm_reader_t *reader)
{
return &((pcm_native_converter_t *)reader)->format;
}
static int64_t get_length(pcm_reader_t *reader)
{
return pcm_get_length(get_source(reader));
}
static int64_t get_position(pcm_reader_t *reader)
{
return pcm_get_position(get_source(reader));
}
static int read_frames(pcm_reader_t *reader, void *buffer, unsigned nframes)
{
pcm_native_converter_t *self = (pcm_native_converter_t *)reader;
const pcm_sample_description_t *sfmt = pcm_get_format(self->src);
unsigned bytes = nframes * sfmt->bytes_per_frame;
if (self->capacity < bytes) {
void *p = realloc(self->pivot, bytes);
if (!p) return -1;
self->pivot = p;
self->capacity = bytes;
}
nframes = pcm_read_frames(self->src, self->pivot, nframes);
if (pcm_convert_to_native(sfmt, self->pivot, nframes, buffer) < 0)
return -1;
return nframes;
}
static void teardown(pcm_reader_t **reader)
{
pcm_native_converter_t *self = (pcm_native_converter_t *)*reader;
pcm_teardown(&self->src);
free(self->pivot);
free(self);
*reader = 0;
}
static pcm_reader_vtbl_t my_vtable = {
get_format, get_length, get_position, read_frames, teardown
};
pcm_reader_t *pcm_open_native_converter(pcm_reader_t *reader)
{
pcm_native_converter_t *self = 0;
pcm_sample_description_t *fmt;
if ((self = calloc(1, sizeof(pcm_native_converter_t))) == 0)
return 0;
self->src = reader;
self->vtbl = &my_vtable;
memcpy(&self->format, pcm_get_format(reader), sizeof(self->format));
fmt = &self->format;
fmt->sample_type = PCM_IS_FLOAT(fmt) ? PCM_TYPE_FLOAT : PCM_TYPE_SINT;
fmt->bytes_per_frame = 4 * fmt->channels_per_frame;
return (pcm_reader_t *)self;
}

View File

@ -6,6 +6,7 @@
#define PCM_READER_H
#include "lpcm.h"
#include "metadata.h"
typedef struct pcm_reader_t pcm_reader_t;
@ -54,11 +55,7 @@ int64_t pcm_get_position(pcm_reader_t *r)
return r->vtbl->get_position(r);
}
static inline
int64_t pcm_read_frames(pcm_reader_t *r, void *data, unsigned nframes)
{
return r->vtbl->read_frames(r, data, nframes);
}
int pcm_read_frames(pcm_reader_t *r, void *data, unsigned nframes);
static inline
void pcm_teardown(pcm_reader_t **r)
@ -111,8 +108,17 @@ int pcm_scanb(pcm_io_context_t *io, const char *fmt, ...);
int apple_chan_chunk(pcm_io_context_t *io, uint32_t chunk_size,
pcm_sample_description_t *fmt, uint8_t *mapping);
pcm_reader_t *wav_open(pcm_io_context_t *io, int ignore_length);
pcm_reader_t *raw_open(pcm_io_context_t *io,
const pcm_sample_description_t *desc);
pcm_reader_t *caf_open(pcm_io_context_t *io,
aacenc_tag_callback_t tag_callback, void *tag_ctx);
pcm_reader_t *pcm_open_native_converter(pcm_reader_t *reader);
pcm_reader_t *pcm_open_float_converter(pcm_reader_t *reader);
pcm_reader_t *pcm_open_sint16_converter(pcm_reader_t *reader);
pcm_reader_t *extrapolater_open(pcm_reader_t *reader);
pcm_reader_t *limiter_open(pcm_reader_t *reader);
#endif

View File

@ -19,15 +19,35 @@
#include "m4af_endian.h"
#include "catypes.h"
int pcm_read_frames(pcm_reader_t *r, void *data, unsigned nframes)
{
int n;
unsigned count = 0;
uint8_t *bp = data;
unsigned bpf = pcm_get_format(r)->bytes_per_frame;
do {
n = r->vtbl->read_frames(r, bp, nframes - count);
if (n > 0) {
count += n;
bp += n * bpf;
}
} while (n > 0 && count < nframes);
return count;
}
int pcm_read(pcm_io_context_t *io, void *buffer, uint32_t size)
{
int rc;
uint32_t count = 0;
uint8_t *bp = buffer;
do {
rc = io->vtbl->read(io->cookie, buffer, size - count);
if (rc > 0)
rc = io->vtbl->read(io->cookie, bp, size - count);
if (rc > 0) {
count += rc;
bp += rc;
}
} while (rc > 0 && count < size);
return count > 0 ? count : rc;
}
@ -204,7 +224,7 @@ int apple_chan_chunk(pcm_io_context_t *io, uint32_t chunk_size,
switch (mChannelLayoutTag) {
case kAudioChannelLayoutTag_UseChannelBitmap:
ENSURE(bitcount(mask) == nchannels);
ENSURE(bitcount(mChannelBitmap) == nchannels);
TRY_IO(pcm_skip(io, chunk_size - 12));
fmt->channel_mask = mChannelBitmap;
for (i = 0; i < nchannels; ++i)

View File

@ -43,10 +43,10 @@ static int64_t get_position(pcm_reader_t *reader)
static int read_frames(pcm_reader_t *reader, void *buffer, unsigned nframes)
{
unsigned i, count;
pcm_sint16_converter_t *self = (pcm_sint16_converter_t *)reader;
const pcm_sample_description_t *sfmt = pcm_get_format(self->src);
unsigned bytes = nframes * sfmt->bytes_per_frame;
if (self->capacity < bytes) {
void *p = realloc(self->pivot, bytes);
if (!p) return -1;
@ -54,8 +54,25 @@ static int read_frames(pcm_reader_t *reader, void *buffer, unsigned nframes)
self->capacity = bytes;
}
nframes = pcm_read_frames(self->src, self->pivot, nframes);
if (pcm_convert_to_native_sint16(sfmt, self->pivot, nframes, buffer) < 0)
return -1;
count = nframes * sfmt->channels_per_frame;
if (PCM_IS_FLOAT(sfmt)) {
float *ip = self->pivot;
int16_t *op = buffer;
for (i = 0; i < count; ++i)
op[i] = pcm_clip(ip[i] * 32768.0, -32768.0, 32767.0);
} else {
int32_t *ip = self->pivot;
int16_t *op = buffer;
if (sfmt->bits_per_channel <= 16) {
for (i = 0; i < count; ++i)
op[i] = ip[i] >> 16;
} else {
for (i = 0; i < count; ++i) {
int n = ((ip[i] >> 15) + 1) >> 1;
op[i] = (n == 0x8000) ? 0x7fff : n;
}
}
}
return nframes;
}
@ -83,12 +100,8 @@ pcm_reader_t *pcm_open_sint16_converter(pcm_reader_t *reader)
self->vtbl = &my_vtable;
memcpy(&self->format, pcm_get_format(reader), sizeof(self->format));
fmt = &self->format;
#if WORDS_BIGENDIAN
fmt->sample_type = PCM_TYPE_SINT_BE;
#else
fmt->sample_type = PCM_TYPE_SINT;
#endif
fmt->bits_per_channel = 16;
fmt->sample_type = PCM_TYPE_SINT;
fmt->bytes_per_frame = 2 * fmt->channels_per_frame;
return (pcm_reader_t *)self;
}

View File

@ -14,7 +14,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include "wav_reader.h"
#include "pcm_reader.h"
#define RIFF_FOURCC(a,b,c,d) ((a)|((b)<<8)|((c)<<16)|((d)<<24))

View File

@ -1,15 +0,0 @@
/*
* Copyright (C) 2013 nu774
* For conditions of distribution and use, see copyright notice in COPYING
*/
#ifndef WAV_READER_H
#define WAV_READER_H
#include "lpcm.h"
#include "pcm_reader.h"
pcm_reader_t *wav_open(pcm_io_context_t *io, int ignore_length);
pcm_reader_t *raw_open(pcm_io_context_t *io,
const pcm_sample_description_t *desc);
#endif

View File

@ -1,4 +1,4 @@
#ifndef VERSION_H
#define VERSION_H
const char *fdkaac_version = "0.5.1";
const char *fdkaac_version = "0.6.0";
#endif