1
0
Fork 0
forked from len0rd/rockbox

Initial commit of Monkey's Audio (.ape/.mac) support. Note that Monkey's is an extremely CPU-intensive codec, and that the decoding speed is directly related to the compression level (-c1000, -c2000, -c3000, -c4000 or -c5000) used when encoding the file. Current performance is: -c1000 to -c3000 are realtime on a Gigabeat, -c1000 is realtime on Coldfire targets (H100, H300 and Cowon), and nothing is realtime on PortalPlayer targets (iPods, H10, Sansa). Hopefully this can be improved. More information at FS #7256.

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13562 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Dave Chapman 2007-06-05 16:58:29 +00:00
parent 887b31c01a
commit 520274219a
36 changed files with 3413 additions and 23 deletions

View file

@ -17,7 +17,7 @@ ifdef APPEXTRA
endif
ifdef SOFTWARECODECS
CODECLIBS = -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex
CODECLIBS = -lmad -la52 -lffmpegFLAC -lTremor -lwavpack -lmusepack -lalac -lfaad -lm4a -lspeex -ldemac
endif
# we "borrow" the plugin LDS file
@ -39,7 +39,7 @@ DIRS = .
CODECDEPS = $(LINKCODEC) $(BUILDDIR)/libcodec.a
.PHONY: libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a
.PHONY: libmad liba52 libffmpegFLAC libTremor libspeex libwavpack libmusepack libalac libfaad libm4a libdemac
OUTPUT = $(SOFTWARECODECS)
@ -64,6 +64,7 @@ $(OBJDIR)/wavpack.elf : $(OBJDIR)/wavpack.o $(BUILDDIR)/libwavpack.a $(OBJDIR)/c
$(OBJDIR)/alac.elf : $(OBJDIR)/alac.o $(BUILDDIR)/libalac.a $(BUILDDIR)/libm4a.a $(OBJDIR)/codec_crt0.o
$(OBJDIR)/aac.elf : $(OBJDIR)/aac.o $(BUILDDIR)/libfaad.a $(BUILDDIR)/libm4a.a $(OBJDIR)/codec_crt0.o
$(OBJDIR)/shorten.elf : $(OBJDIR)/shorten.o $(BUILDDIR)/libffmpegFLAC.a $(OBJDIR)/codec_crt0.o
$(OBJDIR)/ape.elf : $(OBJDIR)/ape.o $(BUILDDIR)/libdemac.a $(OBJDIR)/codec_crt0.o
$(OBJDIR)/aiff_enc.elf: $(OBJDIR)/aiff_enc.o $(OBJDIR)/codec_crt0.o
$(OBJDIR)/mp3_enc.elf: $(OBJDIR)/mp3_enc.o $(OBJDIR)/codec_crt0.o
$(OBJDIR)/wav_enc.elf: $(OBJDIR)/wav_enc.o $(OBJDIR)/codec_crt0.o
@ -198,8 +199,14 @@ libfaad:
$(SILENT)mkdir -p $(OBJDIR)/libfaad
$(call PRINTS,MAKE in libfaad)$(MAKE) -C libfaad OBJDIR=$(OBJDIR)/libfaad OUTPUT=$(BUILDDIR)/libfaad.a
$(BUILDDIR)/libdemac.a: libdemac
libdemac:
$(SILENT)mkdir -p $(OBJDIR)/libdemac
$(call PRINTS,MAKE in libdemac)$(MAKE) -C demac/libdemac OBJDIR=$(OBJDIR)/libdemac OUTPUT=$(BUILDDIR)/libdemac.a
clean:
$(call PRINTS,cleaning codecs)rm -fr $(OBJDIR)/libmad $(BUILDDIR)/libmad.a $(OBJDIR)/liba52 $(BUILDDIR)/liba52.a $(OBJDIR)/libffmpegFLAC $(BUILDDIR)/libffmpegFLAC.a $(OBJDIR)/Tremor $(BUILDDIR)/libTremor.a $(OBJDIR)/libspeex $(BUILDDIR)/libSpeex.a $(OBJDIR)/libwavpack $(BUILDDIR)/libwavpack.a $(OBJDIR)/libmusepack $(BUILDDIR)/libmusepack.a $(OBJDIR)/libalac $(BUILDDIR)/libalac.a $(OBJDIR)/libfaad $(BUILDDIR)/libfaad.a $(OBJDIR)/libm4a $(BUILDDIR)/libm4a.a
$(call PRINTS,cleaning codecs)rm -fr $(OBJDIR)/libmad $(BUILDDIR)/libmad.a $(OBJDIR)/liba52 $(BUILDDIR)/liba52.a $(OBJDIR)/libffmpegFLAC $(BUILDDIR)/libffmpegFLAC.a $(OBJDIR)/Tremor $(BUILDDIR)/libTremor.a $(OBJDIR)/libspeex $(BUILDDIR)/libSpeex.a $(OBJDIR)/libwavpack $(BUILDDIR)/libwavpack.a $(OBJDIR)/libmusepack $(BUILDDIR)/libmusepack.a $(OBJDIR)/libalac $(BUILDDIR)/libalac.a $(OBJDIR)/libfaad $(BUILDDIR)/libfaad.a $(OBJDIR)/libm4a $(BUILDDIR)/libm4a.a $(OBJDIR)/libdemac $(BUILDDIR)/libdemac.a
$(SILENT)$(MAKE) -C libmad clean OBJDIR=$(OBJDIR)/libmad
$(SILENT)$(MAKE) -C liba52 clean OBJDIR=$(OBJDIR)/liba52
$(SILENT)$(MAKE) -C libffmpegFLAC clean OBJDIR=$(OBJDIR)/libffmpegFLAC
@ -210,6 +217,7 @@ clean:
$(SILENT)$(MAKE) -C libalac clean OBJDIR=$(OBJDIR)/libalac
$(SILENT)$(MAKE) -C libfaad clean OBJDIR=$(OBJDIR)/libfaad
$(SILENT)$(MAKE) -C libm4a clean OBJDIR=$(OBJDIR)/libm4a
$(SILENT)$(MAKE) -C demac/libdemac clean OBJDIR=$(OBJDIR)/libdemac
$(SILENT)$(MAKE) -C lib clean OBJDIR=$(OBJDIR)/lib
ifneq ($(MAKECMDGOALS),clean)

View file

@ -11,6 +11,7 @@ alac.c
#if MEMORYSIZE > 1
aac.c
#endif
ape.c
shorten.c
aiff.c
speex.c

162
apps/codecs/ape.c Normal file
View file

@ -0,0 +1,162 @@
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2007 Dave Chapman
*
* All files in this archive are subject to the GNU General Public License.
* See the file COPYING in the source tree root for full license agreement.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "codeclib.h"
#define ROCKBOX
#include <codecs/demac/libdemac/demac.h>
CODEC_HEADER
#define BLOCKS_PER_LOOP 4608
#define MAX_CHANNELS 2
#define MAX_BYTESPERSAMPLE 3
#define INPUT_CHUNKSIZE (32*1024)
/* 4608*4 = 18432 bytes per channel */
static int32_t decoded0[BLOCKS_PER_LOOP] IBSS_ATTR;
static int32_t decoded1[BLOCKS_PER_LOOP] IBSS_ATTR;
#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
/* this is the codec entry point */
enum codec_status codec_main(void)
{
struct ape_ctx_t ape_ctx;
uint32_t samplesdone;
uint32_t elapsedtime;
size_t bytesleft;
int retval;
uint32_t currentframe;
int nblocks;
int bytesconsumed;
unsigned char* inbuffer;
int blockstodecode;
int res;
int firstbyte;
/* Generic codec initialisation */
ci->configure(CODEC_SET_FILEBUF_WATERMARK, 1024*512);
ci->configure(CODEC_SET_FILEBUF_CHUNKSIZE, 1024*128);
ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
next_track:
if (codec_init()) {
LOGF("APE: Error initialising codec\n");
retval = CODEC_ERROR;
goto exit;
}
inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
/* Read the file headers to populate the ape_ctx struct */
if (ape_parseheaderbuf(inbuffer,&ape_ctx) < 0) {
LOGF("APE: Error reading header\n");
retval = CODEC_ERROR;
goto exit;
}
ci->advance_buffer(ape_ctx.firstframe);
while (!*ci->taginfo_ready && !ci->stop_codec)
ci->sleep(1);
ci->configure(DSP_SWITCH_FREQUENCY, ape_ctx.samplerate);
ci->configure(DSP_SET_STEREO_MODE, ape_ctx.channels == 1 ?
STEREO_MONO : STEREO_NONINTERLEAVED);
codec_set_replaygain(ci->id3);
/* The main decoding loop */
currentframe = 0;
samplesdone = 0;
/* Initialise the buffer */
inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */
/* The main decoding loop - we decode the frames a small chunk at a time */
while (currentframe < ape_ctx.totalframes)
{
/* Calculate how many blocks there are in this frame */
if (currentframe == (ape_ctx.totalframes - 1))
nblocks = ape_ctx.finalframeblocks;
else
nblocks = ape_ctx.blocksperframe;
ape_ctx.currentframeblocks = nblocks;
/* Initialise the frame decoder */
init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed);
ci->advance_buffer(bytesconsumed);
inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
/* Decode the frame a chunk at a time */
while (nblocks > 0)
{
ci->yield();
if (ci->stop_codec || ci->new_track) {
break;
}
blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);
if ((res = decode_chunk(&ape_ctx, inbuffer, &firstbyte,
&bytesconsumed,
decoded0, decoded1,
blockstodecode)) < 0)
{
/* Frame decoding error, abort */
LOGF("APE: Frame %d, error %d\n",currentframe,res);
retval = CODEC_ERROR;
goto done;
}
ci->yield();
ci->pcmbuf_insert(decoded0, decoded1, blockstodecode);
/* Update the elapsed-time indicator */
samplesdone += blockstodecode;
elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
ci->set_elapsed(elapsedtime);
ci->advance_buffer(bytesconsumed);
inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
/* Decrement the block count */
nblocks -= blockstodecode;
}
currentframe++;
}
retval = CODEC_OK;
done:
LOGF("APE: Decoded %ld samples\n",samplesdone);
if (ci->request_next_track())
goto next_track;
exit:
return retval;
}

339
apps/codecs/demac/COPYING Normal file
View file

@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.

View file

@ -0,0 +1,43 @@
# $Id:$
FILTERS = libdemac/filter_16_11.o libdemac/filter_64_11.o libdemac/filter_256_13.o libdemac/filter_32_10.o libdemac/filter_1280_15.o
LIBOBJS = libdemac/parser.o libdemac/decoder.o libdemac/entropy.o libdemac/predictor.o libdemac/crc.o $(FILTERS)
OBJS = demac.o wavwrite.o $(LIBOBJS)
CFLAGS = -Wall -O3 -Ilibdemac
ifeq ($(findstring CYGWIN,$(shell uname)),CYGWIN)
EXT = .exe
CROSS =
CFLAGS += -mno-cygwin
else
ifdef WIN
EXT = .exe
CROSS = i586-mingw32msvc-
else
EXT =
CROSS =
endif
endif
CC = $(CROSS)gcc
STRIP = $(CROSS)strip
OUTPUT = demac$(EXT)
all: $(OUTPUT)
$(OUTPUT): $(OBJS)
$(CC) -o $(OUTPUT) $(OBJS)
.c.o :
$(CC) $(CFLAGS) $(INC) -c -o $@ $<
libdemac/filter_16_11.o: libdemac/filter.c
libdemac/filter_64_11.o: libdemac/filter.c
libdemac/filter_256_13.o: libdemac/filter.c
libdemac/filter_1280_15.o: libdemac/filter.c
libdemac/filter_32_10.o: libdemac/filter.c
libdemac/entropy.o: libdemac/rangecoding.h
clean:
rm -f $(OUTPUT) $(OBJS) *~ */*~

69
apps/codecs/demac/README Normal file
View file

@ -0,0 +1,69 @@
demac - a decoder for Monkey's Audio files.
Introduction
demac is an implementation in portable ANSI C of a decoder for the
Monkey's Audio lossless compression format. It has the following
features:
* Open source (GNU GPL)
* Written in portable ANSI C
* Designed for use on low memory and embedded devices. All internal
buffers are statically declared - the core library doesn't require
malloc/free. This has the disadvantage that the library isn't
re-entrant.
Compatibility
libdemac is still in the early stages of development but has been
relatively well tested with v3.99 files at all compression levels.
v3.97 files have received less testing - 16-bit files seem to work,
but 24-bit files are causing problems in the range decoder.
Files earlier than v3.97 are not supported by libdemac, but support
might be added in the future.
Source Code
The source code in this directory is structured as follows:
demac/Makefile - Makefile for the standalone demac decoder
demac/demac.c - Simple standalone test program to decoder an APE file to WAV
demac/wavwrite.[ch] - Helper functions for demac.c
demac/libdemac/Makefile - A Makefile for use in Rockbox
demac/libdemac/*.[ch] - The main libdemac code
Latest Version
The latest version of demac and libdemac can always be found in the
"apps/codecs/demac/" directory in the Rockbox source. You can check
this out from svn with the command:
svn co svn://svn.rockbox.org/rockbox/trunk/apps/codecs/demac demac
Or browse the source code online here:
http://svn.rockbox.org/viewvc.cgi/trunk/apps/codecs/demac
Acknowledgements
Thanks to Matt. T. Ashland for writing Monkey's Audio. His website
can be found here: http://www.monkeysaudio.com
Copyright and license
libdemac is (C) 2007 Dave Chapman and is licensed under the GNU
GPL. See the COPYING file in this directory.
The exception is the majority of rangecoding.h, which is (C) 1997,
1998, 1999, 2000 Michael Schindler and is also licensed under the GPL.
See that source file for full details.

272
apps/codecs/demac/demac.c Normal file
View file

@ -0,0 +1,272 @@
/*
demac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
/*
This example is intended to demonstrate how the decoder can be used in
embedded devices - there is no usage of dynamic memory (i.e. no
malloc/free) and small buffer sizes are chosen to minimise both the
memory usage and decoding latency.
This implementation requires the following memory and supports decoding of all APE files up to 24-bit Stereo.
32768 - data from the input stream to be presented to the decoder in one contiguous chunk.
18432 - decoding buffer (left channel)
18432 - decoding buffer (right channel)
17408+5120+2240 - buffers used for filter histories (compression levels 2000-5000)
In addition, this example uses a static 27648 byte buffer as temporary
storage for outputting the data to a WAV file but that could be
avoided by writing the decoded data one sample at a time.
*/
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "demac.h"
#include "wavwrite.h"
#ifndef __WIN32__
#define O_BINARY 0
#endif
#define CALC_CRC 1
#define BLOCKS_PER_LOOP 4608
#define MAX_CHANNELS 2
#define MAX_BYTESPERSAMPLE 3
#define INPUT_CHUNKSIZE (32*1024)
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
/* 4608*2*3 = 27648 bytes */
static unsigned char wavbuffer[BLOCKS_PER_LOOP*MAX_CHANNELS*MAX_BYTESPERSAMPLE];
/* 4608*4 = 18432 bytes per channel */
static int32_t decoded0[BLOCKS_PER_LOOP];
static int32_t decoded1[BLOCKS_PER_LOOP];
/* We assume that 32KB of compressed data is enough to extract up to
27648 bytes of decompressed data. */
static unsigned char inbuffer[INPUT_CHUNKSIZE];
int ape_decode(char* infile, char* outfile)
{
int fd;
int fdwav;
int currentframe;
int nblocks;
int bytesconsumed;
struct ape_ctx_t ape_ctx;
int i, n;
unsigned char* p;
int bytesinbuffer;
int blockstodecode;
int res;
int firstbyte;
int16_t sample16;
int32_t sample32;
uint32_t frame_crc;
int crc_errors = 0;
fd = open(infile,O_RDONLY|O_BINARY);
if (fd < 0) return -1;
/* Read the file headers to populate the ape_ctx struct */
if (ape_parseheader(fd,&ape_ctx) < 0) {
printf("Cannot read header\n");
close(fd);
return -1;
}
if ((ape_ctx.fileversion < APE_MIN_VERSION) || (ape_ctx.fileversion > APE_MAX_VERSION)) {
printf("Unsupported file version - %.2f\n", ape_ctx.fileversion/1000.0);
close(fd);
return -2;
}
//ape_dumpinfo(&ape_ctx);
printf("Decoding file - v%.2f, compression level %d\n",ape_ctx.fileversion/1000.0,ape_ctx.compressiontype);
/* Open the WAV file and write a canonical 44-byte WAV header
based on the audio format information in the ape_ctx struct.
NOTE: This example doesn't write the original WAV header and
tail data which are (optionally) stored in the APE file.
*/
fdwav = open_wav(&ape_ctx,outfile);
currentframe = 0;
/* Initialise the buffer */
lseek(fd, ape_ctx.firstframe, SEEK_SET);
bytesinbuffer = read(fd, inbuffer, INPUT_CHUNKSIZE);
firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */
/* The main decoding loop - we decode the frames a small chunk at a time */
while (currentframe < ape_ctx.totalframes)
{
/* Calculate how many blocks there are in this frame */
if (currentframe == (ape_ctx.totalframes - 1))
nblocks = ape_ctx.finalframeblocks;
else
nblocks = ape_ctx.blocksperframe;
ape_ctx.currentframeblocks = nblocks;
/* Initialise the frame decoder */
init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed);
/* Update buffer */
memmove(inbuffer,inbuffer + bytesconsumed, bytesinbuffer - bytesconsumed);
bytesinbuffer -= bytesconsumed;
n = read(fd, inbuffer + bytesinbuffer, INPUT_CHUNKSIZE - bytesinbuffer);
bytesinbuffer += n;
#if CALC_CRC
frame_crc = ape_initcrc();
#endif
/* Decode the frame a chunk at a time */
while (nblocks > 0)
{
blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks);
if ((res = decode_chunk(&ape_ctx, inbuffer, &firstbyte,
&bytesconsumed,
decoded0, decoded1,
blockstodecode)) < 0)
{
/* Frame decoding error, abort */
close(fd);
return res;
}
/* Convert the output samples to WAV format and write to output file */
p = wavbuffer;
if (ape_ctx.bps == 16) {
for (i = 0 ; i < blockstodecode ; i++)
{
sample16 = decoded0[i];
*(p++) = sample16 & 0xff;
*(p++) = (sample16&0xff00) >> 8;
if (ape_ctx.channels == 2) {
sample16 = decoded1[i];
*(p++) = sample16 & 0xff;
*(p++) = (sample16&0xff00) >> 8;
}
}
} else if (ape_ctx.bps == 24) {
for (i = 0 ; i < blockstodecode ; i++)
{
sample32 = decoded0[i];
*(p++) = sample32 & 0xff;
*(p++) = (sample32&0xff00) >> 8;
*(p++) = (sample32&0xff0000) >> 16;
if (ape_ctx.channels == 2) {
sample32 = decoded1[i];
*(p++) = sample32 & 0xff;
*(p++) = (sample32&0xff00) >> 8;
*(p++) = (sample32&0xff0000) >> 16;
}
}
}
#if CALC_CRC
frame_crc = ape_updatecrc(wavbuffer, p - wavbuffer, frame_crc);
#endif
write(fdwav,wavbuffer,p - wavbuffer);
/* Update the buffer */
memmove(inbuffer,inbuffer + bytesconsumed, bytesinbuffer - bytesconsumed);
bytesinbuffer -= bytesconsumed;
n = read(fd, inbuffer + bytesinbuffer, INPUT_CHUNKSIZE - bytesinbuffer);
bytesinbuffer += n;
/* Decrement the block count */
nblocks -= blockstodecode;
}
#if CALC_CRC
frame_crc = ape_finishcrc(frame_crc);
if (ape_ctx.CRC != frame_crc)
{
fprintf(stderr,"CRC error in frame %d\n",currentframe);
crc_errors++;
}
#endif
currentframe++;
}
close(fd);
close(fdwav);
if (crc_errors > 0)
return -1;
else
return 0;
}
int main(int argc, char* argv[])
{
int res;
if (argc != 3) {
fprintf(stderr,"Usage: demac infile.ape outfile.wav\n");
return 0;
}
res = ape_decode(argv[1], argv[2]);
if (res < 0)
{
fprintf(stderr,"DECODING ERROR %d, ABORTING\n", res);
}
else
{
fprintf(stderr,"DECODED OK - NO CRC ERRORS.\n");
}
return 0;
}

View file

@ -0,0 +1,43 @@
# __________ __ ___.
# Open \______ \ ____ ____ | | _\_ |__ _______ ___
# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
# \/ \/ \/ \/ \/
# $Id:$
#
INCLUDES=-I$(APPSDIR) -I.. -I. -I$(FIRMDIR)/include -I$(FIRMDIR)/export \
-I$(FIRMDIR)/common -I$(FIRMDIR)/drivers -I$(BUILDDIR)
ifdef APPEXTRA
INCLUDES += $(patsubst %,-I$(APPSDIR)/%,$(subst :, ,$(APPEXTRA)))
endif
DEMACOPTS = -O3 -DROCKBOX
CFLAGS = $(INCLUDES) $(GCCOPTS) $(TARGET_INC) $(DEMACOPTS) $(TARGET) \
$(EXTRA_DEFINES) -DMEM=${MEMORYSIZE} $(PROFILE_OPTS)
# This sets up 'SRC' based on the files mentioned in SOURCES
include $(TOOLSDIR)/makesrc.inc
SOURCES = $(SRC)
OBJS2 := $(SRC:%.c=$(OBJDIR)/%.o)
OBJS = $(patsubst %.S, $(OBJDIR)/%.o, $(OBJS2))
DEPFILE = $(OBJDIR)/dep-libdemac
DIRS =
all: $(OUTPUT)
$(OUTPUT): $(OBJS)
$(call PRINTS,AR+RANLIB $(@F))$(AR) ruv $@ $+ >/dev/null 2>&1
$(SILENT)$(RANLIB) $@
include $(TOOLSDIR)/make.inc
clean:
$(call PRINTS,cleaning libdemac)rm -f $(OBJS) $(OUTPUT) $(DEPFILE)
ifneq ($(MAKECMDGOALS),clean)
-include $(DEPFILE)
endif

View file

@ -0,0 +1,10 @@
crc.c
predictor.c
entropy.c
decoder.c
parser.c
filter_1280_15.c
filter_16_11.c
filter_256_13.c
filter_32_10.c
filter_64_11.c

View file

@ -0,0 +1,119 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <inttypes.h>
static uint32_t crctab32[] =
{
0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA,
0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3,
0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988,
0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91,
0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE,
0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7,
0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC,
0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5,
0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172,
0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B,
0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940,
0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59,
0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116,
0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F,
0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924,
0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D,
0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A,
0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433,
0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818,
0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01,
0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E,
0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457,
0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C,
0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65,
0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2,
0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB,
0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0,
0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9,
0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086,
0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F,
0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4,
0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD,
0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A,
0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683,
0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8,
0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1,
0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE,
0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7,
0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC,
0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5,
0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252,
0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B,
0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60,
0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79,
0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236,
0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F,
0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04,
0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D,
0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A,
0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713,
0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38,
0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21,
0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E,
0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777,
0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C,
0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45,
0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2,
0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB,
0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0,
0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9,
0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6,
0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF,
0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94,
0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D
};
uint32_t ape_initcrc(void)
{
return 0xffffffff;
}
/* Update the CRC from a block of WAV-format audio data */
uint32_t ape_updatecrc(unsigned char *block, int count, uint32_t crc)
{
while (count--)
crc = (crc >> 8) ^ crctab32[(crc & 0xff) ^ *block++];
return crc;
}
uint32_t ape_finishcrc(uint32_t crc)
{
crc ^= 0xffffffff;
crc >>= 1;
return crc;
}

View file

@ -0,0 +1,184 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <inttypes.h>
#include <string.h>
#include "demac.h"
#include "predictor.h"
#include "entropy.h"
#include "filter.h"
/* Statically allocate the filter buffers */
static int16_t filterbuf32[(32*3 + HISTORY_SIZE) * 2] IBSS_ATTR; /* 4480 bytes */
static int16_t filterbuf256[(256*3 + HISTORY_SIZE) * 2] IBSS_ATTR; /* 5120 bytes */
/* This is only needed for "insane" files, and no Rockbox targets can
hope to decode them in realtime anyway. */
static int16_t filterbuf1280[(1280*3 + HISTORY_SIZE) * 2]; /* 17408 bytes */
void init_frame_decoder(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed)
{
init_entropy_decoder(ape_ctx, inbuffer, firstbyte, bytesconsumed);
//printf("CRC=0x%08x\n",ape_ctx->CRC);
//printf("Flags=0x%08x\n",ape_ctx->frameflags);
init_predictor_decoder(ape_ctx);
switch (ape_ctx->compressiontype)
{
case 2000:
init_filter_16_11(filterbuf32);
break;
case 3000:
init_filter_64_11(filterbuf256);
break;
case 4000:
init_filter_256_13(filterbuf256);
init_filter_32_10(filterbuf32);
break;
case 5000:
init_filter_1280_15(filterbuf1280);
init_filter_256_13(filterbuf256);
init_filter_16_11(filterbuf32);
}
}
int decode_chunk(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed,
int32_t* decoded0, int32_t* decoded1,
int count)
{
int res;
int32_t left, right;
#ifdef ROCKBOX
int scale = (APE_OUTPUT_DEPTH - ape_ctx->bps);
#define SCALE(x) ((x) << scale)
#else
#define SCALE(x) (x)
#endif
if ((ape_ctx->channels==1) || (ape_ctx->frameflags & APE_FRAMECODE_PSEUDO_STEREO)) {
if (ape_ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
res = entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed, decoded0, decoded1, count);
/* We are pure silence, so we're done. */
return 0;
} else {
res = entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed, decoded0, NULL, count);
}
switch (ape_ctx->compressiontype)
{
case 2000:
apply_filter_16_11(ape_ctx->fileversion,decoded0,NULL,count);
break;
case 3000:
apply_filter_64_11(ape_ctx->fileversion,decoded0,NULL,count);
break;
case 4000:
apply_filter_32_10(ape_ctx->fileversion,decoded0,NULL,count);
apply_filter_256_13(ape_ctx->fileversion,decoded0,NULL,count);
break;
case 5000:
apply_filter_16_11(ape_ctx->fileversion,decoded0,NULL,count);
apply_filter_256_13(ape_ctx->fileversion,decoded0,NULL,count);
apply_filter_1280_15(ape_ctx->fileversion,decoded0,NULL,count);
}
/* Now apply the predictor decoding */
predictor_decode_mono(ape_ctx,decoded0,count);
if (ape_ctx->channels==2) {
/* Pseudo-stereo - just copy left channel to right channel */
while (count--)
{
left = *decoded0;
*(decoded1++) = *(decoded0++) = SCALE(left);
}
} else {
/* Mono - do nothing unless it's 8-bit audio */
if (ape_ctx->bps == 8) {
/* TODO: Handle 8-bit streams */
}
}
} else { /* Stereo */
if (ape_ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
/* We are pure silence, so we're done. */
return 0;
}
res = entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed, decoded0, decoded1, count);
/* Apply filters - compression type 1000 doesn't have any */
switch (ape_ctx->compressiontype)
{
case 2000:
apply_filter_16_11(ape_ctx->fileversion,decoded0,decoded1,count);
break;
case 3000:
apply_filter_64_11(ape_ctx->fileversion,decoded0,decoded1,count);
break;
case 4000:
apply_filter_32_10(ape_ctx->fileversion,decoded0,decoded1,count);
apply_filter_256_13(ape_ctx->fileversion,decoded0,decoded1,count);
break;
case 5000:
apply_filter_16_11(ape_ctx->fileversion,decoded0,decoded1,count);
apply_filter_256_13(ape_ctx->fileversion,decoded0,decoded1,count);
apply_filter_1280_15(ape_ctx->fileversion,decoded0,decoded1,count);
}
/* Now apply the predictor decoding */
predictor_decode_stereo(ape_ctx,decoded0,decoded1,count);
if (ape_ctx->bps == 8) {
/* TODO: Handle 8-bit streams */
} else {
/* Decorrelate and scale to output depth */
while (count--)
{
left = *decoded1 - (*decoded0 / 2);
right = left + *decoded0;
*(decoded0++) = SCALE(left);
*(decoded1++) = SCALE(right);
}
}
}
return res;
}

View file

@ -0,0 +1,40 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_DECODER_H
#define _APE_DECODER_H
#include <inttypes.h>
#include "parser.h"
void init_frame_decoder(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed);
int decode_chunk(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed,
int32_t* decoded0, int32_t* decoded1,
int count);
#endif

View file

@ -0,0 +1,45 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_DECODER_H
#define _APE_DECODER_H
#include <inttypes.h>
#include "parser.h"
void init_frame_decoder(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed);
int decode_chunk(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed,
int32_t* decoded0, int32_t* decoded1,
int count);
uint32_t ape_initcrc(void);
uint32_t ape_updatecrc(unsigned char *block, int count, uint32_t crc);
uint32_t ape_finishcrc(uint32_t crc);
#endif

View file

@ -0,0 +1,314 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <inttypes.h>
#include <string.h>
#include "parser.h"
#include "entropy.h"
#include "rangecoding.h" /* Range-coding (static inline) functions */
#define MODEL_ELEMENTS 64
/*
The following counts arrays for use with the range decoder are
hard-coded in the Monkey's Audio decoder.
*/
static const int counts_3970[65] ICONST_ATTR =
{
0,14824,28224,39348,47855,53994,58171,60926,
62682,63786,64463,64878,65126,65276,65365,65419,
65450,65469,65480,65487,65491,65493,65494,65495,
65496,65497,65498,65499,65500,65501,65502,65503,
65504,65505,65506,65507,65508,65509,65510,65511,
65512,65513,65514,65515,65516,65517,65518,65519,
65520,65521,65522,65523,65524,65525,65526,65527,
65528,65529,65530,65531,65532,65533,65534,65535,
65536
};
/* counts_diff_3970[i] = counts_3970[i+1] - counts_3970[i] */
static const int counts_diff_3970[64] ICONST_ATTR =
{
14824,13400,11124,8507,6139,4177,2755,1756,
1104,677,415,248,150,89,54,31,
19,11,7,4,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
};
static const int counts_3980[65] ICONST_ATTR =
{
0,19578,36160,48417,56323,60899,63265,64435,
64971,65232,65351,65416,65447,65466,65476,65482,
65485,65488,65490,65491,65492,65493,65494,65495,
65496,65497,65498,65499,65500,65501,65502,65503,
65504,65505,65506,65507,65508,65509,65510,65511,
65512,65513,65514,65515,65516,65517,65518,65519,
65520,65521,65522,65523,65524,65525,65526,65527,
65528,65529,65530,65531,65532,65533,65534,65535,
65536
};
/* counts_diff_3980[i] = counts_3980[i+1] - counts_3980[i] */
static const int counts_diff_3980[64] ICONST_ATTR =
{
19578,16582,12257,7906,4576,2366,1170,536,
261,119,65,31,19,10,6,3,
3,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
};
/*
range_get_symbol_* functions based on main decoding loop in simple_d.c from
http://www.compressconsult.com/rangecoder/rngcod13.zip
(c) Michael Schindler
*/
static inline int range_get_symbol_3980(void)
{
int symbol, cf;
cf = range_decode_culshift(16);
/* figure out the symbol inefficiently; a binary search would be much better */
for (symbol = 0; counts_3980[symbol+1] <= cf; symbol++);
range_decode_update(counts_diff_3980[symbol],counts_3980[symbol]);
return symbol;
}
static inline int range_get_symbol_3970(void)
{
int symbol, cf;
cf = range_decode_culshift(16);
/* figure out the symbol inefficiently; a binary search would be much better */
for (symbol = 0; counts_3970[symbol+1] <= cf; symbol++);
range_decode_update(counts_diff_3970[symbol],counts_3970[symbol]);
return symbol;
}
/* MAIN DECODING FUNCTIONS */
struct rice_t
{
uint32_t k;
uint32_t ksum;
};
static struct rice_t riceX IBSS_ATTR;
static struct rice_t riceY IBSS_ATTR;
static inline void update_rice(struct rice_t* rice, int x)
{
rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5);
if (rice->k == 0) {
rice->k = 1;
} else if (rice->ksum < ((uint32_t)1 << (rice->k + 4))) {
rice->k--;
} else if (rice->ksum >= ((uint32_t)1 << (rice->k + 5))) {
rice->k++;
}
}
static inline int entropy_decode3980(struct rice_t* rice)
{
int base, x, pivot, overflow;
pivot = rice->ksum >> 5;
if (pivot == 0) pivot=1;
overflow = range_get_symbol_3980();
if (overflow == (MODEL_ELEMENTS-1)) {
overflow = range_decode_short() << 16;
overflow |= range_decode_short();
}
if (pivot >= 0x10000) {
/* Codepath for 24-bit streams */
int nbits, lo_bits, base_hi, base_lo;
/* Count the number of bits in pivot */
nbits = 17; /* We know there must be at least 17 bits */
while ((pivot >> nbits) > 0) { nbits++; }
/* base_lo is the low (nbits-16) bits of base
base_hi is the high 16 bits of base
*/
lo_bits = (nbits - 16);
base_hi = range_decode_culfreq((pivot >> lo_bits) + 1);
range_decode_update(1, base_hi);
base_lo = range_decode_culfreq(1 << lo_bits);
range_decode_update(1, base_lo);
base = (base_hi << lo_bits) + base_lo;
} else {
/* Codepath for 16-bit streams */
base = range_decode_culfreq(pivot);
range_decode_update(1, base);
}
x = base + (overflow * pivot);
update_rice(rice, x);
/* Convert to signed */
if (x & 1)
return (x >> 1) + 1;
else
return -(x >> 1);
}
static inline int entropy_decode3970(struct rice_t* rice)
{
int x, tmpk;
int overflow = range_get_symbol_3970();
if (overflow == (MODEL_ELEMENTS - 1)) {
tmpk = range_decode_bits(5);
overflow = 0;
} else {
tmpk = (rice->k < 1) ? 0 : rice->k - 1;
}
if (tmpk <= 16) {
x = range_decode_bits(tmpk);
} else {
x = range_decode_short();
x |= (range_decode_bits(tmpk - 16) << 16);
}
x += (overflow << tmpk);
update_rice(rice, x);
/* Convert to signed */
if (x & 1)
return (x >> 1) + 1;
else
return -(x >> 1);
}
void init_entropy_decoder(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed)
{
bytebuffer = inbuffer;
bytebufferoffset = *firstbyte;
/* Read the CRC */
ape_ctx->CRC = read_byte();
ape_ctx->CRC = (ape_ctx->CRC << 8) | read_byte();
ape_ctx->CRC = (ape_ctx->CRC << 8) | read_byte();
ape_ctx->CRC = (ape_ctx->CRC << 8) | read_byte();
/* Read the frame flags if they exist */
ape_ctx->frameflags = 0;
if ((ape_ctx->fileversion > 3820) && (ape_ctx->CRC & 0x80000000)) {
ape_ctx->CRC &= ~0x80000000;
ape_ctx->frameflags = read_byte();
ape_ctx->frameflags = (ape_ctx->frameflags << 8) | read_byte();
ape_ctx->frameflags = (ape_ctx->frameflags << 8) | read_byte();
ape_ctx->frameflags = (ape_ctx->frameflags << 8) | read_byte();
}
/* Keep a count of the blocks decoded in this frame */
ape_ctx->blocksdecoded = 0;
/* Initialise the rice structs */
riceX.k = 10;
riceX.ksum = (1 << riceX.k) * 16;
riceY.k = 10;
riceY.ksum = (1 << riceY.k) * 16;
/* The first 8 bits of input are ignored. */
skip_byte();
range_start_decoding();
/* Return the new state of the buffer */
*bytesconsumed = (intptr_t)bytebuffer - (intptr_t)inbuffer;
*firstbyte = bytebufferoffset;
}
int entropy_decode(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed,
int32_t* decoded0, int32_t* decoded1,
int blockstodecode)
{
bytebuffer = inbuffer;
bytebufferoffset = *firstbyte;
ape_ctx->blocksdecoded += blockstodecode;
if (ape_ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE) {
/* We are pure silence, just memset the output buffer. */
memset(decoded0, 0, blockstodecode * sizeof(int32_t));
memset(decoded1, 0, blockstodecode * sizeof(int32_t));
} else {
if (ape_ctx->fileversion > 3970) {
while (blockstodecode--) {
*(decoded0++) = entropy_decode3980(&riceY);
if (decoded1 != NULL)
*(decoded1++) = entropy_decode3980(&riceX);
}
} else {
while (blockstodecode--) {
*(decoded0++) = entropy_decode3970(&riceY);
if (decoded1 != NULL)
*(decoded1++) = entropy_decode3970(&riceX);
}
}
}
if (ape_ctx->blocksdecoded == ape_ctx->currentframeblocks)
{
range_done_decoding();
}
/* Return the new state of the buffer */
*bytesconsumed = bytebuffer - inbuffer;
*firstbyte = bytebufferoffset;
return(0);
}

View file

@ -0,0 +1,40 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_ENTROPY_H
#define _APE_ENTROPY_H
#include <inttypes.h>
void init_entropy_decoder(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed);
int entropy_decode(struct ape_ctx_t* ape_ctx,
unsigned char* inbuffer, int* firstbyte,
int* bytesconsumed,
int32_t* decoded0, int32_t* decoded1,
int blockstodecode);
#endif

View file

@ -0,0 +1,215 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <string.h>
#include <inttypes.h>
#include "demac.h"
#include "filter.h"
#include "vector_math16.h"
struct filter_t {
int16_t* coeffs; /* ORDER entries */
/* We store all the filter delays in a single buffer */
int16_t* historybuffer; /* ORDER*2 + HISTORY_SIZE entries */
int16_t* delay;
int16_t* adaptcoeffs;
int avg;
};
/* We name the functions according to the ORDER and FRACBITS
pre-processor symbols and build multiple .o files from this .c file
- this increases code-size but gives the compiler more scope for
optimising the individual functions, as well as replacing a lot of
variables with constants.
*/
#if FRACBITS == 11
#if ORDER == 16
#define INIT_FILTER init_filter_16_11
#define APPLY_FILTER apply_filter_16_11
#elif ORDER == 64
#define INIT_FILTER init_filter_64_11
#define APPLY_FILTER apply_filter_64_11
#endif
#elif FRACBITS == 13
#define INIT_FILTER init_filter_256_13
#define APPLY_FILTER apply_filter_256_13
#elif FRACBITS == 10
#define INIT_FILTER init_filter_32_10
#define APPLY_FILTER apply_filter_32_10
#elif FRACBITS == 15
#define INIT_FILTER init_filter_1280_15
#define APPLY_FILTER apply_filter_1280_15
#endif
/* Some macros to handle the fixed-point stuff */
#define FP_HALF (1 << (FRACBITS - 1)) /* 0.5 in fixed-point format. */
#define FP_TO_INT(x) ((x + FP_HALF) >> FRACBITS); /* round(x) */
#define SATURATE(x) (int16_t)(((x) == (int16_t)(x)) ? (x) : ((x) >> 31) ^ 0x7FFF);
/* Apply the filter with state f to count entries in data[] */
static inline void do_apply_filter_3980(struct filter_t* f, int32_t* data, int count)
{
int res;
int absres;
while(count--)
{
res = FP_TO_INT(scalarproduct(f->delay - ORDER, f->coeffs));
if (*data < 0)
vector_add(f->coeffs, f->adaptcoeffs - ORDER);
else if (*data > 0)
vector_sub(f->coeffs, f->adaptcoeffs - ORDER);
/* Convert res from (32-FRACBITS).FRACBITS fixed-point format to an
integer (rounding to nearest) and add the input value to
it */
res += *data;
*data++ = res;
/* Update the output history */
*f->delay++ = SATURATE(res);
/* Version 3.98 and later files */
/* Update the adaption coefficients */
absres = (res < 0 ? -res : res);
if (absres > (f->avg * 3))
*f->adaptcoeffs = ((res >> 25) & 64) - 32;
else if (absres > (f->avg * 4) / 3)
*f->adaptcoeffs = ((res >> 26) & 32) - 16;
else if (absres > 0)
*f->adaptcoeffs = ((res >> 27) & 16) - 8;
else
*f->adaptcoeffs = 0;
f->avg += (absres - f->avg) / 16;
f->adaptcoeffs[-1] >>= 1;
f->adaptcoeffs[-2] >>= 1;
f->adaptcoeffs[-8] >>= 1;
f->adaptcoeffs++;
/* Have we filled the history buffer? */
if (f->delay == f->historybuffer + HISTORY_SIZE + (ORDER*2)) {
memmove(f->historybuffer, f->delay - (ORDER*2),
(ORDER*2) * sizeof(int16_t));
f->delay = f->historybuffer + ORDER*2;
f->adaptcoeffs = f->historybuffer + ORDER;
}
}
}
static inline void do_apply_filter_3970(struct filter_t* f, int32_t* data, int count)
{
int res;
while(count--)
{
res = FP_TO_INT(scalarproduct(f->delay - ORDER, f->coeffs));
if (*data < 0)
vector_add(f->coeffs, f->adaptcoeffs - ORDER);
else if (*data > 0)
vector_sub(f->coeffs, f->adaptcoeffs - ORDER);
/* Convert res from (32-FRACBITS).FRACBITS fixed-point format to an
integer (rounding to nearest) and add the input value to
it */
res += *data;
*data++ = res;
/* Update the output history */
*f->delay++ = SATURATE(res);
/* Version ??? to < 3.98 files (untested) */
f->adaptcoeffs[0] = (res == 0) ? 0 : ((res >> 28) & 8) - 4;
f->adaptcoeffs[-4] >>= 1;
f->adaptcoeffs[-8] >>= 1;
f->adaptcoeffs++;
/* Have we filled the history buffer? */
if (f->delay == f->historybuffer + HISTORY_SIZE + (ORDER*2)) {
memmove(f->historybuffer, f->delay - (ORDER*2),
(ORDER*2) * sizeof(int16_t));
f->delay = f->historybuffer + ORDER*2;
f->adaptcoeffs = f->historybuffer + ORDER;
}
}
}
static struct filter_t filter0 IBSS_ATTR;
static struct filter_t filter1 IBSS_ATTR;
static void do_init_filter(struct filter_t* f, int16_t* buf)
{
f->coeffs = buf;
f->historybuffer = buf + ORDER;
/* Zero the output history buffer */
memset(f->historybuffer, 0 , (ORDER*2) * sizeof(int16_t));
f->delay = f->historybuffer + ORDER*2;
f->adaptcoeffs = f->historybuffer + ORDER;
/* Zero the co-efficients */
memset(f->coeffs, 0, ORDER * sizeof(int16_t));
/* Zero the running average */
f->avg = 0;
}
void INIT_FILTER(int16_t* buf)
{
do_init_filter(&filter0, buf);
do_init_filter(&filter1, buf + ORDER * 3 + HISTORY_SIZE);
}
int APPLY_FILTER(int fileversion, int32_t* data0, int32_t* data1, int count)
{
if (fileversion >= 3980) {
do_apply_filter_3980(&filter0, data0, count);
if (data1 != NULL)
do_apply_filter_3980(&filter1, data1, count);
} else {
do_apply_filter_3970(&filter0, data0, count);
if (data1 != NULL)
do_apply_filter_3970(&filter1, data1, count);
}
return 0;
}

View file

@ -0,0 +1,48 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_FILTER_H
#define _APE_FILTER_H
#include <inttypes.h>
/* The size of the history buffers */
#define HISTORY_SIZE 512
void init_filter_16_11(int16_t* buf);
int apply_filter_16_11(int fileversion, int32_t* decoded0, int32_t* decoded1, int count);
void init_filter_64_11(int16_t* buf);
int apply_filter_64_11(int fileversion, int32_t* decoded0, int32_t* decoded1, int count);
void init_filter_32_10(int16_t* buf);
int apply_filter_32_10(int fileversion, int32_t* decoded0, int32_t* decoded1, int count);
void init_filter_256_13(int16_t* buf);
int apply_filter_256_13(int fileversion, int32_t* decoded0, int32_t* decoded1, int count);
void init_filter_1280_15(int16_t* buf);
int apply_filter_1280_15(int fileversion, int32_t* decoded0, int32_t* decoded1, int count);
#endif

View file

@ -0,0 +1,27 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#define ORDER 1280
#define FRACBITS 15
#include "filter.c"

View file

@ -0,0 +1,27 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#define ORDER 16
#define FRACBITS 11
#include "filter.c"

View file

@ -0,0 +1,27 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#define ORDER 256
#define FRACBITS 13
#include "filter.c"

View file

@ -0,0 +1,27 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#define ORDER 32
#define FRACBITS 10
#include "filter.c"

View file

@ -0,0 +1,27 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#define ORDER 64
#define FRACBITS 11
#include "filter.c"

View file

@ -0,0 +1,357 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <inttypes.h>
#include <string.h>
#ifndef ROCKBOX
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#endif
#include "parser.h"
static inline int16_t get_int16(unsigned char* buf)
{
return(buf[0] | (buf[1] << 8));
}
static inline uint16_t get_uint16(unsigned char* buf)
{
return(buf[0] | (buf[1] << 8));
}
static inline uint32_t get_uint32(unsigned char* buf)
{
return(buf[0] | (buf[1] << 8) | (buf[2] << 16) | (buf[3] << 24));
}
int ape_parseheaderbuf(unsigned char* buf, struct ape_ctx_t* ape_ctx)
{
unsigned char* header;
memset(ape_ctx,0,sizeof(struct ape_ctx_t));
/* TODO: Skip any leading junk such as id3v2 tags */
ape_ctx->junklength = 0;
memcpy(ape_ctx->magic, buf, 4);
if (memcmp(ape_ctx->magic,"MAC ",4)!=0)
{
return -1;
}
ape_ctx->fileversion = get_int16(buf + 4);
if (ape_ctx->fileversion >= 3980)
{
ape_ctx->padding1 = get_int16(buf + 6);
ape_ctx->descriptorlength = get_uint32(buf + 8);
ape_ctx->headerlength = get_uint32(buf + 12);
ape_ctx->seektablelength = get_uint32(buf + 16);
ape_ctx->wavheaderlength = get_uint32(buf + 20);
ape_ctx->audiodatalength = get_uint32(buf + 24);
ape_ctx->audiodatalength_high = get_uint32(buf + 28);
ape_ctx->wavtaillength = get_uint32(buf + 32);
memcpy(ape_ctx->md5, buf + 36, 16);
header = buf + ape_ctx->descriptorlength;
/* Read header data */
ape_ctx->compressiontype = get_uint16(header + 0);
ape_ctx->formatflags = get_uint16(header + 2);
ape_ctx->blocksperframe = get_uint32(header + 4);
ape_ctx->finalframeblocks = get_uint32(header + 8);
ape_ctx->totalframes = get_uint32(header + 12);
ape_ctx->bps = get_uint16(header + 16);
ape_ctx->channels = get_uint16(header + 18);
ape_ctx->samplerate = get_uint32(header + 20);
ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->descriptorlength +
ape_ctx->headerlength + ape_ctx->seektablelength +
ape_ctx->wavheaderlength;
} else {
ape_ctx->compressiontype = get_uint16(buf + 6);
ape_ctx->formatflags = get_uint16(buf + 8);
ape_ctx->channels = get_uint16(buf + 10);
ape_ctx->samplerate = get_uint32(buf + 14);
ape_ctx->wavheaderlength = get_uint32(buf + 18);
ape_ctx->totalframes = get_uint32(buf + 26);
ape_ctx->finalframeblocks = get_uint32(buf + 30);
}
ape_ctx->totalsamples = ape_ctx->finalframeblocks;
if (ape_ctx->totalframes > 1)
ape_ctx->totalsamples += ape_ctx->blocksperframe * (ape_ctx->totalframes-1);
/* TODO: Parse and store seektable */
return 0;
}
#ifndef ROCKBOX
/* Helper functions */
static int read_uint16(int fd, uint16_t* x)
{
unsigned char tmp[2];
int n;
n = read(fd,tmp,2);
if (n != 2)
return -1;
*x = tmp[0] | (tmp[1] << 8);
return 0;
}
static int read_int16(int fd, int16_t* x)
{
return read_uint16(fd, (uint16_t*)x);
}
static int read_uint32(int fd, uint32_t* x)
{
unsigned char tmp[4];
int n;
n = read(fd,tmp,4);
if (n != 4)
return -1;
*x = tmp[0] | (tmp[1] << 8) | (tmp[2] << 16) | (tmp[3] << 24);
return 0;
}
int ape_parseheader(int fd, struct ape_ctx_t* ape_ctx)
{
int i,n;
/* TODO: Skip any leading junk such as id3v2 tags */
ape_ctx->junklength = 0;
lseek(fd,ape_ctx->junklength,SEEK_SET);
n = read(fd,&ape_ctx->magic,4);
if (n != 4) return -1;
if (memcmp(ape_ctx->magic,"MAC ",4)!=0)
{
return -1;
}
if (read_int16(fd,&ape_ctx->fileversion) < 0)
return -1;
if (ape_ctx->fileversion >= 3980)
{
if (read_int16(fd,&ape_ctx->padding1) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->descriptorlength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->headerlength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->seektablelength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->wavheaderlength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->audiodatalength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->audiodatalength_high) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->wavtaillength) < 0)
return -1;
if (read(fd,&ape_ctx->md5,16) != 16)
return -1;
/* Skip any unknown bytes at the end of the descriptor. This is for future
compatibility */
if (ape_ctx->descriptorlength > 52)
lseek(fd,ape_ctx->descriptorlength - 52, SEEK_CUR);
/* Read header data */
if (read_uint16(fd,&ape_ctx->compressiontype) < 0)
return -1;
if (read_uint16(fd,&ape_ctx->formatflags) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->blocksperframe) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->finalframeblocks) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->totalframes) < 0)
return -1;
if (read_uint16(fd,&ape_ctx->bps) < 0)
return -1;
if (read_uint16(fd,&ape_ctx->channels) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->samplerate) < 0)
return -1;
} else {
ape_ctx->descriptorlength = 0;
ape_ctx->headerlength = 32;
if (read_uint16(fd,&ape_ctx->compressiontype) < 0)
return -1;
if (read_uint16(fd,&ape_ctx->formatflags) < 0)
return -1;
if (read_uint16(fd,&ape_ctx->channels) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->samplerate) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->wavheaderlength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->wavtaillength) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->totalframes) < 0)
return -1;
if (read_uint32(fd,&ape_ctx->finalframeblocks) < 0)
return -1;
if (ape_ctx->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL)
{
lseek(fd, 4, SEEK_CUR); /* Skip the peak level */
ape_ctx->headerlength += 4;
}
if (ape_ctx->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS)
{
if (read_uint32(fd,&ape_ctx->seektablelength) < 0)
return -1;
ape_ctx->headerlength += 4;
ape_ctx->seektablelength *= sizeof(int32_t);
} else {
ape_ctx->seektablelength = ape_ctx->totalframes * sizeof(int32_t);
}
if (ape_ctx->formatflags & MAC_FORMAT_FLAG_8_BIT)
ape_ctx->bps = 8;
else if (ape_ctx->formatflags & MAC_FORMAT_FLAG_24_BIT)
ape_ctx->bps = 24;
else
ape_ctx->bps = 16;
if (ape_ctx->fileversion >= 3950)
ape_ctx->blocksperframe = 73728 * 4;
else if ((ape_ctx->fileversion >= 3900) || (ape_ctx->fileversion >= 3800 && ape_ctx->compressiontype >= 4000))
ape_ctx->blocksperframe = 73728;
else
ape_ctx->blocksperframe = 9216;
/* Skip any stored wav header */
if (!(ape_ctx->formatflags & MAC_FORMAT_FLAG_CREATE_WAV_HEADER))
{
lseek(fd, ape_ctx->wavheaderlength, SEEK_CUR);
}
}
ape_ctx->totalsamples = ape_ctx->finalframeblocks;
if (ape_ctx->totalframes > 1)
ape_ctx->totalsamples += ape_ctx->blocksperframe * (ape_ctx->totalframes-1);
if (ape_ctx->seektablelength > 0)
{
ape_ctx->seektable = malloc(ape_ctx->seektablelength);
if (ape_ctx->seektable == NULL)
return -1;
for (i=0; i < ape_ctx->seektablelength / sizeof(uint32_t); i++)
{
if (read_uint32(fd,&ape_ctx->seektable[i]) < 0)
{
free(ape_ctx->seektable);
return -1;
}
}
}
ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->descriptorlength +
ape_ctx->headerlength + ape_ctx->seektablelength +
ape_ctx->wavheaderlength;
return 0;
}
void ape_dumpinfo(struct ape_ctx_t* ape_ctx)
{
int i;
printf("Descriptor Block:\n\n");
printf("magic = \"%c%c%c%c\"\n",
ape_ctx->magic[0],ape_ctx->magic[1],
ape_ctx->magic[2],ape_ctx->magic[3]);
printf("fileversion = %d\n",ape_ctx->fileversion);
printf("descriptorlength = %d\n",ape_ctx->descriptorlength);
printf("headerlength = %d\n",ape_ctx->headerlength);
printf("seektablelength = %d\n",ape_ctx->seektablelength);
printf("wavheaderlength = %d\n",ape_ctx->wavheaderlength);
printf("audiodatalength = %d\n",ape_ctx->audiodatalength);
printf("audiodatalength_high = %d\n",ape_ctx->audiodatalength_high);
printf("wavtaillength = %d\n",ape_ctx->wavtaillength);
printf("md5 = ");
for (i = 0; i < 16; i++)
printf("%02x",ape_ctx->md5[i]);
printf("\n");
printf("\nHeader Block:\n\n");
printf("compressiontype = %d\n",ape_ctx->compressiontype);
printf("formatflags = %d\n",ape_ctx->formatflags);
printf("blocksperframe = %d\n",ape_ctx->blocksperframe);
printf("finalframeblocks = %d\n",ape_ctx->finalframeblocks);
printf("totalframes = %d\n",ape_ctx->totalframes);
printf("bps = %d\n",ape_ctx->bps);
printf("channels = %d\n",ape_ctx->channels);
printf("samplerate = %d\n",ape_ctx->samplerate);
printf("\nSeektable\n\n");
if ((ape_ctx->seektablelength / sizeof(uint32_t)) != ape_ctx->totalframes)
{
printf("No seektable\n");
}
else
{
for ( i = 0; i < ape_ctx->seektablelength / sizeof(uint32_t) ; i++)
{
if (i < ape_ctx->totalframes-1) {
printf("%8d %d (%d bytes)\n",i,ape_ctx->seektable[i],ape_ctx->seektable[i+1]-ape_ctx->seektable[i]);
} else {
printf("%8d %d\n",i,ape_ctx->seektable[i]);
}
}
}
printf("\nCalculated information:\n\n");
printf("junklength = %d\n",ape_ctx->junklength);
printf("firstframe = %d\n",ape_ctx->firstframe);
printf("totalsamples = %d\n",ape_ctx->totalsamples);
}
#endif /* !ROCKBOX */

View file

@ -0,0 +1,137 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_PARSER_H
#define _APE_PARSER_H
#include <inttypes.h>
#ifdef ROCKBOX
/* Include the Rockbox Codec API when building for Rockbox */
#define APE_OUTPUT_DEPTH 29
#ifndef ROCKBOX_PLUGIN
#include "../lib/codeclib.h"
#include <codecs.h>
#endif
#else
#define APE_OUTPUT_DEPTH (ape_ctx->bps)
#define IBSS_ATTR
#define ICONST_ATTR
#define ICODE_ATTR
#endif
/* The earliest and latest file formats supported by this library */
#define APE_MIN_VERSION 3970
#define APE_MAX_VERSION 3990
#define MAC_FORMAT_FLAG_8_BIT 1 // is 8-bit [OBSOLETE]
#define MAC_FORMAT_FLAG_CRC 2 // uses the new CRC32 error detection [OBSOLETE]
#define MAC_FORMAT_FLAG_HAS_PEAK_LEVEL 4 // uint32 nPeakLevel after the header [OBSOLETE]
#define MAC_FORMAT_FLAG_24_BIT 8 // is 24-bit [OBSOLETE]
#define MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS 16 // has the number of seek elements after the peak level
#define MAC_FORMAT_FLAG_CREATE_WAV_HEADER 32 // create the wave header on decompression (not stored)
/* Special frame codes:
MONO_SILENCE - All PCM samples in frame are zero (mono streams only)
LEFT_SILENCE - All PCM samples for left channel in frame are zero (stereo streams)
RIGHT_SILENCE - All PCM samples for left channel in frame are zero (stereo streams)
PSEUDO_STEREO - Left and Right channels are identical
*/
#define APE_FRAMECODE_MONO_SILENCE 1
#define APE_FRAMECODE_STEREO_SILENCE 3
#define APE_FRAMECODE_PSEUDO_STEREO 4
#define HISTORY_SIZE 512
#define PREDICTOR_ORDER 8
struct predictor_t
{
/* Adaption co-efficients */
int32_t coeffsA[4];
int32_t coeffsB[5];
/* Filter histories */
int32_t historybuffer[HISTORY_SIZE + PREDICTOR_ORDER * 4];
int32_t* delayA;
int32_t* delayB;
int32_t* adaptcoeffsA;
int32_t* adaptcoeffsB;
int32_t lastA;
int32_t filterA;
int32_t filterB;
};
struct ape_ctx_t
{
/* Derived fields */
uint32_t junklength;
uint32_t firstframe;
uint32_t totalsamples;
/* Info from Descriptor Block */
char magic[4];
int16_t fileversion;
int16_t padding1;
uint32_t descriptorlength;
uint32_t headerlength;
uint32_t seektablelength;
uint32_t wavheaderlength;
uint32_t audiodatalength;
uint32_t audiodatalength_high;
uint32_t wavtaillength;
uint8_t md5[16];
/* Info from Header Block */
uint16_t compressiontype;
uint16_t formatflags;
uint32_t blocksperframe;
uint32_t finalframeblocks;
uint32_t totalframes;
uint16_t bps;
uint16_t channels;
uint32_t samplerate;
/* Seektable */
uint32_t* seektable;
/* Decoder state */
uint32_t CRC;
int frameflags;
int currentframeblocks;
int blocksdecoded;
struct predictor_t predictorY;
struct predictor_t predictorX;
};
int ape_parseheader(int fd, struct ape_ctx_t* ape_ctx);
int ape_parseheaderbuf(unsigned char* buf, struct ape_ctx_t* ape_ctx);
void ape_dumpinfo(struct ape_ctx_t* ape_ctx);
#endif

View file

@ -0,0 +1,196 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <inttypes.h>
#include <string.h>
#include "parser.h"
#include "predictor.h"
#include "vector_math32.h"
/* Return 0 if x is zero, -1 if x is positive, 1 if x is negative */
#define SIGN(x) (x) ? (((x) > 0) ? -1 : 1) : 0
static const int32_t initial_coeffs[4] = {
360, 317, -109, 98
};
static void init_predictor(struct predictor_t* p)
{
/* Zero the history buffers */
memset(p->historybuffer, 0, (PREDICTOR_ORDER*4) * sizeof(int32_t));
p->delayA = p->historybuffer + PREDICTOR_ORDER*4;
p->delayB = p->historybuffer + PREDICTOR_ORDER*3;
p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2;
p->adaptcoeffsB = p->historybuffer + PREDICTOR_ORDER;
/* Initialise and zero the co-efficients */
memcpy(p->coeffsA, initial_coeffs, sizeof(initial_coeffs));
memset(p->coeffsB, 0, sizeof(p->coeffsB));
p->filterA = 0;
p->filterB = 0;
p->lastA = 0;
}
static int do_predictor_decode(struct predictor_t* p, int32_t A, int32_t B)
{
int32_t predictionA, predictionB, currentA;
p->delayA[0] = p->lastA;
p->delayA[-1] = p->delayA[0] - p->delayA[-1];
predictionA = scalarproduct4_rev32(p->coeffsA,p->delayA);
/* Apply a scaled first-order filter compression */
p->delayB[0] = B - ((p->filterB * 31) >> 5);
p->filterB = B;
p->delayB[-1] = p->delayB[0] - p->delayB[-1];
predictionB = scalarproduct5_rev32(p->coeffsB,p->delayB);
currentA = A + ((predictionA + (predictionB >> 1)) >> 10);
p->adaptcoeffsA[0] = SIGN(p->delayA[0]);
p->adaptcoeffsA[-1] = SIGN(p->delayA[-1]);
p->adaptcoeffsB[0] = SIGN(p->delayB[0]);
p->adaptcoeffsB[-1] = SIGN(p->delayB[-1]);
if (A > 0)
{
vector_sub4_rev32(p->coeffsA, p->adaptcoeffsA);
vector_sub5_rev32(p->coeffsB, p->adaptcoeffsB);
}
else if (A < 0)
{
vector_add4_rev32(p->coeffsA, p->adaptcoeffsA);
vector_add5_rev32(p->coeffsB, p->adaptcoeffsB);
}
p->delayA++;
p->delayB++;
p->adaptcoeffsA++;
p->adaptcoeffsB++;
/* Have we filled the history buffer? */
if (p->delayA == p->historybuffer + HISTORY_SIZE + (PREDICTOR_ORDER*4)) {
memmove(p->historybuffer, p->delayA - (PREDICTOR_ORDER*4),
(PREDICTOR_ORDER*4) * sizeof(int32_t));
p->delayA = p->historybuffer + PREDICTOR_ORDER*4;
p->delayB = p->historybuffer + PREDICTOR_ORDER*3;
p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2;
p->adaptcoeffsB = p->historybuffer + PREDICTOR_ORDER;
}
p->lastA = currentA;
p->filterA = currentA + ((p->filterA * 31) >> 5);
return p->filterA;
}
static int32_t X;
void init_predictor_decoder(struct ape_ctx_t* ape_ctx)
{
X = 0;
init_predictor(&ape_ctx->predictorY);
init_predictor(&ape_ctx->predictorX);
}
int predictor_decode_stereo(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int32_t* decoded1, int count) ICODE_ATTR;
int predictor_decode_stereo(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int32_t* decoded1, int count)
{
while (count--)
{
*decoded0 = do_predictor_decode(&ape_ctx->predictorY, *decoded0, X);
X = do_predictor_decode(&ape_ctx->predictorX, *decoded1, *(decoded0)++);
*(decoded1++) = X;
}
return 0;
}
int predictor_decode_mono(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int count)
{
struct predictor_t* p = &ape_ctx->predictorY;
int32_t predictionA, currentA, A;
currentA = p->lastA;
while (count--)
{
A = *decoded0;
p->delayA[0] = currentA;
p->delayA[-1] = p->delayA[0] - p->delayA[-1];
predictionA = (p->delayA[0] * p->coeffsA[0]) +
(p->delayA[-1] * p->coeffsA[1]) +
(p->delayA[-2] * p->coeffsA[2]) +
(p->delayA[-3] * p->coeffsA[3]);
currentA = A + (predictionA >> 10);
p->adaptcoeffsA[0] = SIGN(p->delayA[0]);
p->adaptcoeffsA[-1] = SIGN(p->delayA[-1]);
if (A > 0)
{
p->coeffsA[0] -= p->adaptcoeffsA[0];
p->coeffsA[1] -= p->adaptcoeffsA[-1];
p->coeffsA[2] -= p->adaptcoeffsA[-2];
p->coeffsA[3] -= p->adaptcoeffsA[-3];
}
else if (A < 0)
{
p->coeffsA[0] += p->adaptcoeffsA[0];
p->coeffsA[1] += p->adaptcoeffsA[-1];
p->coeffsA[2] += p->adaptcoeffsA[-2];
p->coeffsA[3] += p->adaptcoeffsA[-3];
}
p->delayA++;
p->adaptcoeffsA++;
/* Have we filled the history buffer? */
if (p->delayA == p->historybuffer + HISTORY_SIZE + (PREDICTOR_ORDER*4)) {
memmove(p->historybuffer, p->delayA - (PREDICTOR_ORDER*4),
(PREDICTOR_ORDER*4) * sizeof(int32_t));
p->delayA = p->historybuffer + PREDICTOR_ORDER*4;
p->adaptcoeffsA = p->historybuffer + PREDICTOR_ORDER*2;
}
p->filterA = currentA + ((p->filterA * 31) >> 5);
*(decoded0++) = p->filterA;
}
p->lastA = currentA;
return 0;
}

View file

@ -0,0 +1,36 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_PREDICTOR_H
#define _APE_PREDICTOR_H
#include <inttypes.h>
#include "parser.h"
#include "filter.h"
void init_predictor_decoder(struct ape_ctx_t* ape_ctx);
int predictor_decode_stereo(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int32_t* decoded1, int count);
int predictor_decode_mono(struct ape_ctx_t* ape_ctx, int32_t* decoded0, int count);
#endif

View file

@ -0,0 +1,180 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
/*
Range decoder adapted from rangecod.c included in:
http://www.compressconsult.com/rangecoder/rngcod13.zip
rangecod.c range encoding
(c) Michael Schindler
1997, 1998, 1999, 2000
http://www.compressconsult.com/
michael@compressconsult.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.
The encoding functions were removed, and functions turned into "static
inline" functions and moved to a .h file. Some minor cosmetic changes
were made (e.g. turning pre-processor symbols into upper-case,
removing the rc parameter from each function (and the RNGC macro)).
*/
/* BITSTREAM READING FUNCTIONS */
/* We deal with the input data one byte at a time - to ensure
functionality on CPUs of any endianness regardless of any requirements
for aligned reads.
*/
static unsigned char* bytebuffer IBSS_ATTR;
static int bytebufferoffset IBSS_ATTR;
static inline void skip_byte(void)
{
if (bytebufferoffset) {
bytebufferoffset--;
} else {
bytebufferoffset = 3;
bytebuffer += 4;
}
}
static inline int read_byte(void)
{
int ch = bytebuffer[bytebufferoffset];
skip_byte();
return ch;
}
/* RANGE DECODING FUNCTIONS */
/* SIZE OF RANGE ENCODING CODE VALUES. */
#define CODE_BITS 32
#define TOP_VALUE ((unsigned int)1 << (CODE_BITS-1))
#define SHIFT_BITS (CODE_BITS - 9)
#define EXTRA_BITS ((CODE_BITS-2) % 8 + 1)
#define BOTTOM_VALUE (TOP_VALUE >> 8)
struct rangecoder_t
{
uint32_t low; /* low end of interval */
uint32_t range; /* length of interval */
uint32_t help; /* bytes_to_follow resp. intermediate value */
unsigned int buffer; /* buffer for input/output */
};
static struct rangecoder_t rc;
/* Start the decoder */
static inline void range_start_decoding(void)
{
rc.buffer = read_byte();
rc.low = rc.buffer >> (8 - EXTRA_BITS);
rc.range = (uint32_t) 1 << EXTRA_BITS;
}
static inline void range_dec_normalize(void)
{
while (rc.range <= BOTTOM_VALUE)
{
rc.buffer = (rc.buffer << 8) | read_byte();
rc.low = (rc.low << 8) | ((rc.buffer >> 1) & 0xff);
rc.range <<= 8;
}
}
/* Calculate culmulative frequency for next symbol. Does NO update!*/
/* tot_f is the total frequency */
/* or: totf is (code_value)1<<shift */
/* returns the culmulative frequency */
static inline int range_decode_culfreq(int tot_f)
{ int tmp;
range_dec_normalize();
rc.help = rc.range / tot_f;
tmp = rc.low / rc.help;
return tmp;
}
static inline int range_decode_culshift(int shift)
{
int tmp;
range_dec_normalize();
rc.help = rc.range>>shift;
tmp = rc.low/rc.help;
return tmp;
}
/* Update decoding state */
/* sy_f is the interval length (frequency of the symbol) */
/* lt_f is the lower end (frequency sum of < symbols) */
static inline void range_decode_update(int sy_f, int lt_f)
{ int tmp;
tmp = rc.help * lt_f;
rc.low -= tmp;
rc.range = rc.help * sy_f;
}
/* Decode a byte/short without modelling */
static inline unsigned char decode_byte(void)
{ int tmp = range_decode_culshift(8);
range_decode_update( 1,tmp);
return tmp;
}
static inline int short range_decode_short(void)
{ int tmp = range_decode_culshift(16);
range_decode_update( 1,tmp);
return tmp;
}
/* Decode n bits (n <= 16) without modelling - based on range_decode_short */
static inline int range_decode_bits(int n)
{ int tmp = range_decode_culshift(n);
range_decode_update( 1,tmp);
return tmp;
}
/* Finish decoding */
static inline void range_done_decoding(void)
{ range_dec_normalize(); /* normalize to use up all bytes */
}

View file

@ -0,0 +1,140 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
static inline void vector_add(int16_t* v1, int16_t* v2)
{
#if ORDER > 32
int order = (ORDER >> 5);
while (order--)
#endif
{
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
#if ORDER > 16
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
*v1++ += *v2++;
#endif
}
}
static inline void vector_sub(int16_t* v1, int16_t* v2)
{
#if ORDER > 32
int order = (ORDER >> 5);
while (order--)
#endif
{
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
#if ORDER > 16
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
*v1++ -= *v2++;
#endif
}
}
static inline int32_t scalarproduct(int16_t* v1, int16_t* v2)
{
int res = 0;
#if ORDER > 16
int order = (ORDER >> 4);
while (order--)
#endif
{
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
res += *v1++ * *v2++;
}
return res;
}

View file

@ -0,0 +1,54 @@
/*
libdemac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
/* 32-bit vector math functions */
#define scalarproduct4_rev32(x,y) ((x[0] * y[0]) + (x[1] * y[-1]) + \
(x[2] * y[-2]) + (x[3] * y[-3]))
#define scalarproduct5_rev32(x,y) ((x[0] * y[0]) + (x[1] * y[-1]) + \
(x[2] * y[-2]) + (x[3] * y[-3]) + \
(x[4] * y[-4]))
#define vector_sub4_rev32(x, y) { x[0] -= y[0]; \
x[1] -= y[-1]; \
x[2] -= y[-2]; \
x[3] -= y[-3]; }
#define vector_sub5_rev32(x, y) { x[0] -= y[0]; \
x[1] -= y[-1]; \
x[2] -= y[-2]; \
x[3] -= y[-3]; \
x[4] -= y[-4]; }
#define vector_add4_rev32(x, y) { x[0] += y[0]; \
x[1] += y[-1]; \
x[2] += y[-2]; \
x[3] += y[-3]; }
#define vector_add5_rev32(x, y) { x[0] += y[0]; \
x[1] += y[-1]; \
x[2] += y[-2]; \
x[3] += y[-3]; \
x[4] += y[-4]; }

View file

@ -0,0 +1,107 @@
/*
demac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#include <stdio.h>
#include <inttypes.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include "parser.h"
static unsigned char wav_header[44]={
'R','I','F','F',// 0 - ChunkID
0,0,0,0, // 4 - ChunkSize (filesize-8)
'W','A','V','E',// 8 - Format
'f','m','t',' ',// 12 - SubChunkID
16,0,0,0, // 16 - SubChunk1ID // 16 for PCM
1,0, // 20 - AudioFormat (1=Uncompressed)
2,0, // 22 - NumChannels
0,0,0,0, // 24 - SampleRate in Hz
0,0,0,0, // 28 - Byte Rate (SampleRate*NumChannels*(BitsPerSample/8)
4,0, // 32 - BlockAlign (== NumChannels * BitsPerSample/8)
16,0, // 34 - BitsPerSample
'd','a','t','a',// 36 - Subchunk2ID
0,0,0,0 // 40 - Subchunk2Size
};
int open_wav(struct ape_ctx_t* ape_ctx, char* filename)
{
int fd;
int x;
int filesize;
int bytespersample;
fd=creat(filename,0644);
if (fd < 0)
return fd;
bytespersample=ape_ctx->bps/8;
filesize=ape_ctx->totalsamples*bytespersample*ape_ctx->channels+44;
// ChunkSize
x=filesize-8;
wav_header[4]=(x&0xff);
wav_header[5]=(x&0xff00)>>8;
wav_header[6]=(x&0xff0000)>>16;
wav_header[7]=(x&0xff000000)>>24;
// Number of channels
wav_header[22]=ape_ctx->channels;
// Samplerate
wav_header[24]=ape_ctx->samplerate&0xff;
wav_header[25]=(ape_ctx->samplerate&0xff00)>>8;
wav_header[26]=(ape_ctx->samplerate&0xff0000)>>16;
wav_header[27]=(ape_ctx->samplerate&0xff000000)>>24;
// ByteRate
x=ape_ctx->samplerate*(ape_ctx->bps/8)*ape_ctx->channels;
wav_header[28]=(x&0xff);
wav_header[29]=(x&0xff00)>>8;
wav_header[30]=(x&0xff0000)>>16;
wav_header[31]=(x&0xff000000)>>24;
// BlockAlign
wav_header[32]=(ape_ctx->bps/8)*ape_ctx->channels;
// Bits per sample
wav_header[34]=ape_ctx->bps;
// Subchunk2Size
x=filesize-44;
wav_header[40]=(x&0xff);
wav_header[41]=(x&0xff00)>>8;
wav_header[42]=(x&0xff0000)>>16;
wav_header[43]=(x&0xff000000)>>24;
write(fd,wav_header,sizeof(wav_header));
return fd;
}

View file

@ -0,0 +1,32 @@
/*
demac - A Monkey's Audio decoder
$Id:$
Copyright (C) Dave Chapman 2007
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., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA
*/
#ifndef _APE_WAVWRITE_H
#define _APE_WAVWRITE_H
#include "parser.h"
int open_wav(struct ape_ctx_t* ape_ctx, char* filename);
#endif

View file

@ -76,6 +76,8 @@ const struct filetype inbuilt_filetypes[] = {
{ "nsf", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "nsfe",FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "spc", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "ape", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
{ "mac", FILE_ATTR_AUDIO, Icon_Audio, VOICE_EXT_MPA },
#endif
{ "m3u", FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },
{ "m3u8",FILE_ATTR_M3U, Icon_Playlist, LANG_PLAYLIST },

View file

@ -982,6 +982,56 @@ static bool get_flac_metadata(int fd, struct mp3entry* id3)
return true;
}
static bool get_monkeys_metadata(int fd, struct mp3entry* id3)
{
/* Use the trackname part of the id3 structure as a temporary buffer */
unsigned char* buf = (unsigned char *)id3->path;
unsigned char* header;
bool rc = false;
uint32_t descriptorlength;
uint32_t totalsamples;
uint32_t blocksperframe, finalframeblocks, totalframes;
lseek(fd, 0, SEEK_SET);
if (read(fd, buf, 4) < 4)
{
return rc;
}
if (memcmp(buf, "MAC ", 4) != 0)
{
return rc;
}
read(fd, buf + 4, MAX_PATH - 4);
descriptorlength = buf[8] | (buf[9] << 8) |
(buf[10] << 16) | (buf[11] << 24);
header = buf + descriptorlength;
blocksperframe = header[4] | (header[5] << 8) |
(header[6] << 16) | (header[7] << 24);
finalframeblocks = header[8] | (header[9] << 8) |
(header[10] << 16) | (header[11] << 24);
totalframes = header[12] | (header[13] << 8) |
(header[14] << 16) | (header[15] << 24);
id3->vbr = true; /* All FLAC files are VBR */
id3->filesize = filesize(fd);
id3->frequency = header[20] | (header[21] << 8) |
(header[22] << 16) | (header[23] << 24);
totalsamples = finalframeblocks;
if (totalframes > 1)
totalsamples += blocksperframe * (totalframes-1);
id3->length = ((int64_t) totalsamples * 1000) / id3->frequency;
id3->bitrate = (id3->filesize * 8) / id3->length;
return true;
}
static bool get_wave_metadata(int fd, struct mp3entry* id3)
{
/* Use the trackname part of the id3 structure as a temporary buffer */
@ -2152,6 +2202,14 @@ bool get_metadata(struct track_info* track, int fd, const char* trackname,
break;
case AFMT_APE:
if (!get_monkeys_metadata(fd, &(track->id3)))
{
return false;
}
read_ape_tags(fd, &(track->id3));
break;
case AFMT_MPC:
if (!get_musepack_metadata(fd, &(track->id3)))
return false;

View file

@ -53,6 +53,7 @@ enum
AFMT_NSF, /* NESM (NES Sound Format) */
AFMT_SPEEX, /* Ogg Speex speech */
AFMT_SPC, /* SPC700 save state */
AFMT_APE, /* Monkey's Audio (APE) */
#endif
/* add new formats at any index above this line to have a sensible order -

View file

@ -107,6 +107,9 @@ const struct afmt_entry audio_formats[AFMT_NUM_CODECS] =
/* SPC700 Save State */
[AFMT_SPC] =
AFMT_ENTRY("SPC", "spc", NULL, "spc\0" ),
/* APE (Monkey's Audio) */
[AFMT_APE] =
AFMT_ENTRY("APE", "ape", NULL, "ape\0mac\0" ),
#endif
};

38
tools/configure vendored
View file

@ -756,7 +756,7 @@ EOF
archosrom=""
flash="$pwd/rombox.iriver"
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset=$iriverbitmaptools
@ -781,7 +781,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset=$iriverbitmaptools
@ -806,7 +806,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset=$iriverbitmaptools
@ -831,7 +831,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset="$iaudiobitmaptools"
@ -857,7 +857,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset="$iaudiobitmaptools"
@ -881,7 +881,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -906,7 +906,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -930,7 +930,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -955,7 +955,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -980,7 +980,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -1005,7 +1005,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -1030,7 +1030,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
# toolset is the tools within the tools directory that we build for
# this particular target.
toolset=$genericbitmaptools
@ -1053,7 +1053,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
toolset=$gigabeatbitmaptools
boottool="$rootdir/tools/scramble -gigabeat"
bootoutput="FWIMG01.DAT"
@ -1077,7 +1077,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
bootoutput="bootloader-$archos.ipod"
# toolset is the tools within the tools directory that we build for
# this particular target.
@ -1102,7 +1102,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
boottool="$rootdir/tools/scramble -mi4v3 -model=h10 -type=RBBL"
bootoutput="H10_20GC.mi4"
# toolset is the tools within the tools directory that we build for
@ -1128,7 +1128,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
boottool="$rootdir/tools/scramble -mi4v2 -model=h105 -type=RBBL"
bootoutput="H10.mi4"
# toolset is the tools within the tools directory that we build for
@ -1154,7 +1154,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
boottool="$rootdir/tools/scramble -mi4v3 -model=e200 -type=RBBL"
bootoutput="PP5022.mi4"
# toolset is the tools within the tools directory that we build for
@ -1183,7 +1183,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
boottool="$rootdir/tools/scramble -mi4r -model=e20r -type=RBBL"
bootoutput="pp5022.mi4"
# toolset is the tools within the tools directory that we build for
@ -1209,7 +1209,7 @@ EOF
archosrom=""
flash=""
plugins="yes"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex"
codecs="libmad liba52 libffmpegFLAC libTremor libwavpack libmusepack libalac libfaad libm4a libspeex libdemac"
boottool="$rootdir/tools/scramble -mi4v2"
bootoutput="pp5020.mi4"
# toolset is the tools within the tools directory that we build for