[Decals-svnlog] SF.net SVN: decals: [2]
Status: Inactive
Brought to you by:
jbr79
From: <jb...@us...> - 2007-08-20 00:08:13
|
Revision: 2 http://decals.svn.sourceforge.net/decals/?rev=2&view=rev Author: jbr79 Date: 2007-08-19 17:08:12 -0700 (Sun, 19 Aug 2007) Log Message: ----------- initial SVN import Added Paths: ----------- Makefile alsdec.c alsdec.h alstab.h bitreader.c bitreader.h bswap.h common.h config.h config.mak main.c Added: Makefile =================================================================== --- Makefile (rev 0) +++ Makefile 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,37 @@ +## +# Makefile for Decals +## + +include config.mak + +LDFLAGS = +LIBOBJS = +LIBS = -lm + +PROGS = decals$(EXEEXT) + +decals_OBJS = alsdec.o bitreader.o main.o +decals_SRCS = $(alsdec_OBJS:.o=.c) +decals_LDFLAGS = + +all: dep $(PROGS) + +.c.o: + $(CC) -DHAVE_CONFIG_H $(CFLAGS) -c $< + +decals$(EXEEXT): $(decals_OBJS) + $(CC) $(CFLAGS) -o $@ $(decals_LDFLAGS) $(decals_OBJS) $(LIBOBJS) $(LIBS) + +clean: + $(RM) decals$(EXEEXT) *.o .depend + +dep: depend + +depend: .depend + +.depend: $(decals_SRCS) + $(CC) -MM $(CFLAGS) $^ 1>.depend + +ifneq ($(wildcard .depend),) +include .depend +endif Added: alsdec.c =================================================================== --- alsdec.c (rev 0) +++ alsdec.c 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,708 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * internal frame buffering is from FFmpeg/libavcodec/flac.c + * Copyright (c) 2003 Alex Bergszaszi + * fast_realloc() is from FFmpeg/libavcodec/utils.c + * Copyright (c) 2001 Fabrice Bellard + * Copyright (c) 2002-2004 Michael Niedermayer + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alsdec.c + * ALS decoder + */ + +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <assert.h> + +#include "bitreader.h" +#include "alsdec.h" +#include "alstab.h" + +static void * +fast_realloc(void *ptr, unsigned int *size, unsigned int min_size) +{ + if(min_size < *size) + return ptr; + + *size = MAX(17*min_size/16 + 32, min_size); + + return realloc(ptr, *size); +} + +static int +read_als_header(AlsDecodeContext *ctx) +{ + int magic; + + // read header fields from bitstream + magic = get_bits(&ctx->gbc, 32); + ctx->sample_rate = get_bits(&ctx->gbc, 32); + ctx->samples = get_bits(&ctx->gbc, 32); + ctx->channels = get_bits(&ctx->gbc, 16) + 1; + ctx->file_type = get_bits(&ctx->gbc, 3); + ctx->bps = get_bits(&ctx->gbc, 3) * 8 + 8; + ctx->sample_type = get_bits1(&ctx->gbc); + ctx->source_order = get_bits1(&ctx->gbc); + ctx->frame_size = get_bits(&ctx->gbc, 16) + 1; + ctx->random_access = get_bits(&ctx->gbc, 8); + ctx->ra_location = get_bits(&ctx->gbc, 2); + ctx->adapt_order = get_bits1(&ctx->gbc); + ctx->coef_table = get_bits(&ctx->gbc, 2); + ctx->ltp = get_bits1(&ctx->gbc); + ctx->pred_order = get_bits(&ctx->gbc, 10); + ctx->blksw = get_bits(&ctx->gbc, 2); + ctx->coding_type = get_bits1(&ctx->gbc); + ctx->coding_part = get_bits1(&ctx->gbc); + ctx->joint_stereo = get_bits1(&ctx->gbc); + ctx->mcc = get_bits1(&ctx->gbc); + ctx->ch_config = get_bits1(&ctx->gbc); + ctx->ch_reorder = get_bits1(&ctx->gbc); + ctx->has_crc = get_bits1(&ctx->gbc); + ctx->rlslms = get_bits1(&ctx->gbc); + get_bits(&ctx->gbc, 5); + ctx->has_aux = get_bits1(&ctx->gbc); + + // check for validity + if(magic != 0x414C5300) { + fprintf(stderr, "ALS header not found\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->sample_rate == 0) { + fprintf(stderr, "invalid ALS header: sample rate cannot be 0\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->samples == 0) { + fprintf(stderr, "invalid ALS header: sample count cannot be 0\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->file_type > 2) { + fprintf(stderr, "invalid ALS header: unknown file type: %d\n", + ctx->file_type); + return ALS_ERROR_GENERAL; + } + if(ctx->bps > 32) { + fprintf(stderr, "invalid ALS header: reserved bit depth: %d \n", + ctx->bps); + return ALS_ERROR_GENERAL; + } + if(ctx->coef_table == 3) { + fprintf(stderr, "invalid ALS header: invalid coefficient table: 3\n"); + return ALS_ERROR_GENERAL; + } + + // calculate frame count + ctx->last_samples = ctx->samples % ctx->frame_size; + ctx->frames = ctx->samples / ctx->frame_size; + if(ctx->last_samples) + ctx->frames++; + + // calculate bits for channel index + ctx->bpc = MAX(1, ceil(LOG2(ctx->channels))); + + // calculate random access frame count + if(ctx->random_access) { + ctx->ra_units = ctx->frames / ctx->random_access; + if(ctx->frames % ctx->random_access) + ctx->ra_units++; + ctx->ra_index = 0; + } + + // calculate block switch flag bits + if(ctx->blksw) + ctx->blksw = 1 << (ctx->blksw + 2); + + return ALS_OK; +} + +static int +read_channel_order(AlsDecodeContext *ctx, FILE *fp) +{ + GetBitContext gbc; + uint8_t *buf; + int i, size; + + ctx->ch_pos = calloc(ctx->channels, 1); + if(!ctx->ch_pos) + return ALS_ERROR_MEMORY; + size = ((ctx->bpc * ctx->channels) + 7) / 8; + buf = calloc(1, size); + if(!buf) + return ALS_ERROR_MEMORY; + if(fread(buf, 1, size, fp) != size) + return ALS_ERROR_EOF; + init_get_bits(&gbc, buf, size * 8); + + for(i=0; i<ctx->channels; i++) { + ctx->ch_pos[i] = get_bits(&gbc, ctx->bpc); + } + free(buf); + return ALS_OK; +} + +int +als_decode_init(AlsDecodeContext *ctx, FILE *fp) +{ + uint8_t buf[22]; + int i, ret; + + memset(ctx, 0, sizeof(*ctx)); + + // ALS header + if(fread(buf, 1, 22, fp) != 22) + return ALS_ERROR_EOF; + init_get_bits(&ctx->gbc, buf, 176); + ret = read_als_header(ctx); + if(ret) + return ret; + + // channel configuration (unused) + if(ctx->ch_config) + if(fread(buf, 2, 1, fp) != 1) + return ALS_ERROR_EOF; + + // channel reordering + if(ctx->ch_reorder) { + ret = read_channel_order(ctx, fp); + if(ret) + return ret; + } + + // source file header and trailer + if(fread(&ctx->header_size, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->header_size = be2me_32(ctx->header_size); + if(fread(&ctx->trailer_size, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->trailer_size = be2me_32(ctx->trailer_size); + if(ctx->header_size > 0) { + ctx->header = calloc(ctx->header_size, 1); + if(!ctx->header) + return ALS_ERROR_MEMORY; + if(fread(ctx->header, 1, ctx->header_size, fp) != ctx->header_size) + return ALS_ERROR_EOF; + } + if(ctx->trailer_size > 0) { + ctx->trailer = calloc(ctx->trailer_size, 1); + if(!ctx->trailer) + return ALS_ERROR_MEMORY; + if(fread(ctx->trailer, 1, ctx->trailer_size, fp) != ctx->trailer_size) + return ALS_ERROR_EOF; + } + + // CRC-32 + if(ctx->has_crc) { + if(fread(&ctx->ref_crc, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->ref_crc = be2me_32(ctx->ref_crc); + ctx->crc = 0xFFFFFFFF; + } + + // random access units + if(ctx->random_access) { + ctx->ra_sizes = calloc(ctx->ra_units, sizeof(uint32_t)); + if(!ctx->ra_sizes) + return ALS_ERROR_MEMORY; + if(ctx->ra_location == RA_LOCATION_HEADER) { + if(fread(ctx->ra_sizes, 4, ctx->ra_units, fp) != ctx->ra_units) + return ALS_ERROR_EOF; + for(i=0; i<ctx->ra_units; i++) { + ctx->ra_sizes[i] = be2me_32(ctx->ra_sizes[i]); + } + } + } + + // auxilliary data + if(ctx->has_aux) { + if(fread(&ctx->aux_size, 1, 4, fp) != 4) + return ALS_ERROR_EOF; + ctx->aux_size = be2me_32(ctx->aux_size); + ctx->aux = calloc(1, ctx->aux_size); + if(!ctx->aux) + return ALS_ERROR_MEMORY; + if(fread(ctx->aux, 1, ctx->aux_size, fp) != ctx->aux_size) + return ALS_ERROR_EOF; + } + + // allocate blocks + /*ctx->frame.blocks = calloc(ctx->channels, sizeof(AlsBlock)); + if(!ctx->frame.blocks) + return ALS_ERROR_MEMORY;*/ + + // allocated decoded audio + ctx->decoded = calloc(ctx->channels, sizeof(int32_t *)); + for(i=0; i<ctx->channels; i++) { + ctx->decoded[i] = calloc(ctx->frame_size, sizeof(int32_t)); + } + + // allocate buffer + ctx->max_frame_bytes = (ctx->channels * ctx->bps * ctx->frame_size + 7) / 8; + ctx->bitstream = fast_realloc(ctx->bitstream, + &ctx->allocated_bitstream_size, + ctx->max_frame_bytes); + + return ALS_OK; +} + +/** + * Parses block switch flags to determine subblock count and sizes. + * @return Returns the number of subblocks + */ +static int +parse_subblock_sizes(uint32_t flags, int fs, int sub_sizes[32]) +{ + int b; + int i, j, k, l, m, n; + int sh; + uint8_t lvl[5][16]; + + // parse flags into binary tree + sh = 30; + for(l=0; l<5; l++) { + n = 1 << l; + for(i=0; i<n; i++) { + lvl[l][i] = (flags >> sh) & 1; + sh--; + } + } + + // traverse binary tree to determine subblock count and sizes + b = 0; + l = 0; // level 0 + if(!lvl[l][0]) { + sub_sizes[b++] = fs; + } else { + for(i=0; i<2; i++) { + l = 1; // level 1 + if(!lvl[l][i]) { + sub_sizes[b++] = fs >> l; + } else { + for(j=0; j<2; j++) { + l = 2; // level 2 + if(!lvl[l][j]) { + sub_sizes[b++] = fs >> l; + } else { + for(k=0; k<2; k++) { + l = 3; // level 3 + if(!lvl[l][k]) { + sub_sizes[b++] = fs >> l; + } else { + for(m=0; m<2; m++) { + l = 4; // level 4 + if(!lvl[l][m]) { + sub_sizes[b++] = fs >> l; + } else { + l = 5; // level 5 + sub_sizes[b++] = fs >> l; + sub_sizes[b++] = fs >> l; + } + } + } + } + } + } + } + } + } + + // return number of subblocks + return b; +} + +static int +decode_subblock(AlsDecodeContext *ctx, int ch, int sb) +{ + int i; + int sb_size = ctx->frame.subblock_sizes[sb]; + fprintf(stderr, "channel=%d subblock=%d\n", ch, sb); + + align_get_bits(&ctx->gbc); + if(get_bits1(&ctx->gbc)) { + ctx->frame.block_type = BLOCK_TYPE_NORMAL; + } else { + if(get_bits1(&ctx->gbc)) + ctx->frame.block_type = BLOCK_TYPE_CONSTANT; + else + ctx->frame.block_type = BLOCK_TYPE_ZERO; + } + /*ctx->frame.block_type = get_bits(&ctx->gbc, 2); + if(ctx->frame.block_type == 3) + ctx->frame.block_type = BLOCK_TYPE_NORMAL;*/ + fprintf(stderr, "block type: "); + switch(ctx->frame.block_type) { + case BLOCK_TYPE_ZERO: fprintf(stderr, "ZERO\n"); break; + case BLOCK_TYPE_CONSTANT: fprintf(stderr, "CONSTANT\n"); break; + case BLOCK_TYPE_NORMAL: fprintf(stderr, "NORMAL\n"); break; + } + ctx->frame.diff_flag = get_bits1(&ctx->gbc); + fprintf(stderr, "difference signal: %s\n", ctx->frame.diff_flag?"yes":"no"); + + if(ctx->frame.block_type == BLOCK_TYPE_CONSTANT) { + align_get_bits(&ctx->gbc); + get_bits(&ctx->gbc, ctx->bps); + } else if(ctx->frame.block_type == BLOCK_TYPE_NORMAL) { + if(ctx->coding_type == CODING_TYPE_RICE) { + // determine entropy partitioning + ctx->frame.ec_part = 1; + if(ctx->coding_part && get_bits1(&ctx->gbc)) + ctx->frame.ec_part = 4; + fprintf(stderr, "ec partitions: %d\n", ctx->frame.ec_part); + + // read Rice parameters for each partition + ctx->frame.rice_params[0] = get_bits(&ctx->gbc, 4+(ctx->bps>16)); + for(i=1; i<ctx->frame.ec_part; i++) { + ctx->frame.rice_params[i] = ctx->frame.rice_params[i-1]; + ctx->frame.rice_params[i] += get_rice(&ctx->gbc, 0); + } + fprintf(stderr, "rice params:"); + for(i=0; i<ctx->frame.ec_part; i++) { + fprintf(stderr, " %d", ctx->frame.rice_params[i]); + } + fprintf(stderr, "\n"); + } else if(ctx->coding_type == CODING_TYPE_BGMC) { + // determine entropy partitioning + if(ctx->coding_part) { + ctx->frame.ec_part = 1 << get_bits(&ctx->gbc, 2); + } else if(get_bits1(&ctx->gbc)) { + ctx->frame.ec_part = 4; + } + + // read BGMC parameters for each partition + ctx->frame.bgmc_rice[0] = get_bits(&ctx->gbc, 8+(ctx->bps>16)); + for(i=1; i<ctx->frame.ec_part; i++) { + ctx->frame.bgmc_rice[i] = ctx->frame.rice_params[i-1]; + ctx->frame.bgmc_rice[i] += get_rice(&ctx->gbc, 2); + } + + // separate grouped BGMC parameters + for(i=1; i<ctx->frame.ec_part; i++) { + ctx->frame.bgmc_freq[i] = ctx->frame.bgmc_rice[i] & 0x0F; + ctx->frame.bgmc_rice[i] >>= 4; + } + } + + // shift for unused LSB's + ctx->frame.lsb_shift = get_bits1(&ctx->gbc); + if(ctx->frame.lsb_shift) + ctx->frame.lsb_shift += get_bits(&ctx->gbc, 4); + fprintf(stderr, "shift: %d\n", ctx->frame.lsb_shift); + + // decode LPC coefficients + if(!ctx->rlslms) { + // determine LPC order + int p = ctx->pred_order; + if(ctx->adapt_order) { + int max_order = CLIP(p, 1, (sb_size>>3)-1); + int obits = MAX(1, ceil(LOG2(max_order))); + p = get_bits(&ctx->gbc, obits); + } + ctx->frame.pred_order = p; + fprintf(stderr, "lpc order: %d\n", p); + + // decode quantized coefficients + if(ctx->coef_table == 3) { + for(i=0; i<p; i++) { + ctx->frame.parcor_coefs[i] = get_bits(&ctx->gbc, 7) - 64; + } + } else { + const ParcorVars *pv = parcor_vars[ctx->coef_table]; + i = 0; + for(; i<MIN(p, 20); i++) { + ctx->frame.parcor_coefs[i] = pv[i].offset + get_rice(&ctx->gbc, pv[i].param); + } + for(; i<MIN(p, 127); i++) { + ctx->frame.parcor_coefs[i] = (i & 1) + get_rice(&ctx->gbc, 2); + } + for(; i<p; i++) { + ctx->frame.parcor_coefs[i] = get_rice(&ctx->gbc, 1); + } + } + fprintf(stderr, "qpar:"); + for(i=0; i<p; i++) { + fprintf(stderr, " %d", ctx->frame.parcor_coefs[i]); + } + fprintf(stderr, "\n"); + + // compute scaled parcor coefficients + for(i=0; i<p; i++) { + int qc = ctx->frame.parcor_coefs[i]; + int coef; + if(i < 2) { + coef = 32 + ((qc + 64) * (qc + 65) << 7) - (1 << 20); + if(i == 2) + coef = -coef; + } else { + coef = (qc << 14) + (1 << 13); + } + ctx->frame.parcor_coefs[i] = coef; + } + fprintf(stderr, "par:"); + for(i=0; i<p; i++) { + fprintf(stderr, " %d", ctx->frame.parcor_coefs[i]); + } + fprintf(stderr, "\n"); + } else { + // default prediction order for RLS-LMS + ctx->frame.pred_order = 10; + } + + // no LTP + + // decode residual + if(ctx->frame.is_ra_frame && sb == 0) { + // get residual signal, random access + int j, prog; + + prog = MIN(3, ctx->frame.pred_order); + if(prog > 0) + get_rice(&ctx->gbc, ctx->bps-4); + if(prog > 1) + get_rice(&ctx->gbc, MIN(ctx->frame.rice_params[0]+3, 31)); + if(prog > 2) + get_rice(&ctx->gbc, MIN(ctx->frame.rice_params[0]+1, 31)); + + if(ctx->coding_type == CODING_TYPE_RICE) { + int part_size = sb_size / ctx->frame.ec_part; + for(j=0; j<part_size-prog; j++) { + get_rice(&ctx->gbc, ctx->frame.rice_params[0]); + } + for(i=1; i<ctx->frame.ec_part; i++) { + for(j=0; j<part_size; j++) { + get_rice(&ctx->gbc, ctx->frame.rice_params[i]); + } + } + } else if(ctx->coding_type == CODING_TYPE_BGMC) { + fprintf(stderr, "BGMC decoding unsupported\n"); + return ALS_ERROR_GENERAL; + } + } else { + // get residual signal, no random access + int j; + if(ctx->coding_type == CODING_TYPE_RICE) { + int part_size = sb_size / ctx->frame.ec_part; + fprintf(stderr, "partition size: %d\n", part_size); + for(i=0; i<ctx->frame.ec_part; i++) { + fprintf(stderr, "res[%d]:", i); + for(j=0; j<part_size; j++) { + int r = get_rice(&ctx->gbc, ctx->frame.rice_params[i]); + fprintf(stderr, " %d", r); + } + fprintf(stderr, "\n"); + } + } else if(ctx->coding_type == CODING_TYPE_BGMC) { + fprintf(stderr, "BGMC decoding unsupported\n"); + return ALS_ERROR_GENERAL; + } + } + } + + // no RLS-LMS + + // no MCC + + return ALS_OK; +} + +static int +decode_single_block(AlsDecodeContext *ctx, int ch) +{ + int sb; + + ctx->frame.coupled_block = 0; + ctx->frame.num_subblocks = 1; + ctx->frame.subblock_sizes[0] = ctx->frame_size; + if(ctx->frame_index == ctx->frames) + ctx->frame.subblock_sizes[0] = ctx->last_samples; + + for(sb=0; sb<ctx->frame.num_subblocks; sb++) { + decode_subblock(ctx, ch, sb); + } + + return ALS_OK; +} + +static int +decode_joint_block(AlsDecodeContext *ctx, int ch0) +{ + int ch1 = ch0 + 1; + return ALS_OK; +} + +static int +decode_frame(AlsDecodeContext *ctx, int alloc_data_size) +{ + int ch; + + // read random access unit size + ctx->frame.is_ra_frame = 0; + if(ctx->random_access) { + ctx->frame.is_ra_frame = !(ctx->frame_index % ctx->random_access); + if(ctx->frame.is_ra_frame && ctx->ra_location == RA_LOCATION_FRAME) { + ctx->ra_sizes[ctx->ra_index] = get_bits(&ctx->gbc, 32); + } + } + + // determine if MCC is used + ctx->frame.use_mcc = 0; + if(ctx->mcc) { + if(ctx->joint_stereo) + ctx->frame.use_mcc = get_bits(&ctx->gbc, 8); + else + ctx->frame.use_mcc = 1; + } + + // currently unsupported features + if(ctx->frame.use_mcc) { + fprintf(stderr, "MCC unsupported\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->joint_stereo) { + fprintf(stderr, "Joint Stereo unsupported\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->blksw) { + fprintf(stderr, "Block Switching unsupported\n"); + return ALS_ERROR_GENERAL; + } + if(ctx->rlslms) { + fprintf(stderr, "RLS-LMS unsupported\n"); + return ALS_ERROR_GENERAL; + } + + for(ch=0; ch<ctx->channels; ch++) { + decode_single_block(ctx, ch); + } + + // increment indices + if(ctx->frame.is_ra_frame) { + ctx->ra_index++; + } + ctx->frame_index++; + + return ALS_OK; +} + +int +als_decode_frame(AlsDecodeContext *ctx, void *data, int *data_size, + uint8_t *buf, int buf_size) +{ + int input_buf_size = 0; + int32_t *samples = data; + int alloc_data_size = *data_size; + int frame_size; + int i, ch; + + *data_size = 0; + + assert(ctx->max_frame_bytes > 0); + + fprintf(stderr, "decoding frame %d\n", ctx->frame_index); + + // copy input bytes to internal buffer + buf_size = MAX(MIN(buf_size, ctx->max_frame_bytes - ctx->bitstream_size), 0); + input_buf_size = buf_size; + if(ctx->bitstream_index + ctx->bitstream_size + buf_size > ctx->allocated_bitstream_size) { + memmove(ctx->bitstream, &ctx->bitstream[ctx->bitstream_index], ctx->bitstream_size); + ctx->bitstream_index = 0; + } + memcpy(&ctx->bitstream[ctx->bitstream_index + ctx->bitstream_size], buf, buf_size); + buf = &ctx->bitstream[ctx->bitstream_index]; + ctx->bitstream_size += buf_size; + if(ctx->bitstream_size < ctx->max_frame_bytes) { + // need more data + if(ctx->frame_index != ctx->frames-1) { + fprintf(stderr, "need more data...\n"); + return input_buf_size; + } + } + init_get_bits(&ctx->gbc, buf, ctx->bitstream_size*8); + + // decode ALS frame to ctx->decoded + if(decode_frame(ctx, alloc_data_size)) { + fprintf(stderr, "decode_frame() failed\n"); + ctx->bitstream_size = 0; + ctx->bitstream_index = 0; + return -1; + } + fprintf(stderr, "\n"); + + if(ctx->frame_index == ctx->frames) + frame_size = ctx->last_samples; + else + frame_size = ctx->frame_size; + + // copy/interleave ctx->decoded to samples + for(i=0; i<frame_size; i++) { + for(ch=0; ch<ctx->channels; ch++) { + *(samples++) = ctx->decoded[ch][i]; + } + } + + *data_size = (int8_t *)samples - (int8_t *)data; + + i = (get_bits_count(&ctx->gbc) + 7) / 8; + if(i > buf_size) { + fprintf(stderr, "frame size too large (max_frame_bytes too low)\n"); + ctx->bitstream_size = 0; + ctx->bitstream_index = 0; + return -1; + } + + if(ctx->bitstream_size) { + ctx->bitstream_index += i; + ctx->bitstream_size -= i; + return input_buf_size; + } else { + return i; + } +} + +int +als_decode_close(AlsDecodeContext *ctx) +{ + int i; + if(ctx) { + if(ctx->ch_pos) + free(ctx->ch_pos); + if(ctx->header) + free(ctx->header); + if(ctx->trailer) + free(ctx->trailer); + if(ctx->ra_sizes) + free(ctx->ra_sizes); + if(ctx->aux) + free(ctx->aux); + //if(ctx->frame.blocks) + // free(ctx->frame.blocks); + if(ctx->decoded) { + for(i=0; i<ctx->channels; i++) { + if(ctx->decoded[i]) + free(ctx->decoded[i]); + } + free(ctx->decoded); + } + if(ctx->bitstream) + free(ctx->bitstream); + } + return ALS_OK; +} Added: alsdec.h =================================================================== --- alsdec.h (rev 0) +++ alsdec.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,170 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alsdec.h + * ALS decoder header + */ + +#ifndef ALSDEC_H +#define ALSDEC_H + +#include "common.h" + +#include <stdio.h> +#include <string.h> + +#include "bitreader.h" + +enum { + ALS_OK = 0, + ALS_ERROR_GENERAL = -1, + ALS_ERROR_MEMORY = -2, + ALS_ERROR_EOF = -3 +} AlsError; + +enum { + FILE_TYPE_RAW = 0, + FILE_TYPE_WAVE = 1, + FILE_TYPE_AIFF = 2 +} FileType; + +enum { + SAMPLE_TYPE_INT = 0, + SAMPLE_TYPE_FLOAT = 1 +} SampleType; + +enum { + SRC_ORDER_LE = 0, + SRC_ORDER_BE = 1 +} SourceOrder; + +enum { + RA_LOCATION_NONE = 0, + RA_LOCATION_FRAME = 1, + RA_LOCATION_HEADER = 2 +} RaLocation; + +enum { + CODING_TYPE_RICE = 0, + CODING_TYPE_BGMC = 1 +} CodingType; + +enum { + BLOCK_TYPE_ZERO = 0, + BLOCK_TYPE_CONSTANT, + BLOCK_TYPE_NORMAL +} BlockType; + +typedef struct { + /* frame */ + int is_ra_frame; ///< flag is on if current frame is an RA frame + int use_mcc; ///< flag is on if current frame uses MCC + + /* block */ + int num_subblocks; ///< number of subblocks for the current block + int subblock_sizes[32]; ///< list containing the size of each subblock + int coupled_block; ///< indicates if this is a coupled block + + /* subblock */ + int block_type; ///< indicates normal, zero, or constant block type + int diff_flag; ///< for zero and constant blocks, indicates if the + ///< block contains a difference signal or a normal + ///< signal + int ec_part; ///< number of entropy coding partitions + int rice_params[4]; ///< Rice parameters for each partition + int bgmc_rice[8]; ///< for BGMC, Rice parameters for coding tail + int bgmc_freq[8]; ///< for BGMC, frequency indices for coding MSB + int lsb_shift; ///< optional shift level for unused LSB's + int pred_order; ///< current prediction order + int parcor_coefs[1023]; ///< decoded parcor coefficients +} AlsFrame; + +typedef struct { + + GetBitContext gbc; + + /* from ALS header */ + uint32_t sample_rate; ///< sampling frequency + uint32_t samples; ///< number of audio samples in the file + int channels; ///< number of channels + int file_type; ///< source file type (original file format) + int bps; ///< bits-per-sample + int sample_type; ///< source sample type (integer or floating-point) + int source_order; ///< source sample byte order + int frame_size; ///< number of samples in each frame + int random_access; ///< random access frame interval + int ra_location; ///< where the RA frames are located + int adapt_order; ///< uses adaptive (non-fixed) prediction order + int coef_table; ///< which coefficient table to use + int ltp; ///< uses long term prediction + int pred_order; ///< maximum or fixed prediction order + int blksw; ///< block switching + int coding_type; ///< entropy coding type (Rice or BGMC) + int coding_part; ///< coded blocks are partitioned + int joint_stereo; ///< uses joint stereo channel correlation + int mcc; ///< uses multi-channel correlation + int ch_config; ///< has channel configuration + int ch_reorder; ///< has channel reordering + int has_crc; ///< has CRC error checking + int rlslms; ///< uses RLSLMS + int has_aux; ///< has auxiliary data + int *ch_pos; ///< channel positions, if reordering + int header_size; ///< source header size + int trailer_size; ///< source trailer size + + /* derived values */ + int bpc; ///< bits used to reference channel positions + int last_samples; ///< number of samples in the final frame + int frames; ///< number of frames in the file + int ra_units; ///< number of random access units + uint32_t *ra_sizes; ///< sizes, in bytes, of random access units + int aux_size; ///< auxilliary data size + uint8_t *aux; ///< auxilliary data + int header_pos; ///< file position of source header + uint8_t *header; ///< source header + int trailer_pos; ///< file position of source trailer + uint8_t *trailer; ///< source trailer + int start_pos; ///< file position of first ALS frame + uint32_t ref_crc; ///< reference CRC-32 checksum + + /* global fields */ + AlsFrame frame; ///< current frame data + int frame_index; ///< frame index number + int ra_index; ///< random access index number + uint32_t crc; ///< running CRC-32 checksum of decoded audio + + /* internal buffers */ + int32_t **decoded; ///< decoded audio data + int max_frame_bytes; ///< estimated maximum coded bytes in a frame + uint8_t *bitstream; ///< internal bitstream buffer + int bitstream_size; ///< current buffer size + int bitstream_index; ///< current buffer index + unsigned int allocated_bitstream_size; ///< total buffer size + +} AlsDecodeContext; + +extern int als_decode_init(AlsDecodeContext *ctx, FILE *fp); + +extern int als_decode_frame(AlsDecodeContext *ctx, void *data, int *data_size, + uint8_t *buf, int buf_size); + +extern int als_decode_close(AlsDecodeContext *ctx); + +#endif /* ALSDEC_H */ Added: alstab.h =================================================================== --- alstab.h (rev 0) +++ alstab.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,52 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file alstab.h + * ALS tables + */ + +#ifndef ALSTAB_H +#define ALSTAB_H + +/* rice code parameters for each coeff: */ +typedef struct { + int offset; + int param; +} ParcorVars; + +static const ParcorVars parcor_vars[3][20] = { + // samplerate is 44.1kHz or 48kHz + { {-52, 4}, {-29, 5}, {-31, 4}, { 19, 4}, {-16, 4}, + { 12, 3}, { -7, 3}, { 9, 3}, { -5, 3}, { 6, 3}, + { -4, 3}, { 3, 3}, { -3, 2}, { 3, 2}, { -2, 2}, + { 3, 2}, { -1, 2}, { 2, 2}, { -1, 2}, { 2, 2} }, + // samplerate is 96kHz + { {-58, 3}, {-42, 4}, {-46, 4}, { 37, 5}, {-36, 4}, + { 29, 4}, {-29, 4}, { 25, 4}, {-23, 4}, { 20, 4}, + {-17, 4}, { 16, 4}, {-12, 4}, { 12, 3}, {-10, 4}, + { 7, 3}, { -4, 4}, { 3, 3}, { -1, 3}, { 1, 3} }, + // samplerate is 192kHz + { {-59, 3}, {-45, 5}, {-50, 4}, { 38, 4}, {-39, 4}, + { 32, 4}, {-30, 4}, { 25, 3}, {-23, 3}, { 20, 3}, + {-20, 3}, { 16, 3}, {-13, 3}, { 10, 3}, { -7, 3}, + { 3, 3}, { 0, 3}, { -1, 3}, { 2, 3}, { -1, 2} } +}; + +#endif /* ALSTAB_H */ Added: bitreader.c =================================================================== --- bitreader.c (rev 0) +++ bitreader.c 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,213 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * This file is derived from libvorbis. + * Copyright (c) 2002, Xiph.org Foundation + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bitreader.c + * Memory-based bitwise reader + */ + +#include "bitreader.h" + +#include <stdlib.h> +#include <string.h> + +static const uint32_t mask[33] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, 0x0000000F, + 0x0000001F, 0x0000003F, 0x0000007F, 0x000000FF, 0x000001FF, + 0x000003FF, 0x000007FF, 0x00000FFF, 0x00001FFF, 0x00003FFF, + 0x00007FFF, 0x0000FFFF, 0x0001FFFF, 0x0003FFFF, 0x0007FFFF, + 0x000FFFFF, 0x001FFFFF, 0x003FFFFF, 0x007FFFFF, 0x00FFFFFF, + 0x01FFFFFF, 0x03FFFFFF, 0x07FFFFFF, 0x0FFFFFFF, 0x1FFFFFFF, + 0x3FFFFFFF, 0x7FFFFFFF, 0xFFFFFFFF +}; + +/* Bit Reader Functions */ + +void +init_get_bits(GetBitContext *b, uint8_t *buf, int bits) +{ + memset(b, 0, sizeof(*b)); + b->buffer = b->ptr = buf; + b->storage = (bits + 7) / 8; +} + +void +seek_bits(GetBitContext *b, int bitpos) +{ + int bytepos = bitpos >> 3; + if(bytepos < 0 || bytepos > b->storage) return; + b->ptr = &b->buffer[bytepos]; + b->endbyte = 0; + b->endbit = 0; +} + +void +skip_bits(GetBitContext *b, int bits) +{ + bits += b->endbit; + b->ptr += (bits >> 3); + b->endbyte += (bits >> 3); + b->endbit = (bits & 7); +} + +void +skip_bits1(GetBitContext *b) +{ + if(++(b->endbit) > 7) { + b->endbit = 0; + b->ptr++; + b->endbyte++; + } +} + +/* Read in bits without advancing the bitptr; bits <= 32 */ +uint32_t +look_bits(GetBitContext *b, int bits) +{ + unsigned long ret; + int m = 32-bits; + + bits += b->endbit; + + if(((b->endbyte+4)>=b->storage) && ((b->endbyte*8+bits)>(b->storage*8))) { + return 0; + } + + ret = b->ptr[0] << (24+b->endbit); + if(bits > 8) { + ret |= b->ptr[1] << (16+b->endbit); + if(bits > 16) { + ret |= b->ptr[2] << (8+b->endbit); + if(bits > 24) { + ret |= b->ptr[3] << (b->endbit); + if(bits>32 && b->endbit) { + ret|=b->ptr[4]>>(8-b->endbit); + } + } + } + } + return (uint32_t)(((ret&0xFFFFFFFF)>>(m>>1))>>((m+1)>>1)); +} + +/* bits <= 32 */ +uint32_t +get_bits(GetBitContext *b, int bits) +{ + long ret; + long m = 32 - bits; + + bits += b->endbit; + + if(b->endbyte+4 >= b->storage) { + // not the main path + ret = 0; + if((b->endbyte * 8 + bits) > (b->storage * 8)) { + goto overflow; + } + } + + ret = b->ptr[0] << (24+b->endbit); + if(bits > 8) { + ret |= b->ptr[1] << (16+b->endbit); + if(bits > 16) { + ret |= b->ptr[2] << (8+b->endbit); + if(bits > 24) { + ret |= b->ptr[3] << (b->endbit); + if(bits > 32 && b->endbit) { + ret |= b->ptr[4] >> (8-b->endbit); + } + } + } + } + ret = ((ret & 0xFFFFFFFFUL)>>(m>>1))>>((m+1)>>1); + + overflow: + b->ptr += (bits >> 3); + b->endbyte += (bits >> 3); + b->endbit = (bits & 7); + return (uint32_t)ret; +} + +long +get_bits1(GetBitContext *b) +{ + long ret; + + if(b->endbyte >= b->storage) { + // not the main path + ret=-1L; + goto overflow; + } + + ret = (b->ptr[0] >> (7-b->endbit)) & 1; + + overflow: + + b->endbit++; + if(b->endbit > 7) { + b->endbit = 0; + b->ptr++; + b->endbyte++; + } + return ret; +} + +void +align_get_bits(GetBitContext *b) +{ + if(b->endbit) { + b->endbit = 0; + b->ptr++; + b->endbyte++; + } +} + +long +get_bits_count(GetBitContext *b) +{ + return (b->endbyte*8+b->endbit); +} + +int32_t +get_rice(GetBitContext *b, int rp) +{ + uint32_t j, k; + int32_t v; + + k = 0; + while(get_bits1(b)) + k++; + if(rp) { + j = get_bits(b, rp); + if(j & (1 << (rp-1))) + v = (k << (rp-1)) | (j & ((1 << (rp-1)) -1)); + else + v = -((k << (rp-1)) | j) - 1; + } else { + // special case for rice param == 0 + if(k & 1) + v = (-(int)k-1) >> 1; + else + v = k >> 1; + } + return v; +} Added: bitreader.h =================================================================== --- bitreader.h (rev 0) +++ bitreader.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,61 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * This file is derived from libvorbis. + * Copyright (c) 2002, Xiph.org Foundation + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bitreader.h + * Memory-based bitwise reader + */ + +#ifndef BITREADER_H +#define BITREADER_H + +#include <stdint.h> + +typedef struct { + long endbyte; + int endbit; + uint8_t *buffer; + uint8_t *ptr; + long storage; +} GetBitContext; + +extern void init_get_bits(GetBitContext *b, uint8_t *buf, int bits); + +extern void seek_bits(GetBitContext *b, int bitpos); + +extern void skip_bits(GetBitContext *b, int bits); + +extern void skip_bits1(GetBitContext *b); + +extern uint32_t look_bits(GetBitContext *b, int bits); + +extern uint32_t get_bits(GetBitContext *b, int bits); + +extern long get_bits1(GetBitContext *b); + +extern void align_get_bits(GetBitContext *b); + +extern long get_bits_count(GetBitContext *b); + +extern int32_t get_rice(GetBitContext *b, int rp); + +#endif /* BITREADER_H */ Added: bswap.h =================================================================== --- bswap.h (rev 0) +++ bswap.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,79 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * This file is based on FFmpeg/libavutil/bswap.h + * Copyright (c) 2006 Michael Niedermayer + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file bswap.h + * Byte swap + */ + +#ifndef BSWAP_H +#define BSWAP_H + +#include "common.h" + +#ifdef HAVE_BYTESWAP_H +#include <byteswap.h> +#else + +static inline uint16_t bswap_16(uint16_t x){ + return (x>>8) | (x<<8); +} + +static inline uint32_t bswap_32(uint32_t x){ + x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); + return (x>>16) | (x<<16); +} + +static inline uint64_t bswap_64(uint64_t x) +{ + union { + uint64_t ll; + uint32_t l[2]; + } w, r; + w.ll = x; + r.l[0] = bswap_32(w.l[1]); + r.l[1] = bswap_32(w.l[0]); + return r.ll; +} + +#endif /* !HAVE_BYTESWAP_H */ + +// be2me ... BigEndian to MachineEndian +// le2me ... LittleEndian to MachineEndian + +#ifdef WORDS_BIGENDIAN +#define be2me_16(x) (x) +#define be2me_32(x) (x) +#define be2me_64(x) (x) +#define le2me_16(x) bswap_16(x) +#define le2me_32(x) bswap_32(x) +#define le2me_64(x) bswap_64(x) +#else +#define be2me_16(x) bswap_16(x) +#define be2me_32(x) bswap_32(x) +#define be2me_64(x) bswap_64(x) +#define le2me_16(x) (x) +#define le2me_32(x) (x) +#define le2me_64(x) (x) +#endif + +#endif /* BSWAP_H */ Added: common.h =================================================================== --- common.h (rev 0) +++ common.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,120 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file common.h + * Common header file + */ + +#ifndef COMMON_H +#define COMMON_H + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include <math.h> + +#ifdef HAVE_INTTYPES_H +#include <inttypes.h> +#else +#if defined(_WIN32) && defined(_MSC_VER) + +// integer types +typedef __int8 int8_t; +typedef unsigned __int8 uint8_t; +typedef __int16 int16_t; +typedef unsigned __int16 uint16_t; +typedef __int32 int32_t; +typedef unsigned __int32 uint32_t; +typedef __int64 int64_t; +typedef unsigned __int64 uint64_t; + +// limits +#define INT8_MIN _I8_MIN +#define INT8_MAX _I8_MAX +#define UINT8_MAX _UI8_MAX +#define INT16_MIN _I16_MIN +#define INT16_MAX _I16_MAX +#define UINT16_MAX _UI16_MAX +#define INT32_MIN _I32_MIN +#define INT32_MAX _I32_MAX +#define UINT32_MAX _UI32_MAX +#define INT64_MIN _I64_MIN +#define INT64_MAX _I64_MAX +#define UINT64_MAX _UI64_MAX + +// fprintf macros +#define PRId8 "d" +#define PRIi8 "i" +#define PRIo8 "o" +#define PRIu8 "u" +#define PRIx8 "x" +#define PRIX8 "X" +#define PRId16 "hd" +#define PRIi16 "hi" +#define PRIo16 "ho" +#define PRIu16 "hu" +#define PRIx16 "hx" +#define PRIX16 "hX" +#define PRId32 "I32d" +#define PRIi32 "I32i" +#define PRIo32 "I32o" +#define PRIu32 "I32u" +#define PRIx32 "I32x" +#define PRIX32 "I32X" +#define PRId64 "I64d" +#define PRIi64 "I64i" +#define PRIo64 "I64o" +#define PRIu64 "I64u" +#define PRIx64 "I64x" +#define PRIX64 "I64X" + +#endif +#endif /* EMULATE_INTTYPES */ + +#if __GNUC__ && !__INTEL_COMPILER +#define ALIGN16(x) x __attribute__((aligned(16))) +#else +#if defined(_MSC_VER) || defined(__INTEL_COMPILER) +#define ALIGN16(x) __declspec(align(16)) x +#else +#define ALIGN16(x) x +#endif +#endif + +#ifdef _WIN32 +#define CDECL __cdecl +#ifdef _MSC_VER +#define inline __inline +#endif /* _MSC_VER */ +#else +#define CDECL +#endif + +#define LOG2(a) (log((a)) / log(2.0)) + +#define ABS(a) ((a) >= 0 ? (a) : (-(a))) +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#define MIN(a,b) ((a) > (b) ? (b) : (a)) +#define CLIP(x,min,max) MAX(MIN((x), (max)), (min)) + +#include "bswap.h" + +#endif /* COMMON_H */ Added: config.h =================================================================== --- config.h (rev 0) +++ config.h 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,2 @@ +#define HAVE_INTTYPES_H 1 +// #define WORDS_BIGENDIAN Added: config.mak =================================================================== --- config.mak (rev 0) +++ config.mak 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,17 @@ +# set these to your liking + +CC = gcc + +RM = rm -f + +MAKE = make + +DEBUG_CFLAGS = -g + +EXTRA_CFLAGS = -O3 -fomit-frame-pointer + +WARNING_CFLAGS = -Wall -pedantic -std=c99 + +CFLAGS = $(DEBUG_CFLAGS) $(EXTRA_CFLAGS) $(WARNING_CFLAGS) + +EXEEXT = Added: main.c =================================================================== --- main.c (rev 0) +++ main.c 2007-08-20 00:08:12 UTC (rev 2) @@ -0,0 +1,184 @@ +/* + * MPEG-4 Audio Lossless Coding (ALS) decoder + * Copyright (c) 2007 Justin Ruggles + * + * Decals is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * Decals is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with Decals; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file main.c + * commandline front-end + */ + +#include "common.h" + +#include <stdlib.h> +#include <stdio.h> + +#include "alsdec.h" + +static void +print_als_header(AlsDecodeContext *ctx) +{ + fprintf(stderr, "** ALS HEADER **\n"); + fprintf(stderr, "sample rate: %u\n", ctx->sample_rate); + fprintf(stderr, "sample count: %u\n", ctx->samples); + fprintf(stderr, "channels: %d\n", ctx->channels); + switch(ctx->file_type) { + case FILE_TYPE_RAW: fprintf(stderr, "source file type: raw\n"); break; + case FILE_TYPE_WAVE: fprintf(stderr, "source file type: wave\n"); break; + case FILE_TYPE_AIFF: fprintf(stderr, "source file type: aiff\n"); break; + } + fprintf(stderr, "bits-per-sample: %d\n", ctx->bps); + switch(ctx->sample_type) { + case SAMPLE_TYPE_INT: fprintf(stderr, "sample type: integer\n"); break; + case SAMPLE_TYPE_FLOAT: fprintf(stderr, "sample type: floating-point\n"); break; + } + switch(ctx->source_order) { + case SRC_ORDER_LE: fprintf(stderr, "source byte order: little-endian\n"); break; + case SRC_ORDER_BE: fprintf(stderr, "source byte order: big-endian\n"); break; + } + fprintf(stderr, "frame size: %d\n", ctx->frame_size); + fprintf(stderr, "frame count: %d\n", ctx->frames); + if(ctx->random_access) { + fprintf(stderr, "random access: yes\n"); + fprintf(stderr, " ra interval: %d\n", ctx->random_access); + switch(ctx->ra_location) { + case RA_LOCATION_FRAME: fprintf(stderr, " ra location: frames\n"); break; + case RA_LOCATION_HEADER: fprintf(stderr, " ra location: header\n"); break; + } + fprintf(stderr, " number of ra units: %d\n", ctx->ra_units); + if(ctx->ra_location == RA_LOCATION_HEADER) { + int i; + for(i=0; i<ctx->ra_units; i++) { + fprintf(stderr, " %04d : %u\n", i, ctx->ra_sizes[i]); + } + } + } else { + fprintf(stderr, "random access: no\n"); + } + fprintf(stderr, "adaptive pred order: %s\n", ctx->adapt_order?"yes":"no"); + fprintf(stderr, "coefficient table: %d\n", ctx->coef_table); + fprintf(stderr, "long-term prediction: %s\n", ctx->ltp?"yes":"no"); + fprintf(stderr, "%sprediction order: %d\n", ctx->adapt_order?"max ":"", + ctx->pred_order); + fprintf(stderr, "block switching: %s\n", ctx->blksw?"yes":"no"); + switch(ctx->coding_type) { + case CODING_TYPE_RICE: fprintf(stderr, "entropy coding type: rice\n"); break; + case CODING_TYPE_BGMC: fprintf(stderr, "entropy coding type: bgmc\n"); break; + } + fprintf(stderr, "entropy partitioning: %s\n", ctx->coding_part?"yes":"no"); + fprintf(stderr, "joint stereo: %s\n", ctx->joint_stereo?"yes":"no"); + fprintf(stderr, "multi-channel correlation: %s\n", ctx->mcc?"yes":"no"); + fprintf(stderr, "channel configuration: %s\n", ctx->ch_config?"yes":"no"); + fprintf(stderr, "channel reordering: %s\n", ctx->ch_reorder?"yes":"no"); + if(ctx->ch_reorder) { + int ch; + for(ch=0; ch<ctx->channels; ch++) { + fprintf(stderr, " %d -> %d\n", ch, ctx->ch_pos[ch]); + } + } + if(ctx->has_crc) fprintf(stderr, "CRC: 0x%08X\n", ctx->ref_crc); + else fprintf(stderr, "CRC: none\n"); + fprintf(stderr, "rls-lms prediction: %s\n", ctx->rlslms?"yes":"no"); + if(ctx->has_aux) fprintf(stderr, "auxiliary data: %d\n", ctx->aux_size); + else fprintf(stderr, "auxiliary data: none\n"); + fprintf(stderr, "header size: %d\n", ctx->header_size); + fprintf(stderr, "trailer size: %d\n", ctx->trailer_size); + fprintf(stderr, "\n"); +} + +int +main(int argc, char **argv) +{ + FILE *fp; + char *fname; + AlsDecodeContext ctx; + int err=0; + uint8_t *data=NULL; + int data_size; + uint8_t *buf=NULL; + int buf_size; + int sample_count=0; + + if(argc != 2) { + fprintf(stderr, "\nusage: decals input.als\n"); + return 0; + } + fname = argv[1]; + fp = fopen(fname, "rb"); + if(!fp) { + fprintf(stderr, "cannot open file: %s\n", fname); + return 1; + } + + err = als_decode_init(&ctx, fp); + switch(err) { + case ALS_ERROR_GENERAL: fprintf(stderr, "error reading ALS header\n"); break; + case ALS_ERROR_MEMORY: fprintf(stderr, "out-of-memory error\n"); break; + case ALS_ERROR_EOF: fprintf(stderr, "end-of-file error\n"); break; + } + if(err) { + goto cleanup; + } + print_als_header(&ctx); + + data = calloc(ctx.channels * ctx.frame_size, sizeof(int32_t)); + if(!data) { + fprintf(stderr, "out-of-memory error\n"); + goto cleanup; + } + + buf_size = 16384; + buf = calloc(buf_size, 1); + if(!buf) { + fprintf(stderr, "out-of-memory error\n"); + goto cleanup; + } + + + do { + int consumed = 0; + data_size = 0; + do { + err = fread(buf, 1, buf_size, fp); + if(err > 0) { + consumed = als_decode_frame(&ctx, data, &data_size, buf, err); + data_size /= (sizeof(int32_t) * ctx.channels); + //fprintf(stderr, "consumed = %d\n", consumed); + } + } while(err > 0 && data_size == 0); + if(err > 0) { + sample_count += data_size; + fprintf(stderr, "sample count: %d (+%d)\n", sample_count, data_size); + while(data_size > 0 && (!ctx.samples || sample_count < ctx.samples)) { + consumed = als_decode_frame(&ctx, data, &data_size, NULL, 0); + data_size /= (sizeof(int32_t) * ctx.channels); + //fprintf(stderr, "consumed = %d\n", consumed); + if(data_size > 0) { + sample_count += data_size; + fprintf(stderr, "sample count: %d (+%d)\n", sample_count, data_size); + } + } + } + } while(err > 0 && (!ctx.samples || sample_count < ctx.samples)); + +cleanup: + if(data) free(data); + if(buf) free(buf); + fclose(fp); + als_decode_close(&ctx); + return err; +} This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |