Mercurial > audlegacy-plugins
diff src/demac/ape.h @ 2182:cc5e9ec110a4
Added initial version of Monkey's Audio plugin
author | Eugene Zagidullin <e.asphyx@gmail.com> |
---|---|
date | Thu, 22 Nov 2007 02:54:06 +0300 |
parents | |
children | 80d7ab8f2ec5 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demac/ape.h Thu Nov 22 02:54:06 2007 +0300 @@ -0,0 +1,299 @@ +/* + * Monkey's Audio lossless audio decoder, common header, + * some libav* compatibility stuff + * Copyright (c) 2007 Benjamin Zores <ben@geexbox.org> + * based upon libdemac from Dave Chapman. + * Copyright (c) 2007 Eugene Zagidullin <e.asphyx@gmail.com> + * Cleanup libav* depending code, Audacious stuff. + * + * 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_H +#define APE_H + +#define FFMIN(a,b) ((a) < (b) ? (a) : (b)) + +#ifdef DEBUG +#define av_log(a, b, ...) fprintf(stderr, __VA_ARGS__) +#else +#define av_log(a, b, ...) ; +#endif + +#define MKTAG(a,b,c,d) (a | (b << 8) | (c << 16) | (d << 24)) +#define AV_TIME_BASE 1000 +#define AV_WL16(a,b) { \ + ((uint8_t*)(a))[0] = (uint16_t)(b) & 0x00ff; \ + ((uint8_t*)(a))[1] = ((uint16_t)(b) & 0xff00) >> 8; \ + } +#define AV_WL32(a,b) { \ + ((uint8_t*)(a))[0] = ((uint32_t)(b) & 0x000000ff); \ + ((uint8_t*)(a))[1] = ((uint32_t)(b) & 0x0000ff00) >> 8; \ + ((uint8_t*)(a))[2] = ((uint32_t)(b) & 0x00ff0000) >> 16; \ + ((uint8_t*)(a))[3] = ((uint32_t)(b) & 0xff000000) >> 24; \ + } + +#ifndef MAX +#define MAX(a,b) ((a) > (b) ? (a) : (b)) +#endif + +#define BLOCKS_PER_LOOP 4608 +#define MAX_CHANNELS 2 +//#define MAX_BYTESPERSAMPLE 3 + +#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 +/** Total size of all predictor histories */ +#define PREDICTOR_SIZE 50 + +#define YDELAYA (18 + PREDICTOR_ORDER*4) +#define YDELAYB (18 + PREDICTOR_ORDER*3) +#define XDELAYA (18 + PREDICTOR_ORDER*2) +#define XDELAYB (18 + PREDICTOR_ORDER) + +#define YADAPTCOEFFSA 18 +#define XADAPTCOEFFSA 14 +#define YADAPTCOEFFSB 10 +#define XADAPTCOEFFSB 5 + +#define APE_FILTER_LEVELS 3 + +#define AVERROR_IO -1 +#define AVERROR_NOMEM -1 + +typedef struct { + int64_t pos; + int nblocks; + int size; + int skip; + int64_t pts; +} APEFrame; + +typedef struct { + /* Derived fields */ + uint32_t junklength; + uint32_t firstframe; + uint32_t totalsamples; + int currentframe; + APEFrame *frames; + + /* 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; + + /* Added by Eugene: */ + uint32_t frame_size; + //uint64_t total_blocks; + uint64_t duration; + uint32_t max_packet_size; +} APEContext; + +/** Filters applied to the decoded data */ +typedef struct APEFilter { + int16_t *coeffs; ///< actual coefficients used in filtering + int16_t *adaptcoeffs; ///< adaptive filter coefficients used for correcting of actual filter coefficients + int16_t *historybuffer; ///< filter memory + int16_t *delay; ///< filtered values + + int avg; +} APEFilter; + +typedef struct APERice { + uint32_t k; + uint32_t ksum; +} APERice; + +typedef struct APERangecoder { + 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 +} APERangecoder; + +/** Filter histories */ +typedef struct APEPredictor { + int32_t *buf; + + int32_t lastA[2]; + + int32_t filterA[2]; + int32_t filterB[2]; + + int32_t coeffsA[2][4]; ///< adaption coefficients + int32_t coeffsB[2][5]; ///< adaption coefficients + int32_t historybuffer[HISTORY_SIZE + PREDICTOR_SIZE]; +} APEPredictor; + +/** Decoder context */ +typedef struct APEDecoderContext { + //AVCodecContext *avctx; + APEContext *apectx; + //DSPContext dsp; + int channels; + int samples; ///< samples left to decode in current frame + + int fileversion; ///< codec version, very important in decoding process + int compression_level; ///< compression levels + int fset; ///< which filter set to use (calculated from compression level) + int flags; ///< global decoder flags + + uint32_t CRC; ///< frame CRC + int frameflags; ///< frame flags + int currentframeblocks; ///< samples (per channel) in current frame + int blocksdecoded; ///< count of decoded samples in current frame + APEPredictor predictor; ///< predictor used for final reconstruction + + int32_t decoded0[BLOCKS_PER_LOOP]; ///< decoded data for the first channel + int32_t decoded1[BLOCKS_PER_LOOP]; ///< decoded data for the second channel + + int16_t* filterbuf[APE_FILTER_LEVELS]; ///< filter memory + + APERangecoder rc; ///< rangecoder used to decode actual values + APERice riceX; ///< rice code parameters for the second channel + APERice riceY; ///< rice code parameters for the first channel + APEFilter filters[APE_FILTER_LEVELS][2]; ///< filters used for reconstruction + + uint8_t *data; ///< current frame data + uint8_t *data_end; ///< frame data end + uint8_t *ptr; ///< current position in frame data + uint8_t *last_ptr; ///< position where last 4608-sample block ended + /*Eugene:*/ + unsigned int max_packet_size; // Avoid multiply realloc calls +} APEDecoderContext; + + +static inline uint8_t bytestream_get_byte(uint8_t** ptr) { + uint8_t tmp; + tmp = **ptr; + *ptr += 1; + return tmp; +} + +/*static inline uint32_t bytestream_get_be32(uint8_t** ptr) { + uint32_t tmp; + tmp = *((uint32_t*)*ptr); + *ptr += 4; + return tmp; +}*/ + +static inline uint32_t bytestream_get_be32(uint8_t** ptr) { + uint32_t tmp; + tmp = (*ptr)[3] | ((*ptr)[2] << 8) | ((*ptr)[1] << 16) | ((*ptr)[0] << 24); + *ptr += 4; + return tmp; +} + +static inline uint32_t bswap_32(uint32_t x) +{ +#if defined(ARCH_X86) +#if __CPU__ != 386 + __asm("bswap %0": + "=r" (x) : +#else + __asm("xchgb %b0,%h0\n" + " rorl $16,%0\n" + " xchgb %b0,%h0": + LEGACY_REGS (x) : +#endif + "0" (x)); +#elif defined(ARCH_SH4) + __asm__( + "swap.b %0,%0\n" + "swap.w %0,%0\n" + "swap.b %0,%0\n" + :"=r"(x):"0"(x)); +#elif defined(ARCH_ARM) + uint32_t t; + __asm__ ( + "eor %1, %0, %0, ror #16 \n\t" + "bic %1, %1, #0xFF0000 \n\t" + "mov %0, %0, ror #8 \n\t" + "eor %0, %0, %1, lsr #8 \n\t" + : "+r"(x), "+r"(t)); +#elif defined(ARCH_BFIN) + unsigned tmp; + asm("%1 = %0 >> 8 (V);\n\t" + "%0 = %0 << 8 (V);\n\t" + "%0 = %0 | %1;\n\t" + "%0 = PACK(%0.L, %0.H);\n\t" + : "+d"(x), "=&d"(tmp)); +#else + x= ((x<<8)&0xFF00FF00) | ((x>>8)&0x00FF00FF); + x= (x>>16) | (x<<16); +#endif + return x; +} + +static inline void bswap_buf(uint32_t *dst, uint32_t *src, int w){ + int i; + + for(i=0; i+8<=w; i+=8){ + dst[i+0]= bswap_32(src[i+0]); + dst[i+1]= bswap_32(src[i+1]); + dst[i+2]= bswap_32(src[i+2]); + dst[i+3]= bswap_32(src[i+3]); + dst[i+4]= bswap_32(src[i+4]); + dst[i+5]= bswap_32(src[i+5]); + dst[i+6]= bswap_32(src[i+6]); + dst[i+7]= bswap_32(src[i+7]); + } + for(;i<w; i++){ + dst[i+0]= bswap_32(src[i+0]); + } +} + +static inline int16_t av_clip_int16(int a) { + if ((a+32768) & ~65535) return (a>>31) ^ 32767; + else return a; +} + +int ape_read_header(APEContext *ape, VFSFile *pb, int probe_only); +int ape_read_packet(APEContext *ape, VFSFile *pb, uint8_t *pkt, int *pkt_size); +int ape_read_close(APEContext *ape); + +int ape_decode_init(APEDecoderContext *s, APEContext *ctx); +int ape_decode_frame(APEDecoderContext *s, + void *data, int *data_size, + uint8_t * buf, int buf_size); + +int ape_decode_close(APEDecoderContext *s); + +#endif // APE_H