summaryrefslogtreecommitdiff
path: root/apps/codecs
diff options
context:
space:
mode:
authorDave Chapman <dave@dchapman.com>2005-09-22 20:46:58 +0000
committerDave Chapman <dave@dchapman.com>2005-09-22 20:46:58 +0000
commitdebbe9747eb6eecfd79aab648212b55220922eb6 (patch)
treedfd131c1505b32e5b8201bce212ea49fc3b3574d /apps/codecs
parent567718d8372564028ca85c8f5892c86659f14d4c (diff)
First Rockbox version of ALAC decoder - porting to work in Rockbox environment and some simple (but significant) optimisations
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@7544 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs')
-rw-r--r--apps/codecs/libalac/Makefile47
-rw-r--r--apps/codecs/libalac/README.rockbox80
-rw-r--r--apps/codecs/libalac/SOURCES2
-rw-r--r--apps/codecs/libalac/alac.c345
-rw-r--r--apps/codecs/libalac/decomp.h30
-rw-r--r--apps/codecs/libalac/demux.c85
-rw-r--r--apps/codecs/libalac/demux.h2
-rw-r--r--apps/codecs/libalac/stream.h11
8 files changed, 405 insertions, 197 deletions
diff --git a/apps/codecs/libalac/Makefile b/apps/codecs/libalac/Makefile
new file mode 100644
index 0000000000..b815db54b7
--- /dev/null
+++ b/apps/codecs/libalac/Makefile
@@ -0,0 +1,47 @@
+# __________ __ ___.
+# 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 += -I$(APPSDIR)/$(APPEXTRA)
+endif
+
+ALACOPTS = -O3
+CFLAGS = $(GCCOPTS) $(ALACOPTS) $(INCLUDES) $(TARGET) $(EXTRA_DEFINES) -DMEM=${MEMORYSIZE}
+
+# 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-libalac
+DIRS =
+
+OUTPUT = $(BUILDDIR)/libalac.a
+
+all: $(OUTPUT)
+
+$(OUTPUT): $(OBJS)
+ @echo "AR $@"
+ @$(AR) ruv $@ $+ >/dev/null 2>&1
+
+$(OBJDIR)/libalac/%.o: $(APPSDIR)/codecs/libalac/%.c
+ @echo "(libalac) CC $<"
+ @$(CC) -c $(CFLAGS) -I$(APPSDIR)/codecs/libalac/ $< -o $@
+
+include $(TOOLSDIR)/make.inc
+
+clean:
+ @echo "cleaning libalac"
+ @rm -f $(OBJS) $(OUTPUT) $(DEPFILE)
+
+-include $(DEPFILE)
diff --git a/apps/codecs/libalac/README.rockbox b/apps/codecs/libalac/README.rockbox
new file mode 100644
index 0000000000..891e581cfc
--- /dev/null
+++ b/apps/codecs/libalac/README.rockbox
@@ -0,0 +1,80 @@
+Library: Reverse-engineered ALAC decoder v0.1.0
+Imported: 2005-08-14 by Dave Chapman
+
+
+This directory contains a local version of an ALAC (Apple Lossless Audio
+Codec) for use by Rockbox for software decoding of ALAC files. It is
+based on the reverse-engineered decoder by David Hamilton.
+
+LICENSING INFORMATION
+
+/*
+ * ALAC (Apple Lossless Audio Codec) decoder
+ * Copyright (c) 2005 David Hammerton
+ * All rights reserved.
+ *
+ * This is the actual decoder.
+ *
+ * http://crazney.net/programs/itunes/alac.html
+ *
+ * Permission is hereby granted, free of charge, to any person
+ * obtaining a copy of this software and associated documentation
+ * files (the "Software"), to deal in the Software without
+ * restriction, including without limitation the rights to use,
+ * copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be
+ * included in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ */
+
+IMPORT DETAILS
+
+The base version first imported into Rockbox was the first release
+(v0.1.0) of the ALAC decoder by David Hammerton.
+
+Only the files alac.[ch], demux.[ch] and stream.h were used.
+
+stream.c (the original FILE* based I/O implementation) was replaced with
+functions in the ALAC codec - to interface with the Rockbox audio playback
+system.
+
+References to <stdint.h> were replaced with <inttypes.h> and debugging
+calls to fprintf were removed.
+
+The ALAC decoder itself was modified to return samples in host-endian
+order, instead of little-endian.
+
+The run-time detection of CPU endianness was replaced with
+compile-time tests of the ROCKBOX_LITTLE_ENDIAN define.
+
+All malloc calls were removed from alac.c, but some are still present
+in the metadata parser in demux.c - to store unbounded data such as
+the size in bytes of each compressed block in the file.
+
+The only changes to demux.c were to remove debugging calls to fprintf.
+
+The most-used buffers (the temporary 32-bit output buffer) were moved
+into IRAM (on the iRiver). This was enough to make the decoder work
+in real-time.
+
+A point of interest - the -O3 gcc option (the setting used in the
+original Makefile provided with the alac decoder) gives a significant
+speedup compared to -O2. With -O2, the Coldfire runs at a constant
+120MHz, but with -O3, it can power-down to 40MHz for a small amount of
+time.
+
+The file alac.c contained some hints from the original author for
+places where major optimisations can be made - specifically the
+unrolling and optimisation of certain cases of general loops.
diff --git a/apps/codecs/libalac/SOURCES b/apps/codecs/libalac/SOURCES
new file mode 100644
index 0000000000..0c4615619f
--- /dev/null
+++ b/apps/codecs/libalac/SOURCES
@@ -0,0 +1,2 @@
+alac.c
+demux.c
diff --git a/apps/codecs/libalac/alac.c b/apps/codecs/libalac/alac.c
index 575bbf5abc..ae1b413eab 100644
--- a/apps/codecs/libalac/alac.c
+++ b/apps/codecs/libalac/alac.c
@@ -33,8 +33,9 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <stdint.h>
+#include <inttypes.h>
+#include "../codec.h"
#include "decomp.h"
#define _Swap32(v) do { \
@@ -47,53 +48,13 @@
v = (((v) & 0x00FF) << 0x08) | \
(((v) & 0xFF00) >> 0x08); } while (0)
-
-extern int host_bigendian;
-
-struct alac_file
-{
- unsigned char *input_buffer;
- int input_buffer_bitaccumulator; /* used so we can do arbitary
- bit reads */
-
- int samplesize;
- int numchannels;
- int bytespersample;
-
-
- /* buffers */
- int32_t *predicterror_buffer_a;
- int32_t *predicterror_buffer_b;
-
- int32_t *outputsamples_buffer_a;
- int32_t *outputsamples_buffer_b;
-
-
- /* stuff from setinfo */
- uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */
- uint8_t setinfo_7a; /* 0x00 */
- uint8_t setinfo_sample_size; /* 0x10 */
- uint8_t setinfo_rice_historymult; /* 0x28 */
- uint8_t setinfo_rice_initialhistory; /* 0x0a */
- uint8_t setinfo_rice_kmodifier; /* 0x0e */
- uint8_t setinfo_7f; /* 0x02 */
- uint16_t setinfo_80; /* 0x00ff */
- uint32_t setinfo_82; /* 0x000020e7 */
- uint32_t setinfo_86; /* 0x00069fe4 */
- uint32_t setinfo_8a_rate; /* 0x0000ac44 */
- /* end setinfo stuff */
-
-};
-
-
-static void allocate_buffers(alac_file *alac)
-{
- alac->predicterror_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
- alac->predicterror_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
-
- alac->outputsamples_buffer_a = malloc(alac->setinfo_max_samples_per_frame * 4);
- alac->outputsamples_buffer_b = malloc(alac->setinfo_max_samples_per_frame * 4);
-}
+int16_t predictor_coef_table[32] IDATA_ATTR;
+int16_t predictor_coef_table_a[32] IDATA_ATTR;
+int16_t predictor_coef_table_b[32] IDATA_ATTR;
+int32_t predicterror_buffer_a[4096];
+int32_t predicterror_buffer_b[4096];
+int32_t outputsamples_buffer_a[4096] IDATA_ATTR;
+int32_t outputsamples_buffer_b[4096] IDATA_ATTR;
void alac_set_info(alac_file *alac, char *inputbuffer)
{
@@ -107,8 +68,9 @@ void alac_set_info(alac_file *alac, char *inputbuffer)
ptr += 4; /* 0 ? */
alac->setinfo_max_samples_per_frame = *(uint32_t*)ptr; /* buffer size / 2 ? */
- if (!host_bigendian)
- _Swap32(alac->setinfo_max_samples_per_frame);
+#ifdef ROCKBOX_LITTLE_ENDIAN
+ _Swap32(alac->setinfo_max_samples_per_frame);
+#endif
ptr += 4;
alac->setinfo_7a = *(uint8_t*)ptr;
ptr += 1;
@@ -123,24 +85,25 @@ void alac_set_info(alac_file *alac, char *inputbuffer)
alac->setinfo_7f = *(uint8_t*)ptr;
ptr += 1;
alac->setinfo_80 = *(uint16_t*)ptr;
- if (!host_bigendian)
- _Swap16(alac->setinfo_80);
+#ifdef ROCKBOX_LITTLE_ENDIAN
+ _Swap16(alac->setinfo_80);
+#endif
ptr += 2;
alac->setinfo_82 = *(uint32_t*)ptr;
- if (!host_bigendian)
- _Swap32(alac->setinfo_82);
+#ifdef ROCKBOX_LITTLE_ENDIAN
+ _Swap32(alac->setinfo_82);
+#endif
ptr += 4;
alac->setinfo_86 = *(uint32_t*)ptr;
- if (!host_bigendian)
- _Swap32(alac->setinfo_86);
+#ifdef ROCKBOX_LITTLE_ENDIAN
+ _Swap32(alac->setinfo_86);
+#endif
ptr += 4;
alac->setinfo_8a_rate = *(uint32_t*)ptr;
- if (!host_bigendian)
- _Swap32(alac->setinfo_8a_rate);
+#ifdef ROCKBOX_LITTLE_ENDIAN
+ _Swap32(alac->setinfo_8a_rate);
+#endif
ptr += 4;
-
- allocate_buffers(alac);
-
}
/* stream reading */
@@ -432,23 +395,150 @@ static void predictor_decompress_fir_adapt(int32_t *error_buffer,
}
}
-#if 0
- /* 4 and 8 are very common cases (the only ones i've seen). these
- * should be unrolled and optimised
+ /* 4 and 8 are very common cases (the only ones i've seen).
+
+ The following code is an initial attempt to unroll and optimise
+ these two cases by the Rockbox project. More work is needed.
*/
+
+ /* optimised case: 4 */
if (predictor_coef_num == 4)
{
- /* FIXME: optimised general case */
+ for (i = 4 + 1; i < output_size; i++)
+ {
+ int sum = 0;
+ int outval;
+ int error_val = error_buffer[i];
+
+ sum = (buffer_out[4] - buffer_out[0]) * predictor_coef_table[0]
+ + (buffer_out[3] - buffer_out[0]) * predictor_coef_table[1]
+ + (buffer_out[2] - buffer_out[0]) * predictor_coef_table[2]
+ + (buffer_out[1] - buffer_out[0]) * predictor_coef_table[3];
+
+ outval = (1 << (predictor_quantitization-1)) + sum;
+ outval = outval >> predictor_quantitization;
+ outval = outval + buffer_out[0] + error_val;
+ outval = SIGN_EXTENDED32(outval, readsamplesize);
+
+ buffer_out[4+1] = outval;
+
+ if (error_val > 0)
+ {
+ int predictor_num = 4 - 1;
+
+ while (predictor_num >= 0 && error_val > 0)
+ {
+ int val = buffer_out[0] - buffer_out[4 - predictor_num];
+
+ if (val!=0) {
+ if (val < 0) {
+ predictor_coef_table[predictor_num]++;
+ val=-val;
+ } else {
+ predictor_coef_table[predictor_num]--;;
+ }
+ error_val -= ((val >> predictor_quantitization) * (4 - predictor_num));
+ }
+ predictor_num--;
+ }
+ }
+ else if (error_val < 0)
+ {
+ int predictor_num = 4 - 1;
+
+ while (predictor_num >= 0 && error_val < 0)
+ {
+ int val = buffer_out[0] - buffer_out[4 - predictor_num];
+
+ if (val != 0) {
+ if (val > 0) {
+ predictor_coef_table[predictor_num]++;
+ val=-val; /* neg value */
+ } else {
+ predictor_coef_table[predictor_num]--;
+ }
+ error_val -= ((val >> predictor_quantitization) * (4 - predictor_num));
+ }
+ predictor_num--;
+ }
+ }
+
+ buffer_out++;
+ }
return;
}
- if (predictor_coef_table == 8)
+ /* optimised case: 8 */
+ if (predictor_coef_num == 8)
{
- /* FIXME: optimised general case */
- return;
- }
-#endif
+ for (i = 8 + 1;
+ i < output_size;
+ i++)
+ {
+ int sum;
+ int outval;
+ int error_val = error_buffer[i];
+
+ sum = (buffer_out[8] - buffer_out[0]) * predictor_coef_table[0]
+ + (buffer_out[7] - buffer_out[0]) * predictor_coef_table[1]
+ + (buffer_out[6] - buffer_out[0]) * predictor_coef_table[2]
+ + (buffer_out[5] - buffer_out[0]) * predictor_coef_table[3]
+ + (buffer_out[4] - buffer_out[0]) * predictor_coef_table[4]
+ + (buffer_out[3] - buffer_out[0]) * predictor_coef_table[5]
+ + (buffer_out[2] - buffer_out[0]) * predictor_coef_table[6]
+ + (buffer_out[1] - buffer_out[0]) * predictor_coef_table[7];
+
+ outval = (1 << (predictor_quantitization-1)) + sum;
+ outval = outval >> predictor_quantitization;
+ outval = outval + buffer_out[0] + error_val;
+ outval = SIGN_EXTENDED32(outval, readsamplesize);
+
+ buffer_out[8+1] = outval;
+
+ if (error_val > 0)
+ {
+ int predictor_num = 8 - 1;
+
+ while (predictor_num >= 0 && error_val > 0)
+ {
+ int val = buffer_out[0] - buffer_out[8 - predictor_num];
+
+ if (val!=0) {
+ if (val < 0) {
+ predictor_coef_table[predictor_num]++;
+ val=-val;
+ } else {
+ predictor_coef_table[predictor_num]--;;
+ }
+ error_val -= ((val >> predictor_quantitization) * (8 - predictor_num));
+ }
+ predictor_num--;
+ }
+ }
+ else if (error_val < 0)
+ {
+ int predictor_num = 8 - 1;
+ while (predictor_num >= 0 && error_val < 0)
+ {
+ int val = buffer_out[0] - buffer_out[8 - predictor_num];
+ if (val != 0) {
+ if (val > 0) {
+ predictor_coef_table[predictor_num]++;
+ val=-val; /* neg value */
+ } else {
+ predictor_coef_table[predictor_num]--;
+ }
+ error_val -= ((val >> predictor_quantitization) * (8 - predictor_num));
+ }
+ predictor_num--;
+ }
+ }
+
+ buffer_out++;
+ }
+ return;
+ }
/* general case */
if (predictor_coef_num > 0)
@@ -534,26 +624,12 @@ void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
for (i = 0; i < numsamples; i++)
{
int32_t difference, midright;
- int16_t left;
- int16_t right;
midright = buffer_a[i];
difference = buffer_b[i];
-
- right = midright - ((difference * interlacing_leftweight) >> interlacing_shift);
- left = (midright - ((difference * interlacing_leftweight) >> interlacing_shift))
- + difference;
-
- /* output is always little endian */
- if (host_bigendian)
- {
- _Swap16(left);
- _Swap16(right);
- }
-
- buffer_out[i*numchannels] = left;
- buffer_out[i*numchannels + 1] = right;
+ buffer_out[i*numchannels] = (midright - ((difference * interlacing_leftweight) >> interlacing_shift)) + difference;
+ buffer_out[i*numchannels + 1] = midright - ((difference * interlacing_leftweight) >> interlacing_shift);
}
return;
@@ -562,34 +638,27 @@ void deinterlace_16(int32_t *buffer_a, int32_t *buffer_b,
/* otherwise basic interlacing took place */
for (i = 0; i < numsamples; i++)
{
- int16_t left, right;
-
- left = buffer_a[i];
- right = buffer_b[i];
-
- /* output is always little endian */
- if (host_bigendian)
- {
- _Swap16(left);
- _Swap16(right);
- }
-
- buffer_out[i*numchannels] = left;
- buffer_out[i*numchannels + 1] = right;
+ buffer_out[i*numchannels] = buffer_a[i];
+ buffer_out[i*numchannels + 1] = buffer_b[i];
}
}
-void decode_frame(alac_file *alac,
+int16_t* decode_frame(alac_file *alac,
unsigned char *inbuffer,
- void *outbuffer, int *outputsize)
+ int *outputsize)
{
int channels;
+ int16_t* outbuffer;
int32_t outputsamples = alac->setinfo_max_samples_per_frame;
/* setup the stream */
alac->input_buffer = inbuffer;
alac->input_buffer_bitaccumulator = 0;
+ /* We can share the same buffer for outputbuffer
+ and outputsamples_buffer_b - and hence have them both in IRAM*/
+ outbuffer=(int16_t*)outputsamples_buffer_b;
+
channels = readbits(alac, 3);
*outputsize = outputsamples * alac->bytespersample;
@@ -631,7 +700,6 @@ void decode_frame(alac_file *alac,
if (!isnotcompressed)
{ /* so it is compressed */
- int16_t predictor_coef_table[32];
int predictor_coef_num;
int prediction_type;
int prediction_quantitization;
@@ -659,11 +727,11 @@ void decode_frame(alac_file *alac,
/* these bytes seem to have something to do with
* > 2 channel files.
*/
- fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
+ //fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
}
basterdised_rice_decompress(alac,
- alac->predicterror_buffer_a,
+ predicterror_buffer_a,
outputsamples,
readsamplesize,
alac->setinfo_rice_initialhistory,
@@ -673,8 +741,8 @@ void decode_frame(alac_file *alac,
if (prediction_type == 0)
{ /* adaptive fir */
- predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
- alac->outputsamples_buffer_a,
+ predictor_decompress_fir_adapt(predicterror_buffer_a,
+ outputsamples_buffer_a,
outputsamples,
readsamplesize,
predictor_coef_table,
@@ -683,7 +751,7 @@ void decode_frame(alac_file *alac,
}
else
{
- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type);
+ //fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type);
/* i think the only other prediction type (or perhaps this is just a
* boolean?) runs adaptive fir twice.. like:
* predictor_decompress_fir_adapt(predictor_error, tempout, ...)
@@ -704,7 +772,7 @@ void decode_frame(alac_file *alac,
audiobits = SIGN_EXTENDED32(audiobits, readsamplesize);
- alac->outputsamples_buffer_a[i] = audiobits;
+ outputsamples_buffer_a[i] = audiobits;
}
}
else
@@ -722,7 +790,7 @@ void decode_frame(alac_file *alac,
audiobits |= readbits(alac, readsamplesize - 16);
- alac->outputsamples_buffer_a[i] = audiobits;
+ outputsamples_buffer_a[i] = audiobits;
}
}
/* wasted_bytes = 0; // unused */
@@ -735,17 +803,16 @@ void decode_frame(alac_file *alac,
int i;
for (i = 0; i < outputsamples; i++)
{
- int16_t sample = alac->outputsamples_buffer_a[i];
- if (host_bigendian)
- _Swap16(sample);
- ((int16_t*)outbuffer)[i * alac->numchannels] = sample;
+ /* Output mono data as stereo */
+ outbuffer[i*2] = outputsamples_buffer_a[i];
+ outbuffer[i*2+1] = outputsamples_buffer_a[i];
}
break;
}
case 20:
case 24:
case 32:
- fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
+ //fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
break;
default:
break;
@@ -788,13 +855,11 @@ void decode_frame(alac_file *alac,
if (!isnotcompressed)
{ /* compressed */
- int16_t predictor_coef_table_a[32];
int predictor_coef_num_a;
int prediction_type_a;
int prediction_quantitization_a;
int ricemodifier_a;
- int16_t predictor_coef_table_b[32];
int predictor_coef_num_b;
int prediction_type_b;
int prediction_quantitization_b;
@@ -834,12 +899,12 @@ void decode_frame(alac_file *alac,
/*********************/
if (wasted_bytes)
{ /* see mono case */
- fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
+ //fprintf(stderr, "FIXME: unimplemented, unhandling of wasted_bytes\n");
}
/* channel 1 */
basterdised_rice_decompress(alac,
- alac->predicterror_buffer_a,
+ predicterror_buffer_a,
outputsamples,
readsamplesize,
alac->setinfo_rice_initialhistory,
@@ -849,8 +914,8 @@ void decode_frame(alac_file *alac,
if (prediction_type_a == 0)
{ /* adaptive fir */
- predictor_decompress_fir_adapt(alac->predicterror_buffer_a,
- alac->outputsamples_buffer_a,
+ predictor_decompress_fir_adapt(predicterror_buffer_a,
+ outputsamples_buffer_a,
outputsamples,
readsamplesize,
predictor_coef_table_a,
@@ -859,12 +924,12 @@ void decode_frame(alac_file *alac,
}
else
{ /* see mono case */
- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a);
+ //fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_a);
}
/* channel 2 */
basterdised_rice_decompress(alac,
- alac->predicterror_buffer_b,
+ predicterror_buffer_b,
outputsamples,
readsamplesize,
alac->setinfo_rice_initialhistory,
@@ -874,8 +939,8 @@ void decode_frame(alac_file *alac,
if (prediction_type_b == 0)
{ /* adaptive fir */
- predictor_decompress_fir_adapt(alac->predicterror_buffer_b,
- alac->outputsamples_buffer_b,
+ predictor_decompress_fir_adapt(predicterror_buffer_b,
+ outputsamples_buffer_b,
outputsamples,
readsamplesize,
predictor_coef_table_b,
@@ -884,7 +949,7 @@ void decode_frame(alac_file *alac,
}
else
{
- fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b);
+ //fprintf(stderr, "FIXME: unhandled predicition type: %i\n", prediction_type_b);
}
}
else
@@ -902,8 +967,8 @@ void decode_frame(alac_file *alac,
audiobits_a = SIGN_EXTENDED32(audiobits_a, alac->setinfo_sample_size);
audiobits_b = SIGN_EXTENDED32(audiobits_b, alac->setinfo_sample_size);
- alac->outputsamples_buffer_a[i] = audiobits_a;
- alac->outputsamples_buffer_b[i] = audiobits_b;
+ outputsamples_buffer_a[i] = audiobits_a;
+ outputsamples_buffer_b[i] = audiobits_b;
}
}
else
@@ -923,8 +988,8 @@ void decode_frame(alac_file *alac,
audiobits_b = audiobits_b >> (32 - alac->setinfo_sample_size);
audiobits_b |= readbits(alac, alac->setinfo_sample_size - 16);
- alac->outputsamples_buffer_a[i] = audiobits_a;
- alac->outputsamples_buffer_b[i] = audiobits_b;
+ outputsamples_buffer_a[i] = audiobits_a;
+ outputsamples_buffer_b[i] = audiobits_b;
}
}
/* wasted_bytes = 0; */
@@ -936,8 +1001,8 @@ void decode_frame(alac_file *alac,
{
case 16:
{
- deinterlace_16(alac->outputsamples_buffer_a,
- alac->outputsamples_buffer_b,
+ deinterlace_16(outputsamples_buffer_a,
+ outputsamples_buffer_b,
(int16_t*)outbuffer,
alac->numchannels,
outputsamples,
@@ -948,7 +1013,7 @@ void decode_frame(alac_file *alac,
case 20:
case 24:
case 32:
- fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
+ //fprintf(stderr, "FIXME: unimplemented sample size %i\n", alac->setinfo_sample_size);
break;
default:
break;
@@ -957,16 +1022,12 @@ void decode_frame(alac_file *alac,
break;
}
}
+ return outbuffer;
}
-alac_file *create_alac(int samplesize, int numchannels)
+void create_alac(int samplesize, int numchannels, alac_file* alac)
{
- alac_file *newfile = malloc(sizeof(alac_file));
-
- newfile->samplesize = samplesize;
- newfile->numchannels = numchannels;
- newfile->bytespersample = (samplesize / 8) * numchannels;
-
- return newfile;
+ alac->samplesize = samplesize;
+ alac->numchannels = numchannels;
+ alac->bytespersample = (samplesize / 8) * numchannels;
}
-
diff --git a/apps/codecs/libalac/decomp.h b/apps/codecs/libalac/decomp.h
index 23dbc52779..e6fa82d3d7 100644
--- a/apps/codecs/libalac/decomp.h
+++ b/apps/codecs/libalac/decomp.h
@@ -1,12 +1,34 @@
#ifndef __ALAC__DECOMP_H
#define __ALAC__DECOMP_H
-typedef struct alac_file alac_file;
+typedef struct
+{
+ unsigned char *input_buffer;
+ int input_buffer_bitaccumulator; /* used so we can do arbitary
+ bit reads */
+ int samplesize;
+ int numchannels;
+ int bytespersample;
-alac_file *create_alac(int samplesize, int numchannels);
-void decode_frame(alac_file *alac,
+ /* stuff from setinfo */
+ uint32_t setinfo_max_samples_per_frame; /* 0x1000 = 4096 */ /* max samples per frame? */
+ uint8_t setinfo_7a; /* 0x00 */
+ uint8_t setinfo_sample_size; /* 0x10 */
+ uint8_t setinfo_rice_historymult; /* 0x28 */
+ uint8_t setinfo_rice_initialhistory; /* 0x0a */
+ uint8_t setinfo_rice_kmodifier; /* 0x0e */
+ uint8_t setinfo_7f; /* 0x02 */
+ uint16_t setinfo_80; /* 0x00ff */
+ uint32_t setinfo_82; /* 0x000020e7 */
+ uint32_t setinfo_86; /* 0x00069fe4 */
+ uint32_t setinfo_8a_rate; /* 0x0000ac44 */
+ /* end setinfo stuff */
+} alac_file;
+
+void create_alac(int samplesize, int numchannels, alac_file* alac);
+int16_t* decode_frame(alac_file *alac,
unsigned char *inbuffer,
- void *outbuffer, int *outputsize);
+ int *outputsize);
void alac_set_info(alac_file *alac, char *inputbuffer);
#endif /* __ALAC__DECOMP_H */
diff --git a/apps/codecs/libalac/demux.c b/apps/codecs/libalac/demux.c
index 7263a763d4..634dc01ee7 100644
--- a/apps/codecs/libalac/demux.c
+++ b/apps/codecs/libalac/demux.c
@@ -32,9 +32,11 @@
#include <string.h>
#include <stdio.h>
-#include <stdint.h>
+#include <inttypes.h>
#include <stdlib.h>
+#include "../codec.h"
+
#include "stream.h"
#include "demux.h"
@@ -56,7 +58,7 @@ static void read_chunk_ftyp(qtmovie_t *qtmovie, size_t chunk_len)
size_remaining-=4;
if (type != MAKEFOURCC('M','4','A',' '))
{
- fprintf(stderr, "not M4A file\n");
+ //fprintf(stderr, "not M4A file\n");
return;
}
minor_ver = stream_read_uint32(qtmovie->stream);
@@ -151,7 +153,7 @@ static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
if (numentries != 1)
{
- fprintf(stderr, "only expecting one entry in sample description atom!\n");
+ //fprintf(stderr, "only expecting one entry in sample description atom!\n");
return;
}
@@ -173,8 +175,8 @@ static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
entry_remaining -= 6;
version = stream_read_uint16(qtmovie->stream);
- if (version != 1)
- fprintf(stderr, "unknown version??\n");
+ // if (version != 1)
+ //fprintf(stderr, "unknown version??\n");
entry_remaining -= 2;
/* revision level */
@@ -245,8 +247,8 @@ static void read_chunk_stsd(qtmovie_t *qtmovie, size_t chunk_len)
if (qtmovie->res->format != MAKEFOURCC('a','l','a','c'))
{
- fprintf(stderr, "expecting 'alac' data format, got %c%c%c%c\n",
- SPLITFOURCC(qtmovie->res->format));
+// fprintf(stderr, "expecting 'alac' data format, got %c%c%c%c\n",
+// SPLITFOURCC(qtmovie->res->format));
return;
}
}
@@ -282,7 +284,7 @@ static void read_chunk_stts(qtmovie_t *qtmovie, size_t chunk_len)
if (size_remaining)
{
- fprintf(stderr, "ehm, size remianing?\n");
+ //fprintf(stderr, "ehm, size remianing?\n");
stream_skip(qtmovie->stream, size_remaining);
}
}
@@ -305,7 +307,7 @@ static void read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
/* default sample size */
if (stream_read_uint32(qtmovie->stream) != 0)
{
- fprintf(stderr, "i was expecting variable samples sizes\n");
+ //fprintf(stderr, "i was expecting variable samples sizes\n");
stream_read_uint32(qtmovie->stream);
size_remaining -= 4;
return;
@@ -326,7 +328,7 @@ static void read_chunk_stsz(qtmovie_t *qtmovie, size_t chunk_len)
if (size_remaining)
{
- fprintf(stderr, "ehm, size remianing?\n");
+ //fprintf(stderr, "ehm, size remianing?\n");
stream_skip(qtmovie->stream, size_remaining);
}
}
@@ -343,7 +345,7 @@ static void read_chunk_stbl(qtmovie_t *qtmovie, size_t chunk_len)
sub_chunk_len = stream_read_uint32(qtmovie->stream);
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
{
- fprintf(stderr, "strange size for chunk inside stbl\n");
+ //fprintf(stderr, "strange size for chunk inside stbl\n");
return;
}
@@ -366,8 +368,8 @@ static void read_chunk_stbl(qtmovie_t *qtmovie, size_t chunk_len)
stream_skip(qtmovie->stream, sub_chunk_len - 8);
break;
default:
- fprintf(stderr, "(stbl) unknown chunk id: %c%c%c%c\n",
- SPLITFOURCC(sub_chunk_id));
+// fprintf(stderr, "(stbl) unknown chunk id: %c%c%c%c\n",
+// SPLITFOURCC(sub_chunk_id));
return;
}
@@ -383,12 +385,12 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
/**** SOUND HEADER CHUNK ****/
if (stream_read_uint32(qtmovie->stream) != 16)
{
- fprintf(stderr, "unexpected size in media info\n");
+ //fprintf(stderr, "unexpected size in media info\n");
return;
}
if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','m','h','d'))
{
- fprintf(stderr, "not a sound header! can't handle this.\n");
+ //fprintf(stderr, "not a sound header! can't handle this.\n");
return;
}
/* now skip the rest */
@@ -400,7 +402,7 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
dinf_size = stream_read_uint32(qtmovie->stream);
if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('d','i','n','f'))
{
- fprintf(stderr, "expected dinf, didn't get it.\n");
+ //fprintf(stderr, "expected dinf, didn't get it.\n");
return;
}
/* skip it */
@@ -413,7 +415,7 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
stbl_size = stream_read_uint32(qtmovie->stream);
if (stream_read_uint32(qtmovie->stream) != MAKEFOURCC('s','t','b','l'))
{
- fprintf(stderr, "expected stbl, didn't get it.\n");
+ //fprintf(stderr, "expected stbl, didn't get it.\n");
return;
}
read_chunk_stbl(qtmovie, stbl_size);
@@ -421,7 +423,7 @@ static void read_chunk_minf(qtmovie_t *qtmovie, size_t chunk_len)
if (size_remaining)
{
- fprintf(stderr, "oops\n");
+ //fprintf(stderr, "oops\n");
stream_skip(qtmovie->stream, size_remaining);
}
}
@@ -438,7 +440,7 @@ static void read_chunk_mdia(qtmovie_t *qtmovie, size_t chunk_len)
sub_chunk_len = stream_read_uint32(qtmovie->stream);
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
{
- fprintf(stderr, "strange size for chunk inside mdia\n");
+ //fprintf(stderr, "strange size for chunk inside mdia\n");
return;
}
@@ -456,8 +458,8 @@ static void read_chunk_mdia(qtmovie_t *qtmovie, size_t chunk_len)
read_chunk_minf(qtmovie, sub_chunk_len);
break;
default:
- fprintf(stderr, "(mdia) unknown chunk id: %c%c%c%c\n",
- SPLITFOURCC(sub_chunk_id));
+// fprintf(stderr, "(mdia) unknown chunk id: %c%c%c%c\n",
+// SPLITFOURCC(sub_chunk_id));
return;
}
@@ -478,7 +480,7 @@ static void read_chunk_trak(qtmovie_t *qtmovie, size_t chunk_len)
sub_chunk_len = stream_read_uint32(qtmovie->stream);
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
{
- fprintf(stderr, "strange size for chunk inside trak\n");
+ //fprintf(stderr, "strange size for chunk inside trak\n");
return;
}
@@ -493,8 +495,8 @@ static void read_chunk_trak(qtmovie_t *qtmovie, size_t chunk_len)
read_chunk_mdia(qtmovie, sub_chunk_len);
break;
default:
- fprintf(stderr, "(trak) unknown chunk id: %c%c%c%c\n",
- SPLITFOURCC(sub_chunk_id));
+// fprintf(stderr, "(trak) unknown chunk id: %c%c%c%c\n",
+// SPLITFOURCC(sub_chunk_id));
return;
}
@@ -533,7 +535,7 @@ static void read_chunk_moov(qtmovie_t *qtmovie, size_t chunk_len)
sub_chunk_len = stream_read_uint32(qtmovie->stream);
if (sub_chunk_len <= 1 || sub_chunk_len > size_remaining)
{
- fprintf(stderr, "strange size for chunk inside moov\n");
+ //fprintf(stderr, "strange size for chunk inside moov\n");
return;
}
@@ -551,8 +553,8 @@ static void read_chunk_moov(qtmovie_t *qtmovie, size_t chunk_len)
read_chunk_udta(qtmovie, sub_chunk_len);
break;
default:
- fprintf(stderr, "(moov) unknown chunk id: %c%c%c%c\n",
- SPLITFOURCC(sub_chunk_id));
+// fprintf(stderr, "(moov) unknown chunk id: %c%c%c%c\n",
+// SPLITFOURCC(sub_chunk_id));
return;
}
@@ -574,14 +576,11 @@ static void read_chunk_mdat(qtmovie_t *qtmovie, size_t chunk_len)
int qtmovie_read(stream_t *file, demux_res_t *demux_res)
{
- qtmovie_t *qtmovie;
-
- qtmovie = (qtmovie_t*)malloc(sizeof(qtmovie_t));
+ qtmovie_t qtmovie;
/* construct the stream */
- qtmovie->stream = file;
-
- qtmovie->res = demux_res;
+ qtmovie.stream = file;
+ qtmovie.res = demux_res;
/* read the chunks */
while (1)
@@ -589,26 +588,26 @@ int qtmovie_read(stream_t *file, demux_res_t *demux_res)
size_t chunk_len;
fourcc_t chunk_id;
- chunk_len = stream_read_uint32(qtmovie->stream);
- if (stream_eof(qtmovie->stream))
+ chunk_len = stream_read_uint32(qtmovie.stream);
+ if (stream_eof(qtmovie.stream))
{
return 0;
}
if (chunk_len == 1)
{
- fprintf(stderr, "need 64bit support\n");
+ //fprintf(stderr, "need 64bit support\n");
return 0;
}
- chunk_id = stream_read_uint32(qtmovie->stream);
+ chunk_id = stream_read_uint32(qtmovie.stream);
switch (chunk_id)
{
case MAKEFOURCC('f','t','y','p'):
- read_chunk_ftyp(qtmovie, chunk_len);
+ read_chunk_ftyp(&qtmovie, chunk_len);
break;
case MAKEFOURCC('m','o','o','v'):
- read_chunk_moov(qtmovie, chunk_len);
+ read_chunk_moov(&qtmovie, chunk_len);
break;
/* once we hit mdat we stop reading and return.
* this is on the assumption that there is no furhter interesting
@@ -617,16 +616,16 @@ int qtmovie_read(stream_t *file, demux_res_t *demux_res)
* for the decoder. And we don't want to rely on fseek/ftell,
* as they may not always be avilable */
case MAKEFOURCC('m','d','a','t'):
- read_chunk_mdat(qtmovie, chunk_len);
+ read_chunk_mdat(&qtmovie, chunk_len);
return 1;
/* these following atoms can be skipped !!!! */
case MAKEFOURCC('f','r','e','e'):
- stream_skip(qtmovie->stream, chunk_len - 8); /* FIXME not 8 */
+ stream_skip(qtmovie.stream, chunk_len - 8); /* FIXME not 8 */
break;
default:
- fprintf(stderr, "(top) unknown chunk id: %c%c%c%c\n",
- SPLITFOURCC(chunk_id));
+// fprintf(stderr, "(top) unknown chunk id: %c%c%c%c\n",
+// SPLITFOURCC(chunk_id));
return 0;
}
diff --git a/apps/codecs/libalac/demux.h b/apps/codecs/libalac/demux.h
index 62b949fa3b..27c9e826c5 100644
--- a/apps/codecs/libalac/demux.h
+++ b/apps/codecs/libalac/demux.h
@@ -1,7 +1,7 @@
#ifndef DEMUX_H
#define DEMUX_H
-#include <stdint.h>
+#include <inttypes.h>
#include "stream.h"
typedef uint32_t fourcc_t;
diff --git a/apps/codecs/libalac/stream.h b/apps/codecs/libalac/stream.h
index 31f93d9059..95be0b56d0 100644
--- a/apps/codecs/libalac/stream.h
+++ b/apps/codecs/libalac/stream.h
@@ -3,9 +3,11 @@
/* stream.h */
-#include <stdint.h>
+#include <inttypes.h>
-typedef struct stream_tTAG stream_t;
+typedef struct {
+ int eof;
+} stream_t;
void stream_read(stream_t *stream, size_t len, void *buf);
@@ -22,9 +24,4 @@ void stream_skip(stream_t *stream, size_t skip);
int stream_eof(stream_t *stream);
-stream_t *stream_create_file(FILE *file,
- int bigendian);
-void stream_destroy(stream_t *stream);
-
#endif /* STREAM_H */
-