summaryrefslogtreecommitdiffstats
path: root/lib/rbcodec/codecs
diff options
context:
space:
mode:
authorSean Bartell <wingedtachikoma@gmail.com>2011-06-25 21:32:25 -0400
committerNils Wallménius <nils@rockbox.org>2012-04-25 22:13:20 +0200
commitf40bfc9267b13b54e6379dfe7539447662879d24 (patch)
tree9b20069d5e62809ff434061ad730096836f916f2 /lib/rbcodec/codecs
parenta0009907de7a0107d49040d8a180f140e2eff299 (diff)
downloadrockbox-f40bfc9267b13b54e6379dfe7539447662879d24.tar.gz
rockbox-f40bfc9267b13b54e6379dfe7539447662879d24.zip
Add codecs to librbcodec.
Change-Id: Id7f4717d51ed02d67cb9f9cb3c0ada4a81843f97 Reviewed-on: http://gerrit.rockbox.org/137 Reviewed-by: Nils Wallménius <nils@rockbox.org> Tested-by: Nils Wallménius <nils@rockbox.org>
Diffstat (limited to 'lib/rbcodec/codecs')
-rw-r--r--lib/rbcodec/codecs/SOURCES54
-rw-r--r--lib/rbcodec/codecs/a52.c192
-rw-r--r--lib/rbcodec/codecs/a52_rm.c227
-rw-r--r--lib/rbcodec/codecs/aac.c297
-rw-r--r--lib/rbcodec/codecs/adx.c404
-rw-r--r--lib/rbcodec/codecs/aiff.c350
-rw-r--r--lib/rbcodec/codecs/aiff_enc.c400
-rw-r--r--lib/rbcodec/codecs/alac.c146
-rw-r--r--lib/rbcodec/codecs/ape.c330
-rw-r--r--lib/rbcodec/codecs/asap.c140
-rw-r--r--lib/rbcodec/codecs/atrac3_oma.c153
-rw-r--r--lib/rbcodec/codecs/atrac3_rm.c215
-rw-r--r--lib/rbcodec/codecs/au.c314
-rw-r--r--lib/rbcodec/codecs/ay.c137
-rw-r--r--lib/rbcodec/codecs/codec_crt0.c74
-rw-r--r--lib/rbcodec/codecs/codecs.h291
-rw-r--r--lib/rbcodec/codecs/codecs.make206
-rw-r--r--lib/rbcodec/codecs/cook.c202
-rw-r--r--lib/rbcodec/codecs/demac/COPYING339
-rw-r--r--lib/rbcodec/codecs/demac/Makefile42
-rw-r--r--lib/rbcodec/codecs/demac/README69
-rw-r--r--lib/rbcodec/codecs/demac/demac.c281
-rw-r--r--lib/rbcodec/codecs/demac/libdemac.make35
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/SOURCES15
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/crc.c120
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/decoder.c216
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/decoder.h40
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/demac.h45
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/demac_config.h145
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/entropy.c464
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/entropy.h40
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter.c296
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter.h50
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter_1280_15.c32
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter_16_11.c27
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter_256_13.c32
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter_32_10.c27
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/filter_64_11.c27
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/parser.c402
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/parser.h137
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/predictor-arm.S702
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/predictor-cf.S660
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/predictor.c271
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/predictor.h38
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/udiv32_arm-pre.S25
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/udiv32_arm.S318
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math16_armv5te.h404
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math16_armv6.h490
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math16_armv7.h214
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math16_cf.h364
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math16_mmx.h234
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math32_armv4.h201
-rw-r--r--lib/rbcodec/codecs/demac/libdemac/vector_math_generic.h160
-rw-r--r--lib/rbcodec/codecs/demac/wavwrite.c110
-rw-r--r--lib/rbcodec/codecs/demac/wavwrite.h32
-rw-r--r--lib/rbcodec/codecs/flac.c536
-rw-r--r--lib/rbcodec/codecs/gbs.c108
-rw-r--r--lib/rbcodec/codecs/hes.c108
-rw-r--r--lib/rbcodec/codecs/kss.c111
-rw-r--r--lib/rbcodec/codecs/lib/SOURCES12
-rw-r--r--lib/rbcodec/codecs/lib/asm_arm.h292
-rw-r--r--lib/rbcodec/codecs/lib/asm_mcf5249.h353
-rw-r--r--lib/rbcodec/codecs/lib/codeclib.c182
-rw-r--r--lib/rbcodec/codecs/lib/codeclib.h163
-rw-r--r--lib/rbcodec/codecs/lib/codeclib_misc.h310
-rw-r--r--lib/rbcodec/codecs/lib/ffmpeg_bitstream.c374
-rw-r--r--lib/rbcodec/codecs/lib/ffmpeg_bswap.h150
-rw-r--r--lib/rbcodec/codecs/lib/ffmpeg_get_bits.h743
-rw-r--r--lib/rbcodec/codecs/lib/ffmpeg_intreadwrite.h484
-rw-r--r--lib/rbcodec/codecs/lib/ffmpeg_put_bits.h323
-rw-r--r--lib/rbcodec/codecs/lib/fft-ffmpeg.c473
-rw-r--r--lib/rbcodec/codecs/lib/fft-ffmpeg_arm.h456
-rw-r--r--lib/rbcodec/codecs/lib/fft-ffmpeg_cf.h370
-rw-r--r--lib/rbcodec/codecs/lib/fft.h64
-rw-r--r--lib/rbcodec/codecs/lib/fixedpoint.c1
-rw-r--r--lib/rbcodec/codecs/lib/fixedpoint.h49
-rw-r--r--lib/rbcodec/codecs/lib/libcodec.make37
-rw-r--r--lib/rbcodec/codecs/lib/mdct.c644
-rw-r--r--lib/rbcodec/codecs/lib/mdct.h139
-rw-r--r--lib/rbcodec/codecs/lib/mdct_lookup.c872
-rw-r--r--lib/rbcodec/codecs/lib/mdct_lookup.h24
-rw-r--r--lib/rbcodec/codecs/lib/osx.dummy.c0
-rw-r--r--lib/rbcodec/codecs/liba52/AUTHORS23
-rw-r--r--lib/rbcodec/codecs/liba52/COPYING340
-rw-r--r--lib/rbcodec/codecs/liba52/ChangeLog97
-rw-r--r--lib/rbcodec/codecs/liba52/HISTORY28
-rw-r--r--lib/rbcodec/codecs/liba52/INSTALL58
-rw-r--r--lib/rbcodec/codecs/liba52/NEWS46
-rw-r--r--lib/rbcodec/codecs/liba52/README180
-rw-r--r--lib/rbcodec/codecs/liba52/README.rockbox27
-rw-r--r--lib/rbcodec/codecs/liba52/SOURCES5
-rw-r--r--lib/rbcodec/codecs/liba52/TODO17
-rw-r--r--lib/rbcodec/codecs/liba52/a52.h67
-rw-r--r--lib/rbcodec/codecs/liba52/a52_internal.h215
-rw-r--r--lib/rbcodec/codecs/liba52/attributes.h37
-rw-r--r--lib/rbcodec/codecs/liba52/bit_allocate.c265
-rw-r--r--lib/rbcodec/codecs/liba52/bitstream.c97
-rw-r--r--lib/rbcodec/codecs/liba52/bitstream.h54
-rw-r--r--lib/rbcodec/codecs/liba52/config-a52.h26
-rw-r--r--lib/rbcodec/codecs/liba52/downmix.c688
-rw-r--r--lib/rbcodec/codecs/liba52/imdct.c486
-rw-r--r--lib/rbcodec/codecs/liba52/imdct_lookups.h15
-rw-r--r--lib/rbcodec/codecs/liba52/liba52.make18
-rw-r--r--lib/rbcodec/codecs/liba52/mm_accel.h37
-rw-r--r--lib/rbcodec/codecs/liba52/parse.c956
-rw-r--r--lib/rbcodec/codecs/liba52/tables.h246
-rw-r--r--lib/rbcodec/codecs/liba52/tendra.h35
-rw-r--r--lib/rbcodec/codecs/libalac/README43
-rw-r--r--lib/rbcodec/codecs/libalac/README.rockbox80
-rw-r--r--lib/rbcodec/codecs/libalac/SOURCES1
-rw-r--r--lib/rbcodec/codecs/libalac/alac.c1148
-rw-r--r--lib/rbcodec/codecs/libalac/decomp.h54
-rw-r--r--lib/rbcodec/codecs/libalac/libalac.make18
-rw-r--r--lib/rbcodec/codecs/libasap/CREDITS58
-rw-r--r--lib/rbcodec/codecs/libasap/README148
-rw-r--r--lib/rbcodec/codecs/libasap/README.rockbox22
-rw-r--r--lib/rbcodec/codecs/libasap/SOURCES3
-rw-r--r--lib/rbcodec/codecs/libasap/acpu.c1291
-rw-r--r--lib/rbcodec/codecs/libasap/anylang.h218
-rw-r--r--lib/rbcodec/codecs/libasap/apokeysnd.c599
-rw-r--r--lib/rbcodec/codecs/libasap/asap.c2273
-rw-r--r--lib/rbcodec/codecs/libasap/asap.h328
-rw-r--r--lib/rbcodec/codecs/libasap/asap_internal.h115
-rw-r--r--lib/rbcodec/codecs/libasap/libasap.make18
-rw-r--r--lib/rbcodec/codecs/libasap/players.h1386
-rw-r--r--lib/rbcodec/codecs/libasf/SOURCES1
-rw-r--r--lib/rbcodec/codecs/libasf/asf.c435
-rw-r--r--lib/rbcodec/codecs/libasf/asf.h49
-rw-r--r--lib/rbcodec/codecs/libasf/libasf.make18
-rw-r--r--lib/rbcodec/codecs/libatrac/README.rockbox30
-rw-r--r--lib/rbcodec/codecs/libatrac/SOURCES8
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3.c1293
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3.h114
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3_arm.S172
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3_armv5e.S163
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3data.h148
-rw-r--r--lib/rbcodec/codecs/libatrac/atrac3data_fixed.h108
-rw-r--r--lib/rbcodec/codecs/libatrac/fixp_math.h111
-rw-r--r--lib/rbcodec/codecs/libatrac/libatrac.make18
-rw-r--r--lib/rbcodec/codecs/libcook/README.rockbox47
-rw-r--r--lib/rbcodec/codecs/libcook/SOURCES2
-rw-r--r--lib/rbcodec/codecs/libcook/cook.c907
-rw-r--r--lib/rbcodec/codecs/libcook/cook.h131
-rw-r--r--lib/rbcodec/codecs/libcook/cook_fixpoint.h278
-rw-r--r--lib/rbcodec/codecs/libcook/cookdata.h493
-rw-r--r--lib/rbcodec/codecs/libcook/cookdata_fixpoint.h164
-rw-r--r--lib/rbcodec/codecs/libcook/libcook.make18
-rw-r--r--lib/rbcodec/codecs/libfaad/COPYING350
-rw-r--r--lib/rbcodec/codecs/libfaad/README122
-rw-r--r--lib/rbcodec/codecs/libfaad/README.rockbox19
-rw-r--r--lib/rbcodec/codecs/libfaad/SOURCES27
-rw-r--r--lib/rbcodec/codecs/libfaad/analysis.h49
-rw-r--r--lib/rbcodec/codecs/libfaad/bits.c208
-rw-r--r--lib/rbcodec/codecs/libfaad/bits.h381
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb.h142
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_1.h183
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_10.h309
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_11.h412
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_2.h182
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_3.h193
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_4.h196
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_5.h193
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_6.h179
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_7.h159
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_8.h170
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_9.h369
-rw-r--r--lib/rbcodec/codecs/libfaad/codebook/hcb_sf.h273
-rw-r--r--lib/rbcodec/codecs/libfaad/common.c440
-rw-r--r--lib/rbcodec/codecs/libfaad/common.h475
-rw-r--r--lib/rbcodec/codecs/libfaad/decoder.c1029
-rw-r--r--lib/rbcodec/codecs/libfaad/decoder.h112
-rw-r--r--lib/rbcodec/codecs/libfaad/drc.c168
-rw-r--r--lib/rbcodec/codecs/libfaad/drc.h45
-rw-r--r--lib/rbcodec/codecs/libfaad/drm_dec.c992
-rw-r--r--lib/rbcodec/codecs/libfaad/drm_dec.h98
-rw-r--r--lib/rbcodec/codecs/libfaad/error.c62
-rw-r--r--lib/rbcodec/codecs/libfaad/error.h41
-rw-r--r--lib/rbcodec/codecs/libfaad/faad_config.h120
-rw-r--r--lib/rbcodec/codecs/libfaad/filtbank.c482
-rw-r--r--lib/rbcodec/codecs/libfaad/filtbank.h54
-rw-r--r--lib/rbcodec/codecs/libfaad/fixed.h230
-rw-r--r--lib/rbcodec/codecs/libfaad/hcr.c409
-rw-r--r--lib/rbcodec/codecs/libfaad/huffman.c563
-rw-r--r--lib/rbcodec/codecs/libfaad/huffman.h44
-rw-r--r--lib/rbcodec/codecs/libfaad/ic_predict.c267
-rw-r--r--lib/rbcodec/codecs/libfaad/ic_predict.h249
-rw-r--r--lib/rbcodec/codecs/libfaad/iq_table.h16455
-rw-r--r--lib/rbcodec/codecs/libfaad/is.c108
-rw-r--r--lib/rbcodec/codecs/libfaad/is.h64
-rw-r--r--lib/rbcodec/codecs/libfaad/kbd_win.h2294
-rw-r--r--lib/rbcodec/codecs/libfaad/libfaad.make19
-rw-r--r--lib/rbcodec/codecs/libfaad/lt_predict.c215
-rw-r--r--lib/rbcodec/codecs/libfaad/lt_predict.h63
-rw-r--r--lib/rbcodec/codecs/libfaad/mp4.c300
-rw-r--r--lib/rbcodec/codecs/libfaad/mp4.h51
-rw-r--r--lib/rbcodec/codecs/libfaad/ms.c73
-rw-r--r--lib/rbcodec/codecs/libfaad/ms.h41
-rw-r--r--lib/rbcodec/codecs/libfaad/output.c557
-rw-r--r--lib/rbcodec/codecs/libfaad/output.h45
-rw-r--r--lib/rbcodec/codecs/libfaad/pns.c263
-rw-r--r--lib/rbcodec/codecs/libfaad/pns.h53
-rw-r--r--lib/rbcodec/codecs/libfaad/ps_dec.c1938
-rw-r--r--lib/rbcodec/codecs/libfaad/ps_dec.h162
-rw-r--r--lib/rbcodec/codecs/libfaad/ps_syntax.c546
-rw-r--r--lib/rbcodec/codecs/libfaad/ps_tables.h547
-rw-r--r--lib/rbcodec/codecs/libfaad/pulse.c56
-rw-r--r--lib/rbcodec/codecs/libfaad/pulse.h40
-rw-r--r--lib/rbcodec/codecs/libfaad/rvlc.c530
-rw-r--r--lib/rbcodec/codecs/libfaad/rvlc.h53
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_dct.c1990
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_dct.h49
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_dec.c597
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_dec.h242
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_e_nf.c507
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_e_nf.h47
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_fbt.c762
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_fbt.h52
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_hfadj.c1631
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_hfadj.h54
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_hfgen.c539
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_hfgen.h47
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_huff.c357
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_huff.h43
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_noise.h561
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_qmf.c561
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_qmf.h47
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_qmf_c.h172
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_syntax.c868
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_syntax.h64
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_tf_grid.c259
-rw-r--r--lib/rbcodec/codecs/libfaad/sbr_tf_grid.h44
-rw-r--r--lib/rbcodec/codecs/libfaad/sine_win.h4301
-rw-r--r--lib/rbcodec/codecs/libfaad/specrec.c1092
-rw-r--r--lib/rbcodec/codecs/libfaad/specrec.h46
-rw-r--r--lib/rbcodec/codecs/libfaad/structs.h473
-rw-r--r--lib/rbcodec/codecs/libfaad/syntax.c2368
-rw-r--r--lib/rbcodec/codecs/libfaad/syntax.h124
-rw-r--r--lib/rbcodec/codecs/libfaad/tns.c312
-rw-r--r--lib/rbcodec/codecs/libfaad/tns.h48
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/COPYING504
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/README19
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/README.rockbox46
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/SOURCES7
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/arm.S271
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/arm.h8
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/bitstream.h79
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/coldfire.S535
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/coldfire.h11
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/decoder.c627
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/decoder.h49
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/golomb.h110
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/libffmpegFLAC.make18
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/shndec.c481
-rw-r--r--lib/rbcodec/codecs/libffmpegFLAC/shndec.h52
-rw-r--r--lib/rbcodec/codecs/libgme/2413tone.h20
-rw-r--r--lib/rbcodec/codecs/libgme/281btone.h20
-rw-r--r--lib/rbcodec/codecs/libgme/AYSOURCES7
-rw-r--r--lib/rbcodec/codecs/libgme/EMU2413SOURCES4
-rw-r--r--lib/rbcodec/codecs/libgme/GBSSOURCES9
-rw-r--r--lib/rbcodec/codecs/libgme/HESSOURCES8
-rw-r--r--lib/rbcodec/codecs/libgme/KSSSOURCES12
-rw-r--r--lib/rbcodec/codecs/libgme/NSFSOURCES15
-rw-r--r--lib/rbcodec/codecs/libgme/SGCSOURCES7
-rw-r--r--lib/rbcodec/codecs/libgme/VGMSOURCES10
-rw-r--r--lib/rbcodec/codecs/libgme/ay_apu.c413
-rw-r--r--lib/rbcodec/codecs/libgme/ay_apu.h79
-rw-r--r--lib/rbcodec/codecs/libgme/ay_cpu.c59
-rw-r--r--lib/rbcodec/codecs/libgme/ay_emu.c599
-rw-r--r--lib/rbcodec/codecs/libgme/ay_emu.h169
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_common.h160
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_config.h42
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_endian.h168
-rw-r--r--lib/rbcodec/codecs/libgme/blargg_source.h76
-rw-r--r--lib/rbcodec/codecs/libgme/blip_buffer.c225
-rw-r--r--lib/rbcodec/codecs/libgme/blip_buffer.h335
-rw-r--r--lib/rbcodec/codecs/libgme/emu2413.c1981
-rw-r--r--lib/rbcodec/codecs/libgme/emu2413.h164
-rw-r--r--lib/rbcodec/codecs/libgme/emu8950.c1206
-rw-r--r--lib/rbcodec/codecs/libgme/emu8950.h248
-rw-r--r--lib/rbcodec/codecs/libgme/emuadpcm.c297
-rw-r--r--lib/rbcodec/codecs/libgme/emuadpcm.h52
-rw-r--r--lib/rbcodec/codecs/libgme/emutables.h210
-rw-r--r--lib/rbcodec/codecs/libgme/emutypes.h41
-rw-r--r--lib/rbcodec/codecs/libgme/gb_apu.c410
-rw-r--r--lib/rbcodec/codecs/libgme/gb_apu.h85
-rw-r--r--lib/rbcodec/codecs/libgme/gb_cpu.c53
-rw-r--r--lib/rbcodec/codecs/libgme/gb_cpu.h80
-rw-r--r--lib/rbcodec/codecs/libgme/gb_cpu_run.h1187
-rw-r--r--lib/rbcodec/codecs/libgme/gb_oscs.c787
-rw-r--r--lib/rbcodec/codecs/libgme/gb_oscs.h187
-rw-r--r--lib/rbcodec/codecs/libgme/gbs_cpu.c120
-rw-r--r--lib/rbcodec/codecs/libgme/gbs_emu.c452
-rw-r--r--lib/rbcodec/codecs/libgme/gbs_emu.h192
-rw-r--r--lib/rbcodec/codecs/libgme/gme.h18
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu.c371
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu.h66
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu_adpcm.c297
-rw-r--r--lib/rbcodec/codecs/libgme/hes_apu_adpcm.h89
-rw-r--r--lib/rbcodec/codecs/libgme/hes_cpu.c121
-rw-r--r--lib/rbcodec/codecs/libgme/hes_cpu.h132
-rw-r--r--lib/rbcodec/codecs/libgme/hes_cpu_run.h1344
-rw-r--r--lib/rbcodec/codecs/libgme/hes_emu.c644
-rw-r--r--lib/rbcodec/codecs/libgme/hes_emu.h195
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/bbfuncs.c147
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/bbfuncs.h33
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/inflate.c1156
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/inflate.h30
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mallocer.c86
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mallocer.h16
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mbreader.c16
-rw-r--r--lib/rbcodec/codecs/libgme/inflate/mbreader.h15
-rw-r--r--lib/rbcodec/codecs/libgme/kss_cpu.c35
-rw-r--r--lib/rbcodec/codecs/libgme/kss_emu.c714
-rw-r--r--lib/rbcodec/codecs/libgme/kss_emu.h223
-rw-r--r--lib/rbcodec/codecs/libgme/kss_scc_apu.c166
-rw-r--r--lib/rbcodec/codecs/libgme/kss_scc_apu.h51
-rw-r--r--lib/rbcodec/codecs/libgme/libay.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libemu2413.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libgbs.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libhes.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libkss.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libnsf.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libsgc.make10
-rw-r--r--lib/rbcodec/codecs/libgme/libvgm.make10
-rw-r--r--lib/rbcodec/codecs/libgme/m3u_playlist.h31
-rw-r--r--lib/rbcodec/codecs/libgme/msxtypes.h36
-rw-r--r--lib/rbcodec/codecs/libgme/multi_buffer.c286
-rw-r--r--lib/rbcodec/codecs/libgme/multi_buffer.h114
-rw-r--r--lib/rbcodec/codecs/libgme/nes_apu.c397
-rw-r--r--lib/rbcodec/codecs/libgme/nes_apu.h137
-rw-r--r--lib/rbcodec/codecs/libgme/nes_cpu.c62
-rw-r--r--lib/rbcodec/codecs/libgme/nes_cpu.h109
-rw-r--r--lib/rbcodec/codecs/libgme/nes_cpu_run.h1122
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fds_apu.c291
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fds_apu.h116
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fme7_apu.c136
-rw-r--r--lib/rbcodec/codecs/libgme/nes_fme7_apu.h90
-rw-r--r--lib/rbcodec/codecs/libgme/nes_mmc5_apu.h61
-rw-r--r--lib/rbcodec/codecs/libgme/nes_namco_apu.c138
-rw-r--r--lib/rbcodec/codecs/libgme/nes_namco_apu.h71
-rw-r--r--lib/rbcodec/codecs/libgme/nes_oscs.c592
-rw-r--r--lib/rbcodec/codecs/libgme/nes_oscs.h164
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc6_apu.c192
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc6_apu.h62
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc7_apu.c88
-rw-r--r--lib/rbcodec/codecs/libgme/nes_vrc7_apu.h52
-rw-r--r--lib/rbcodec/codecs/libgme/nsf_cpu.c115
-rw-r--r--lib/rbcodec/codecs/libgme/nsf_emu.c921
-rw-r--r--lib/rbcodec/codecs/libgme/nsf_emu.h261
-rw-r--r--lib/rbcodec/codecs/libgme/nsfe_info.c272
-rw-r--r--lib/rbcodec/codecs/libgme/nsfe_info.h30
-rw-r--r--lib/rbcodec/codecs/libgme/opl_apu.c198
-rw-r--r--lib/rbcodec/codecs/libgme/opl_apu.h63
-rw-r--r--lib/rbcodec/codecs/libgme/opltables.h242
-rw-r--r--lib/rbcodec/codecs/libgme/resampler.c218
-rw-r--r--lib/rbcodec/codecs/libgme/resampler.h75
-rw-r--r--lib/rbcodec/codecs/libgme/rom_data.c68
-rw-r--r--lib/rbcodec/codecs/libgme/rom_data.h83
-rw-r--r--lib/rbcodec/codecs/libgme/sgc_cpu.c36
-rw-r--r--lib/rbcodec/codecs/libgme/sgc_emu.c480
-rw-r--r--lib/rbcodec/codecs/libgme/sgc_emu.h195
-rw-r--r--lib/rbcodec/codecs/libgme/sms_apu.c306
-rw-r--r--lib/rbcodec/codecs/libgme/sms_apu.h63
-rw-r--r--lib/rbcodec/codecs/libgme/sms_fm_apu.c82
-rw-r--r--lib/rbcodec/codecs/libgme/sms_fm_apu.h43
-rw-r--r--lib/rbcodec/codecs/libgme/track_filter.c294
-rw-r--r--lib/rbcodec/codecs/libgme/track_filter.h90
-rw-r--r--lib/rbcodec/codecs/libgme/vgm_emu.c858
-rw-r--r--lib/rbcodec/codecs/libgme/vgm_emu.h206
-rw-r--r--lib/rbcodec/codecs/libgme/vrc7tone.h20
-rw-r--r--lib/rbcodec/codecs/libgme/ym2413_emu.c45
-rw-r--r--lib/rbcodec/codecs/libgme/ym2413_emu.h61
-rw-r--r--lib/rbcodec/codecs/libgme/ym2612_emu.c1374
-rw-r--r--lib/rbcodec/codecs/libgme/ym2612_emu.h248
-rw-r--r--lib/rbcodec/codecs/libgme/ymtables.h559
-rw-r--r--lib/rbcodec/codecs/libgme/z80_cpu.c85
-rw-r--r--lib/rbcodec/codecs/libgme/z80_cpu.h116
-rw-r--r--lib/rbcodec/codecs/libgme/z80_cpu_run.h1696
-rw-r--r--lib/rbcodec/codecs/libm4a/SOURCES2
-rw-r--r--lib/rbcodec/codecs/libm4a/demux.c826
-rw-r--r--lib/rbcodec/codecs/libm4a/libm4a.make18
-rw-r--r--lib/rbcodec/codecs/libm4a/m4a.c267
-rw-r--r--lib/rbcodec/codecs/libm4a/m4a.h138
-rw-r--r--lib/rbcodec/codecs/libmad/CHANGES338
-rw-r--r--lib/rbcodec/codecs/libmad/COPYING340
-rw-r--r--lib/rbcodec/codecs/libmad/COPYRIGHT21
-rw-r--r--lib/rbcodec/codecs/libmad/CREDITS116
-rw-r--r--lib/rbcodec/codecs/libmad/D.dat607
-rw-r--r--lib/rbcodec/codecs/libmad/README241
-rw-r--r--lib/rbcodec/codecs/libmad/README.rockbox23
-rw-r--r--lib/rbcodec/codecs/libmad/SOURCES14
-rw-r--r--lib/rbcodec/codecs/libmad/TODO69
-rw-r--r--lib/rbcodec/codecs/libmad/VERSION7
-rw-r--r--lib/rbcodec/codecs/libmad/bit.c218
-rw-r--r--lib/rbcodec/codecs/libmad/bit.h50
-rw-r--r--lib/rbcodec/codecs/libmad/dct32_arm.S328
-rw-r--r--lib/rbcodec/codecs/libmad/fixed.h510
-rw-r--r--lib/rbcodec/codecs/libmad/frame.c499
-rw-r--r--lib/rbcodec/codecs/libmad/frame.h124
-rw-r--r--lib/rbcodec/codecs/libmad/global.h72
-rw-r--r--lib/rbcodec/codecs/libmad/huffman.c3109
-rw-r--r--lib/rbcodec/codecs/libmad/huffman.h66
-rw-r--r--lib/rbcodec/codecs/libmad/imdct_l_arm.S1001
-rw-r--r--lib/rbcodec/codecs/libmad/imdct_mcf5249.S124
-rw-r--r--lib/rbcodec/codecs/libmad/imdct_s.dat62
-rw-r--r--lib/rbcodec/codecs/libmad/layer12.c537
-rw-r--r--lib/rbcodec/codecs/libmad/layer12.h31
-rw-r--r--lib/rbcodec/codecs/libmad/layer3.c3107
-rw-r--r--lib/rbcodec/codecs/libmad/layer3.h30
-rw-r--r--lib/rbcodec/codecs/libmad/libmad.make66
-rw-r--r--lib/rbcodec/codecs/libmad/mad.h31
-rw-r--r--lib/rbcodec/codecs/libmad/mad_iram.h57
-rw-r--r--lib/rbcodec/codecs/libmad/qc_table.dat77
-rw-r--r--lib/rbcodec/codecs/libmad/rq_table.dat8747
-rw-r--r--lib/rbcodec/codecs/libmad/sf_table.dat106
-rw-r--r--lib/rbcodec/codecs/libmad/stream.c165
-rw-r--r--lib/rbcodec/codecs/libmad/stream.h113
-rw-r--r--lib/rbcodec/codecs/libmad/synth.c1232
-rw-r--r--lib/rbcodec/codecs/libmad/synth.h52
-rw-r--r--lib/rbcodec/codecs/libmad/synth_full_arm.S340
-rw-r--r--lib/rbcodec/codecs/libmusepack/AUTHORS10
-rw-r--r--lib/rbcodec/codecs/libmusepack/COPYING31
-rw-r--r--lib/rbcodec/codecs/libmusepack/ChangeLog40
-rw-r--r--lib/rbcodec/codecs/libmusepack/SOURCES14
-rw-r--r--lib/rbcodec/codecs/libmusepack/crc32.c57
-rw-r--r--lib/rbcodec/codecs/libmusepack/decoder.h101
-rw-r--r--lib/rbcodec/codecs/libmusepack/huffman.c530
-rw-r--r--lib/rbcodec/codecs/libmusepack/huffman.h83
-rw-r--r--lib/rbcodec/codecs/libmusepack/internal.h123
-rw-r--r--lib/rbcodec/codecs/libmusepack/libmusepack.make18
-rw-r--r--lib/rbcodec/codecs/libmusepack/minimax.h57
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpc_bits_reader.c181
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpc_bits_reader.h175
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpc_decoder.c767
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpc_demux.c730
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpc_types.h145
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpcdec.h212
-rw-r--r--lib/rbcodec/codecs/libmusepack/mpcdec_math.h231
-rw-r--r--lib/rbcodec/codecs/libmusepack/reader.h100
-rw-r--r--lib/rbcodec/codecs/libmusepack/requant.c184
-rw-r--r--lib/rbcodec/codecs/libmusepack/requant.h61
-rw-r--r--lib/rbcodec/codecs/libmusepack/streaminfo.c255
-rw-r--r--lib/rbcodec/codecs/libmusepack/streaminfo.h114
-rw-r--r--lib/rbcodec/codecs/libmusepack/synth_filter.c610
-rw-r--r--lib/rbcodec/codecs/libmusepack/synth_filter_arm.S693
-rw-r--r--lib/rbcodec/codecs/libmusepack/synth_filter_coldfire.S78
-rw-r--r--lib/rbcodec/codecs/libpcm/SOURCES11
-rw-r--r--lib/rbcodec/codecs/libpcm/adpcm_seek.c101
-rw-r--r--lib/rbcodec/codecs/libpcm/adpcm_seek.h39
-rw-r--r--lib/rbcodec/codecs/libpcm/dialogic_oki_adpcm.c183
-rw-r--r--lib/rbcodec/codecs/libpcm/dvi_adpcm.c308
-rw-r--r--lib/rbcodec/codecs/libpcm/ieee_float.c165
-rw-r--r--lib/rbcodec/codecs/libpcm/ima_adpcm_common.c171
-rw-r--r--lib/rbcodec/codecs/libpcm/ima_adpcm_common.h33
-rw-r--r--lib/rbcodec/codecs/libpcm/itut_g711.c204
-rw-r--r--lib/rbcodec/codecs/libpcm/libpcm.make18
-rw-r--r--lib/rbcodec/codecs/libpcm/linear_pcm.c294
-rw-r--r--lib/rbcodec/codecs/libpcm/ms_adpcm.c168
-rw-r--r--lib/rbcodec/codecs/libpcm/pcm_common.h190
-rw-r--r--lib/rbcodec/codecs/libpcm/qt_ima_adpcm.c138
-rw-r--r--lib/rbcodec/codecs/libpcm/support_formats.h55
-rw-r--r--lib/rbcodec/codecs/libpcm/swf_adpcm.c236
-rw-r--r--lib/rbcodec/codecs/libpcm/yamaha_adpcm.c250
-rw-r--r--lib/rbcodec/codecs/librm/SOURCES1
-rw-r--r--lib/rbcodec/codecs/librm/bytestream.h37
-rw-r--r--lib/rbcodec/codecs/librm/librm.make18
-rw-r--r--lib/rbcodec/codecs/librm/rm.c592
-rw-r--r--lib/rbcodec/codecs/librm/rm.h102
-rw-r--r--lib/rbcodec/codecs/libspc/SOURCES4
-rw-r--r--lib/rbcodec/codecs/libspc/libspc.make18
-rw-r--r--lib/rbcodec/codecs/libspc/spc_codec.h491
-rw-r--r--lib/rbcodec/codecs/libspc/spc_cpu.c1049
-rw-r--r--lib/rbcodec/codecs/libspc/spc_dsp.c1594
-rw-r--r--lib/rbcodec/codecs/libspc/spc_emu.c397
-rw-r--r--lib/rbcodec/codecs/libspc/spc_profiler.c66
-rw-r--r--lib/rbcodec/codecs/libspc/spc_profiler.h72
-rw-r--r--lib/rbcodec/codecs/libspeex/COPYING34
-rw-r--r--lib/rbcodec/codecs/libspeex/README.rockbox30
-rw-r--r--lib/rbcodec/codecs/libspeex/SOURCES45
-rw-r--r--lib/rbcodec/codecs/libspeex/_kiss_fft_guts.h166
-rw-r--r--lib/rbcodec/codecs/libspeex/arch.h242
-rw-r--r--lib/rbcodec/codecs/libspeex/bits.c399
-rw-r--r--lib/rbcodec/codecs/libspeex/cb_search.c621
-rw-r--r--lib/rbcodec/codecs/libspeex/cb_search.h103
-rw-r--r--lib/rbcodec/codecs/libspeex/cb_search_arm4.h137
-rw-r--r--lib/rbcodec/codecs/libspeex/cb_search_bfin.h112
-rw-r--r--lib/rbcodec/codecs/libspeex/cb_search_sse.h84
-rw-r--r--lib/rbcodec/codecs/libspeex/config-speex.h186
-rw-r--r--lib/rbcodec/codecs/libspeex/exc_10_16_table.c51
-rw-r--r--lib/rbcodec/codecs/libspeex/exc_10_32_table.c67
-rw-r--r--lib/rbcodec/codecs/libspeex/exc_20_32_table.c67
-rw-r--r--lib/rbcodec/codecs/libspeex/exc_5_256_table.c291
-rw-r--r--lib/rbcodec/codecs/libspeex/exc_5_64_table.c99
-rw-r--r--lib/rbcodec/codecs/libspeex/exc_8_128_table.c163
-rw-r--r--lib/rbcodec/codecs/libspeex/fftwrap.c288
-rw-r--r--lib/rbcodec/codecs/libspeex/fftwrap.h58
-rw-r--r--lib/rbcodec/codecs/libspeex/filterbank.c227
-rw-r--r--lib/rbcodec/codecs/libspeex/filterbank.h66
-rw-r--r--lib/rbcodec/codecs/libspeex/filters.c845
-rw-r--r--lib/rbcodec/codecs/libspeex/filters.h90
-rw-r--r--lib/rbcodec/codecs/libspeex/filters_arm4.S328
-rw-r--r--lib/rbcodec/codecs/libspeex/filters_arm4.h96
-rw-r--r--lib/rbcodec/codecs/libspeex/filters_bfin.h515
-rw-r--r--lib/rbcodec/codecs/libspeex/filters_cf.S356
-rw-r--r--lib/rbcodec/codecs/libspeex/filters_sse.h336
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_arm4.h148
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_arm5e.h178
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_bfin.h173
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_debug.h487
-rw-r--r--lib/rbcodec/codecs/libspeex/fixed_generic.h106
-rw-r--r--lib/rbcodec/codecs/libspeex/gain_table.c162
-rw-r--r--lib/rbcodec/codecs/libspeex/gain_table_lbr.c66
-rw-r--r--lib/rbcodec/codecs/libspeex/hexc_10_32_table.c68
-rw-r--r--lib/rbcodec/codecs/libspeex/hexc_table.c164
-rw-r--r--lib/rbcodec/codecs/libspeex/high_lsp_tables.c165
-rw-r--r--lib/rbcodec/codecs/libspeex/jitter.c839
-rw-r--r--lib/rbcodec/codecs/libspeex/kiss_fft.c523
-rw-r--r--lib/rbcodec/codecs/libspeex/kiss_fft.h108
-rw-r--r--lib/rbcodec/codecs/libspeex/kiss_fftr.c297
-rw-r--r--lib/rbcodec/codecs/libspeex/kiss_fftr.h51
-rw-r--r--lib/rbcodec/codecs/libspeex/libspeex.make66
-rw-r--r--lib/rbcodec/codecs/libspeex/lpc.c201
-rw-r--r--lib/rbcodec/codecs/libspeex/lpc.h53
-rw-r--r--lib/rbcodec/codecs/libspeex/lpc_bfin.h131
-rw-r--r--lib/rbcodec/codecs/libspeex/lsp.c661
-rw-r--r--lib/rbcodec/codecs/libspeex/lsp.h64
-rw-r--r--lib/rbcodec/codecs/libspeex/lsp_bfin.h89
-rw-r--r--lib/rbcodec/codecs/libspeex/lsp_tables_nb.c362
-rw-r--r--lib/rbcodec/codecs/libspeex/ltp.c856
-rw-r--r--lib/rbcodec/codecs/libspeex/ltp.h141
-rw-r--r--lib/rbcodec/codecs/libspeex/ltp_arm4.h188
-rw-r--r--lib/rbcodec/codecs/libspeex/ltp_bfin.h419
-rw-r--r--lib/rbcodec/codecs/libspeex/ltp_cf.S85
-rw-r--r--lib/rbcodec/codecs/libspeex/ltp_sse.h92
-rw-r--r--lib/rbcodec/codecs/libspeex/math_approx.h332
-rw-r--r--lib/rbcodec/codecs/libspeex/mdf.c1177
-rw-r--r--lib/rbcodec/codecs/libspeex/misc_bfin.h54
-rw-r--r--lib/rbcodec/codecs/libspeex/modes.c484
-rw-r--r--lib/rbcodec/codecs/libspeex/modes.h161
-rw-r--r--lib/rbcodec/codecs/libspeex/modes_wb.c374
-rw-r--r--lib/rbcodec/codecs/libspeex/nb_celp.c1917
-rw-r--r--lib/rbcodec/codecs/libspeex/nb_celp.h205
-rw-r--r--lib/rbcodec/codecs/libspeex/oggframing.c909
-rw-r--r--lib/rbcodec/codecs/libspeex/os_support.h165
-rw-r--r--lib/rbcodec/codecs/libspeex/preprocess.c1185
-rw-r--r--lib/rbcodec/codecs/libspeex/pseudofloat.h382
-rw-r--r--lib/rbcodec/codecs/libspeex/quant_lsp.c391
-rw-r--r--lib/rbcodec/codecs/libspeex/quant_lsp.h74
-rw-r--r--lib/rbcodec/codecs/libspeex/quant_lsp_bfin.h165
-rw-r--r--lib/rbcodec/codecs/libspeex/resample.c1140
-rw-r--r--lib/rbcodec/codecs/libspeex/rockbox.h119
-rw-r--r--lib/rbcodec/codecs/libspeex/sb_celp.c1510
-rw-r--r--lib/rbcodec/codecs/libspeex/sb_celp.h160
-rw-r--r--lib/rbcodec/codecs/libspeex/smallft.c1261
-rw-r--r--lib/rbcodec/codecs/libspeex/smallft.h46
-rw-r--r--lib/rbcodec/codecs/libspeex/speex.c252
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/ogg.h216
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex.h428
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_bits.h184
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_callbacks.h134
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_config_types.h13
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_echo.h123
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_header.h91
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_jitter.h197
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_preprocess.h190
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_resampler.h328
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_stereo.h91
-rw-r--r--lib/rbcodec/codecs/libspeex/speex/speex_types.h126
-rw-r--r--lib/rbcodec/codecs/libspeex/speex_callbacks.c160
-rw-r--r--lib/rbcodec/codecs/libspeex/speex_header.c188
-rw-r--r--lib/rbcodec/codecs/libspeex/stack_alloc.h130
-rw-r--r--lib/rbcodec/codecs/libspeex/stereo.c302
-rw-r--r--lib/rbcodec/codecs/libspeex/vbr.c275
-rw-r--r--lib/rbcodec/codecs/libspeex/vbr.h70
-rw-r--r--lib/rbcodec/codecs/libspeex/vorbis_psy.c508
-rw-r--r--lib/rbcodec/codecs/libspeex/vorbis_psy.h97
-rw-r--r--lib/rbcodec/codecs/libspeex/vq.c147
-rw-r--r--lib/rbcodec/codecs/libspeex/vq.h54
-rw-r--r--lib/rbcodec/codecs/libspeex/vq_arm4.h115
-rw-r--r--lib/rbcodec/codecs/libspeex/vq_bfin.h107
-rw-r--r--lib/rbcodec/codecs/libspeex/vq_sse.h120
-rw-r--r--lib/rbcodec/codecs/libspeex/window.c102
-rw-r--r--lib/rbcodec/codecs/libtremor/CHANGELOG19
-rw-r--r--lib/rbcodec/codecs/libtremor/COPYING28
-rw-r--r--lib/rbcodec/codecs/libtremor/README46
-rw-r--r--lib/rbcodec/codecs/libtremor/README.rockbox17
-rw-r--r--lib/rbcodec/codecs/libtremor/SOURCES16
-rw-r--r--lib/rbcodec/codecs/libtremor/asm_arm.h190
-rw-r--r--lib/rbcodec/codecs/libtremor/asm_mcf5249.h85
-rw-r--r--lib/rbcodec/codecs/libtremor/backends.h133
-rw-r--r--lib/rbcodec/codecs/libtremor/bitwise.c867
-rw-r--r--lib/rbcodec/codecs/libtremor/block.c471
-rw-r--r--lib/rbcodec/codecs/libtremor/codebook.c587
-rw-r--r--lib/rbcodec/codecs/libtremor/codebook.h101
-rw-r--r--lib/rbcodec/codecs/libtremor/codec_internal.h93
-rw-r--r--lib/rbcodec/codecs/libtremor/config-tremor.h55
-rw-r--r--lib/rbcodec/codecs/libtremor/config_types.h25
-rw-r--r--lib/rbcodec/codecs/libtremor/ctype.c4
-rw-r--r--lib/rbcodec/codecs/libtremor/ffmpeg_stuff.h140
-rw-r--r--lib/rbcodec/codecs/libtremor/floor0.c444
-rw-r--r--lib/rbcodec/codecs/libtremor/floor1.c426
-rw-r--r--lib/rbcodec/codecs/libtremor/framing.c2102
-rw-r--r--lib/rbcodec/codecs/libtremor/info.c330
-rw-r--r--lib/rbcodec/codecs/libtremor/ivorbiscodec.h204
-rw-r--r--lib/rbcodec/codecs/libtremor/ivorbisfile.h131
-rw-r--r--lib/rbcodec/codecs/libtremor/libtremor.make18
-rw-r--r--lib/rbcodec/codecs/libtremor/lsp_lookup.h132
-rw-r--r--lib/rbcodec/codecs/libtremor/mapping0.c416
-rw-r--r--lib/rbcodec/codecs/libtremor/misc.h276
-rw-r--r--lib/rbcodec/codecs/libtremor/ogg.h282
-rw-r--r--lib/rbcodec/codecs/libtremor/oggmalloc.c86
-rw-r--r--lib/rbcodec/codecs/libtremor/os.h62
-rw-r--r--lib/rbcodec/codecs/libtremor/os_types.h58
-rw-r--r--lib/rbcodec/codecs/libtremor/registry.c50
-rw-r--r--lib/rbcodec/codecs/libtremor/registry.h40
-rw-r--r--lib/rbcodec/codecs/libtremor/res012.c374
-rw-r--r--lib/rbcodec/codecs/libtremor/sharedbook.c460
-rw-r--r--lib/rbcodec/codecs/libtremor/synthesis.c129
-rw-r--r--lib/rbcodec/codecs/libtremor/vorbisfile.c1671
-rw-r--r--lib/rbcodec/codecs/libtremor/window.c82
-rw-r--r--lib/rbcodec/codecs/libtremor/window.h27
-rw-r--r--lib/rbcodec/codecs/libtremor/window_lookup.h2087
-rw-r--r--lib/rbcodec/codecs/libtta/README72
-rw-r--r--lib/rbcodec/codecs/libtta/README.rockbox33
-rw-r--r--lib/rbcodec/codecs/libtta/SOURCES7
-rw-r--r--lib/rbcodec/codecs/libtta/filter.h136
-rw-r--r--lib/rbcodec/codecs/libtta/filter_arm.S198
-rw-r--r--lib/rbcodec/codecs/libtta/filter_coldfire.S164
-rw-r--r--lib/rbcodec/codecs/libtta/libtta.make18
-rw-r--r--lib/rbcodec/codecs/libtta/ttadec.c582
-rw-r--r--lib/rbcodec/codecs/libtta/ttadec.h203
-rw-r--r--lib/rbcodec/codecs/libtta/ttalib.h157
-rw-r--r--lib/rbcodec/codecs/libwavpack/LICENSE25
-rw-r--r--lib/rbcodec/codecs/libwavpack/README52
-rw-r--r--lib/rbcodec/codecs/libwavpack/README.rockbox15
-rw-r--r--lib/rbcodec/codecs/libwavpack/SOURCES15
-rw-r--r--lib/rbcodec/codecs/libwavpack/arm.S477
-rw-r--r--lib/rbcodec/codecs/libwavpack/arml.S506
-rw-r--r--lib/rbcodec/codecs/libwavpack/bits.c170
-rw-r--r--lib/rbcodec/codecs/libwavpack/coldfire.S537
-rw-r--r--lib/rbcodec/codecs/libwavpack/float.c47
-rw-r--r--lib/rbcodec/codecs/libwavpack/libwavpack.make18
-rw-r--r--lib/rbcodec/codecs/libwavpack/make.bat1
-rw-r--r--lib/rbcodec/codecs/libwavpack/metadata.c171
-rw-r--r--lib/rbcodec/codecs/libwavpack/pack.c470
-rw-r--r--lib/rbcodec/codecs/libwavpack/unpack.c780
-rw-r--r--lib/rbcodec/codecs/libwavpack/wavpack.h447
-rw-r--r--lib/rbcodec/codecs/libwavpack/words.c786
-rw-r--r--lib/rbcodec/codecs/libwavpack/wputils.c555
-rw-r--r--lib/rbcodec/codecs/libwma/SOURCES3
-rw-r--r--lib/rbcodec/codecs/libwma/libwma.make18
-rw-r--r--lib/rbcodec/codecs/libwma/types.h5
-rw-r--r--lib/rbcodec/codecs/libwma/wmadata.h2609
-rw-r--r--lib/rbcodec/codecs/libwma/wmadec.h181
-rw-r--r--lib/rbcodec/codecs/libwma/wmadeci.c1445
-rw-r--r--lib/rbcodec/codecs/libwma/wmafixed.c223
-rw-r--r--lib/rbcodec/codecs/libwma/wmafixed.h237
-rw-r--r--lib/rbcodec/codecs/libwmapro/README.rockbox20
-rw-r--r--lib/rbcodec/codecs/libwmapro/SOURCES4
-rw-r--r--lib/rbcodec/codecs/libwmapro/libwmapro.make18
-rw-r--r--lib/rbcodec/codecs/libwmapro/mdct_tables.c3391
-rw-r--r--lib/rbcodec/codecs/libwmapro/mdct_tables.h10
-rw-r--r--lib/rbcodec/codecs/libwmapro/quant.h53
-rw-r--r--lib/rbcodec/codecs/libwmapro/wma.c164
-rw-r--r--lib/rbcodec/codecs/libwmapro/wma.h75
-rw-r--r--lib/rbcodec/codecs/libwmapro/wmapro_math.h250
-rw-r--r--lib/rbcodec/codecs/libwmapro/wmaprodata.h615
-rw-r--r--lib/rbcodec/codecs/libwmapro/wmaprodec.c1626
-rw-r--r--lib/rbcodec/codecs/libwmapro/wmaprodec.h44
-rw-r--r--lib/rbcodec/codecs/libwmavoice/Makefile64
-rw-r--r--lib/rbcodec/codecs/libwmavoice/README.rockbox26
-rw-r--r--lib/rbcodec/codecs/libwmavoice/SOURCES17
-rw-r--r--lib/rbcodec/codecs/libwmavoice/acelp_filters.c145
-rw-r--r--lib/rbcodec/codecs/libwmavoice/acelp_filters.h120
-rw-r--r--lib/rbcodec/codecs/libwmavoice/acelp_vectors.c270
-rw-r--r--lib/rbcodec/codecs/libwmavoice/acelp_vectors.h264
-rw-r--r--lib/rbcodec/codecs/libwmavoice/avcodec.h4044
-rw-r--r--lib/rbcodec/codecs/libwmavoice/avfft.c142
-rw-r--r--lib/rbcodec/codecs/libwmavoice/avfft.h99
-rw-r--r--lib/rbcodec/codecs/libwmavoice/bitstream.c341
-rw-r--r--lib/rbcodec/codecs/libwmavoice/celp_filters.c210
-rw-r--r--lib/rbcodec/codecs/libwmavoice/celp_filters.h119
-rw-r--r--lib/rbcodec/codecs/libwmavoice/celp_math.c208
-rw-r--r--lib/rbcodec/codecs/libwmavoice/celp_math.h76
-rw-r--r--lib/rbcodec/codecs/libwmavoice/dct.c226
-rw-r--r--lib/rbcodec/codecs/libwmavoice/dct32.c267
-rw-r--r--lib/rbcodec/codecs/libwmavoice/fft.c298
-rw-r--r--lib/rbcodec/codecs/libwmavoice/fft.h244
-rw-r--r--lib/rbcodec/codecs/libwmavoice/get_bits.h691
-rw-r--r--lib/rbcodec/codecs/libwmavoice/internal.h53
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/attributes.h121
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/avutil.h89
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/bswap.h124
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/common.h346
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/internal.h234
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/intreadwrite.h522
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/log.c150
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/log.h138
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/lzo.c280
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/lzo.h66
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/mathematics.c183
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/mathematics.h112
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/mem.c176
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libavutil/mem.h126
-rw-r--r--lib/rbcodec/codecs/libwmavoice/libwmavoice.make37
-rw-r--r--lib/rbcodec/codecs/libwmavoice/lsp.c174
-rw-r--r--lib/rbcodec/codecs/libwmavoice/lsp.h120
-rw-r--r--lib/rbcodec/codecs/libwmavoice/mathops.h182
-rw-r--r--lib/rbcodec/codecs/libwmavoice/mdct.c234
-rw-r--r--lib/rbcodec/codecs/libwmavoice/mdct_tablegen.h60
-rw-r--r--lib/rbcodec/codecs/libwmavoice/put_bits.h343
-rw-r--r--lib/rbcodec/codecs/libwmavoice/rdft.c133
-rw-r--r--lib/rbcodec/codecs/libwmavoice/utils.c1188
-rw-r--r--lib/rbcodec/codecs/libwmavoice/wmavoice.c2060
-rw-r--r--lib/rbcodec/codecs/libwmavoice/wmavoice.h7
-rw-r--r--lib/rbcodec/codecs/libwmavoice/wmavoice_data.h3259
-rw-r--r--lib/rbcodec/codecs/libwmavoice/wmavoice_mainbuild.patch32
-rw-r--r--lib/rbcodec/codecs/mod.c1353
-rw-r--r--lib/rbcodec/codecs/mp3_enc.c2629
-rw-r--r--lib/rbcodec/codecs/mpa.c521
-rw-r--r--lib/rbcodec/codecs/mpc.c186
-rw-r--r--lib/rbcodec/codecs/nsf.c135
-rw-r--r--lib/rbcodec/codecs/raac.c212
-rw-r--r--lib/rbcodec/codecs/sgc.c123
-rw-r--r--lib/rbcodec/codecs/shorten.c164
-rw-r--r--lib/rbcodec/codecs/sid.c1340
-rw-r--r--lib/rbcodec/codecs/smaf.c492
-rw-r--r--lib/rbcodec/codecs/spc.c586
-rw-r--r--lib/rbcodec/codecs/speex.c583
-rw-r--r--lib/rbcodec/codecs/tta.c127
-rw-r--r--lib/rbcodec/codecs/vgm.c142
-rw-r--r--lib/rbcodec/codecs/vorbis.c263
-rw-r--r--lib/rbcodec/codecs/vox.c201
-rw-r--r--lib/rbcodec/codecs/wav.c437
-rw-r--r--lib/rbcodec/codecs/wav64.c441
-rw-r--r--lib/rbcodec/codecs/wav_enc.c386
-rw-r--r--lib/rbcodec/codecs/wavpack.c127
-rw-r--r--lib/rbcodec/codecs/wavpack_enc.c467
-rwxr-xr-xlib/rbcodec/codecs/wma.c196
-rw-r--r--lib/rbcodec/codecs/wmapro.c152
-rw-r--r--lib/rbcodec/codecs/wmavoice.c195
741 files changed, 247480 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/SOURCES b/lib/rbcodec/codecs/SOURCES
new file mode 100644
index 0000000000..db6e82c75f
--- /dev/null
+++ b/lib/rbcodec/codecs/SOURCES
@@ -0,0 +1,54 @@
+/* decoders */
+
+vorbis.c
+mpa.c
+flac.c
+wav.c
+a52.c
+wavpack.c
+#ifndef RB_PROFILE
+alac.c
+#endif
+cook.c
+raac.c
+a52_rm.c
+atrac3_rm.c
+atrac3_oma.c
+mpc.c
+wma.c
+sid.c
+ape.c
+asap.c
+aac.c
+spc.c
+mod.c
+shorten.c
+aiff.c
+speex.c
+adx.c
+smaf.c
+au.c
+vox.c
+wav64.c
+tta.c
+wmapro.c
+ay.c
+gbs.c
+hes.c
+nsf.c
+sgc.c
+vgm.c
+#if MEMORYSIZE > 2
+kss.c
+#endif
+
+#ifdef HAVE_RECORDING
+
+/* encoders */
+
+aiff_enc.c
+mp3_enc.c
+wav_enc.c
+wavpack_enc.c
+
+#endif /* HAVE_RECORDING */
diff --git a/lib/rbcodec/codecs/a52.c b/lib/rbcodec/codecs/a52.c
new file mode 100644
index 0000000000..cb6e66dd05
--- /dev/null
+++ b/lib/rbcodec/codecs/a52.c
@@ -0,0 +1,192 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Dave Chapman
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include <inttypes.h> /* Needed by a52.h */
+#include <codecs/liba52/config-a52.h>
+#include <codecs/liba52/a52.h>
+
+CODEC_HEADER
+
+#define BUFFER_SIZE 4096
+
+#define A52_SAMPLESPERFRAME (6*256)
+
+static a52_state_t *state;
+static unsigned long samplesdone;
+static unsigned long frequency;
+
+/* used outside liba52 */
+static uint8_t buf[3840] IBSS_ATTR;
+
+static inline void output_audio(sample_t *samples)
+{
+ ci->yield();
+ ci->pcmbuf_insert(&samples[0], &samples[256], 256);
+}
+
+static void a52_decode_data(uint8_t *start, uint8_t *end)
+{
+ static uint8_t *bufptr = buf;
+ static uint8_t *bufpos = buf + 7;
+ /*
+ * sample_rate and flags are static because this routine could
+ * exit between the a52_syncinfo() and the ao_setup(), and we want
+ * to have the same values when we get back !
+ */
+ static int sample_rate;
+ static int flags;
+ int bit_rate;
+ int len;
+
+ while (1) {
+ len = end - start;
+ if (!len)
+ break;
+ if (len > bufpos - bufptr)
+ len = bufpos - bufptr;
+ memcpy(bufptr, start, len);
+ bufptr += len;
+ start += len;
+ if (bufptr == bufpos) {
+ if (bufpos == buf + 7) {
+ int length;
+
+ length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
+ if (!length) {
+ //DEBUGF("skip\n");
+ for (bufptr = buf; bufptr < buf + 6; bufptr++)
+ bufptr[0] = bufptr[1];
+ continue;
+ }
+ bufpos = buf + length;
+ } else {
+ /* Unity gain is 1 << 26, and we want to end up on 28 bits
+ of precision instead of the default 30.
+ */
+ level_t level = 1 << 24;
+ sample_t bias = 0;
+ int i;
+
+ /* This is the configuration for the downmixing: */
+ flags = A52_STEREO | A52_ADJUST_LEVEL;
+
+ if (a52_frame(state, buf, &flags, &level, bias))
+ goto error;
+ a52_dynrng(state, NULL, NULL);
+ frequency = sample_rate;
+
+ /* An A52 frame consists of 6 blocks of 256 samples
+ So we decode and output them one block at a time */
+ for (i = 0; i < 6; i++) {
+ if (a52_block(state))
+ goto error;
+ output_audio(a52_samples(state));
+ samplesdone += 256;
+ }
+ ci->set_elapsed(samplesdone/(frequency/1000));
+ bufptr = buf;
+ bufpos = buf + 7;
+ continue;
+ error:
+ //logf("Error decoding A52 stream\n");
+ bufptr = buf;
+ bufpos = buf + 7;
+ }
+ }
+ }
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
+ }
+ else if (reason == CODEC_UNLOAD) {
+ if (state)
+ a52_free(state);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ size_t n;
+ unsigned char *filebuf;
+ int sample_loc;
+ intptr_t param;
+
+ if (codec_init())
+ return CODEC_ERROR;
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ codec_set_replaygain(ci->id3);
+
+ /* Intialise the A52 decoder and check for success */
+ state = a52_init(0);
+
+ samplesdone = 0;
+
+ /* The main decoding loop */
+ if (ci->id3->offset) {
+ if (ci->seek_buffer(ci->id3->offset)) {
+ samplesdone = (ci->id3->offset / ci->id3->bytesperframe) *
+ A52_SAMPLESPERFRAME;
+ ci->set_elapsed(samplesdone/(ci->id3->frequency / 1000));
+ }
+ }
+ else {
+ ci->seek_buffer(ci->id3->first_frame_offset);
+ ci->set_elapsed(0);
+ }
+
+ while (1) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ sample_loc = param/1000 * ci->id3->frequency;
+
+ if (ci->seek_buffer((sample_loc/A52_SAMPLESPERFRAME)*ci->id3->bytesperframe)) {
+ samplesdone = sample_loc;
+ ci->set_elapsed(samplesdone/(ci->id3->frequency/1000));
+ }
+ ci->seek_complete();
+ }
+
+ filebuf = ci->request_buffer(&n, BUFFER_SIZE);
+
+ if (n == 0) /* End of Stream */
+ break;
+
+ a52_decode_data(filebuf, filebuf + n);
+ ci->advance_buffer(n);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/a52_rm.c b/lib/rbcodec/codecs/a52_rm.c
new file mode 100644
index 0000000000..2db126f5b1
--- /dev/null
+++ b/lib/rbcodec/codecs/a52_rm.c
@@ -0,0 +1,227 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Mohamed Tarek
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include <codecs/librm/rm.h>
+#include <inttypes.h> /* Needed by a52.h */
+#include <codecs/liba52/config-a52.h>
+#include <codecs/liba52/a52.h>
+
+CODEC_HEADER
+
+#define BUFFER_SIZE 4096
+
+#define A52_SAMPLESPERFRAME (6*256)
+
+static a52_state_t *state;
+static unsigned long samplesdone;
+static unsigned long frequency;
+static RMContext rmctx;
+static RMPacket pkt;
+
+static void init_rm(RMContext *rmctx)
+{
+ memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
+}
+
+/* used outside liba52 */
+static uint8_t buf[3840] IBSS_ATTR;
+
+/* The following two functions, a52_decode_data and output_audio are taken from a52.c */
+static inline void output_audio(sample_t *samples)
+{
+ ci->yield();
+ ci->pcmbuf_insert(&samples[0], &samples[256], 256);
+}
+
+static void a52_decode_data(uint8_t *start, uint8_t *end)
+{
+ static uint8_t *bufptr = buf;
+ static uint8_t *bufpos = buf + 7;
+ /*
+ * sample_rate and flags are static because this routine could
+ * exit between the a52_syncinfo() and the ao_setup(), and we want
+ * to have the same values when we get back !
+ */
+ static int sample_rate;
+ static int flags;
+ int bit_rate;
+ int len;
+
+ while (1) {
+ len = end - start;
+ if (!len)
+ break;
+ if (len > bufpos - bufptr)
+ len = bufpos - bufptr;
+ memcpy(bufptr, start, len);
+ bufptr += len;
+ start += len;
+ if (bufptr == bufpos) {
+ if (bufpos == buf + 7) {
+ int length;
+
+ length = a52_syncinfo(buf, &flags, &sample_rate, &bit_rate);
+ if (!length) {
+ //DEBUGF("skip\n");
+ for (bufptr = buf; bufptr < buf + 6; bufptr++)
+ bufptr[0] = bufptr[1];
+ continue;
+ }
+ bufpos = buf + length;
+ } else {
+ /* Unity gain is 1 << 26, and we want to end up on 28 bits
+ of precision instead of the default 30.
+ */
+ level_t level = 1 << 24;
+ sample_t bias = 0;
+ int i;
+
+ /* This is the configuration for the downmixing: */
+ flags = A52_STEREO | A52_ADJUST_LEVEL;
+
+ if (a52_frame(state, buf, &flags, &level, bias))
+ goto error;
+ a52_dynrng(state, NULL, NULL);
+ frequency = sample_rate;
+
+ /* An A52 frame consists of 6 blocks of 256 samples
+ So we decode and output them one block at a time */
+ for (i = 0; i < 6; i++) {
+ if (a52_block(state))
+ goto error;
+ output_audio(a52_samples(state));
+ samplesdone += 256;
+ }
+ ci->set_elapsed(samplesdone/(frequency/1000));
+ bufptr = buf;
+ bufpos = buf + 7;
+ continue;
+ error:
+ //logf("Error decoding A52 stream\n");
+ bufptr = buf;
+ bufpos = buf + 7;
+ }
+ }
+ }
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 28);
+ }
+ else if (reason == CODEC_UNLOAD) {
+ if (state)
+ a52_free(state);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ size_t n;
+ uint8_t *filebuf;
+ int consumed, packet_offset;
+ int playback_on = -1;
+ size_t resume_offset;
+ intptr_t param;
+ enum codec_command_action action = CODEC_ACTION_NULL;
+
+ if (codec_init()) {
+ return CODEC_ERROR;
+ }
+
+ resume_offset = ci->id3->offset;
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ codec_set_replaygain(ci->id3);
+
+ ci->seek_buffer(ci->id3->first_frame_offset);
+
+ /* Intializations */
+ state = a52_init(0);
+ ci->memset(&rmctx,0,sizeof(RMContext));
+ ci->memset(&pkt,0,sizeof(RMPacket));
+ init_rm(&rmctx);
+
+ samplesdone = 0;
+
+ /* check for a mid-track resume and force a seek time accordingly */
+ if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
+ resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ /* put number of subpackets to skip in resume_offset */
+ resume_offset /= (rmctx.block_align + PACKET_HEADER_SIZE);
+ param = (int)resume_offset * ((rmctx.block_align * 8 * 1000)/rmctx.bit_rate);
+ action = CODEC_ACTION_SEEK_TIME;
+ }
+ else {
+ /* Seek to the first packet */
+ ci->set_elapsed(0);
+ ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE );
+ }
+
+ /* The main decoding loop */
+ while((unsigned)rmctx.audio_pkt_cnt < rmctx.nb_packets) {
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ packet_offset = param / ((rmctx.block_align*8*1000)/rmctx.bit_rate);
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE +
+ packet_offset*(rmctx.block_align + PACKET_HEADER_SIZE));
+ rmctx.audio_pkt_cnt = packet_offset;
+ samplesdone = (rmctx.sample_rate/1000 * param);
+ ci->set_elapsed(samplesdone/(frequency/1000));
+ ci->seek_complete();
+ }
+
+ action = CODEC_ACTION_NULL;
+
+ filebuf = ci->request_buffer(&n, rmctx.block_align + PACKET_HEADER_SIZE);
+ consumed = rm_get_packet(&filebuf, &rmctx, &pkt);
+
+ if(consumed < 0 && playback_on != 0) {
+ if(playback_on == -1) {
+ /* Error only if packet-parsing failed and playback hadn't started */
+ DEBUGF("rm_get_packet failed\n");
+ return CODEC_ERROR;
+ }
+ else {
+ break;
+ }
+ }
+
+ playback_on = 1;
+ a52_decode_data(filebuf, filebuf + rmctx.block_align);
+ ci->advance_buffer(pkt.length);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/aac.c b/lib/rbcodec/codecs/aac.c
new file mode 100644
index 0000000000..365dca804d
--- /dev/null
+++ b/lib/rbcodec/codecs/aac.c
@@ -0,0 +1,297 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Dave Chapman
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include "libm4a/m4a.h"
+#include "libfaad/common.h"
+#include "libfaad/structs.h"
+#include "libfaad/decoder.h"
+
+CODEC_HEADER
+
+/* The maximum buffer size handled by faad. 12 bytes are required by libfaad
+ * as headroom (see libfaad/bits.c). FAAD_BYTE_BUFFER_SIZE bytes are buffered
+ * for each frame. */
+#define FAAD_BYTE_BUFFER_SIZE (2048-12)
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 29);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ /* Note that when dealing with QuickTime/MPEG4 files, terminology is
+ * a bit confusing. Files with sound are split up in chunks, where
+ * each chunk contains one or more samples. Each sample in turn
+ * contains a number of "sound samples" (the kind you refer to with
+ * the sampling frequency).
+ */
+ size_t n;
+ demux_res_t demux_res;
+ stream_t input_stream;
+ uint32_t sound_samples_done;
+ uint32_t elapsed_time;
+ int file_offset;
+ int framelength;
+ int lead_trim = 0;
+ unsigned int frame_samples;
+ unsigned int i;
+ unsigned char* buffer;
+ NeAACDecFrameInfo frame_info;
+ NeAACDecHandle decoder;
+ int err;
+ uint32_t seek_idx = 0;
+ uint32_t s = 0;
+ uint32_t sbr_fac = 1;
+ unsigned char c = 0;
+ void *ret;
+ intptr_t param;
+ bool empty_first_frame = false;
+
+ /* Clean and initialize decoder structures */
+ memset(&demux_res , 0, sizeof(demux_res));
+ if (codec_init()) {
+ LOGF("FAAD: Codec init error\n");
+ return CODEC_ERROR;
+ }
+
+ file_offset = ci->id3->offset;
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ codec_set_replaygain(ci->id3);
+
+ stream_create(&input_stream,ci);
+
+ ci->seek_buffer(ci->id3->first_frame_offset);
+
+ /* if qtmovie_read returns successfully, the stream is up to
+ * the movie data, which can be used directly by the decoder */
+ if (!qtmovie_read(&input_stream, &demux_res)) {
+ LOGF("FAAD: File init error\n");
+ return CODEC_ERROR;
+ }
+
+ /* initialise the sound converter */
+ decoder = NeAACDecOpen();
+
+ if (!decoder) {
+ LOGF("FAAD: Decode open error\n");
+ return CODEC_ERROR;
+ }
+
+ NeAACDecConfigurationPtr conf = NeAACDecGetCurrentConfiguration(decoder);
+ conf->outputFormat = FAAD_FMT_24BIT; /* irrelevant, we don't convert */
+ NeAACDecSetConfiguration(decoder, conf);
+
+ err = NeAACDecInit2(decoder, demux_res.codecdata, demux_res.codecdata_len, &s, &c);
+ if (err) {
+ LOGF("FAAD: DecInit: %d, %d\n", err, decoder->object_type);
+ return CODEC_ERROR;
+ }
+
+#ifdef SBR_DEC
+ /* Check for need of special handling for seek/resume and elapsed time. */
+ if (ci->id3->needs_upsampling_correction) {
+ sbr_fac = 2;
+ } else {
+ sbr_fac = 1;
+ }
+#endif
+
+ i = 0;
+
+ if (file_offset > 0) {
+ /* Resume the desired (byte) position. Important: When resuming SBR
+ * upsampling files the resulting sound_samples_done must be expanded
+ * by a factor of 2. This is done via using sbr_fac. */
+ if (m4a_seek_raw(&demux_res, &input_stream, file_offset,
+ &sound_samples_done, (int*) &i)) {
+ sound_samples_done *= sbr_fac;
+ } else {
+ sound_samples_done = 0;
+ }
+ NeAACDecPostSeekReset(decoder, i);
+ } else {
+ sound_samples_done = 0;
+ }
+
+ elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
+ ci->set_elapsed(elapsed_time);
+
+ if (i == 0)
+ {
+ lead_trim = ci->id3->lead_trim;
+ }
+
+ /* The main decoding loop */
+ while (i < demux_res.num_sample_byte_sizes) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ /* Deal with any pending seek requests */
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* Seek to the desired time position. Important: When seeking in SBR
+ * upsampling files the seek_time must be divided by 2 when calling
+ * m4a_seek and the resulting sound_samples_done must be expanded
+ * by a factor 2. This is done via using sbr_fac. */
+ if (m4a_seek(&demux_res, &input_stream,
+ (param/10/sbr_fac)*(ci->id3->frequency/100),
+ &sound_samples_done, (int*) &i)) {
+ sound_samples_done *= sbr_fac;
+ elapsed_time = (sound_samples_done * 10) / (ci->id3->frequency / 100);
+ ci->set_elapsed(elapsed_time);
+ seek_idx = 0;
+
+ if (i == 0)
+ {
+ lead_trim = ci->id3->lead_trim;
+ }
+ }
+ NeAACDecPostSeekReset(decoder, i);
+ ci->seek_complete();
+ }
+
+ /* There can be gaps between chunks, so skip ahead if needed. It
+ * doesn't seem to happen much, but it probably means that a
+ * "proper" file can have chunks out of order. Why one would want
+ * that an good question (but files with gaps do exist, so who
+ * knows?), so we don't support that - for now, at least.
+ */
+ file_offset = m4a_check_sample_offset(&demux_res, i, &seek_idx);
+
+ if (file_offset > ci->curpos)
+ {
+ ci->advance_buffer(file_offset - ci->curpos);
+ }
+ else if (file_offset == 0)
+ {
+ LOGF("AAC: get_sample_offset error\n");
+ return CODEC_ERROR;
+ }
+
+ /* Request the required number of bytes from the input buffer */
+ buffer=ci->request_buffer(&n, FAAD_BYTE_BUFFER_SIZE);
+
+ /* Decode one block - returned samples will be host-endian */
+ ret = NeAACDecDecode(decoder, &frame_info, buffer, n);
+
+ /* NeAACDecDecode may sometimes return NULL without setting error. */
+ if (ret == NULL || frame_info.error > 0) {
+ LOGF("FAAD: decode error '%s'\n", NeAACDecGetErrorMessage(frame_info.error));
+ return CODEC_ERROR;
+ }
+
+ /* Advance codec buffer (no need to call set_offset because of this) */
+ ci->advance_buffer(frame_info.bytesconsumed);
+
+ /* Output the audio */
+ ci->yield();
+
+ frame_samples = frame_info.samples >> 1;
+
+ if (empty_first_frame)
+ {
+ /* Remove the first frame from lead_trim, under the assumption
+ * that it had the same size as this frame
+ */
+ empty_first_frame = false;
+ lead_trim -= frame_samples;
+
+ if (lead_trim < 0)
+ {
+ lead_trim = 0;
+ }
+ }
+
+ /* Gather number of samples for the decoded frame. */
+ framelength = frame_samples - lead_trim;
+
+ if (i == demux_res.num_sample_byte_sizes - 1)
+ {
+ // Size of the last frame
+ const uint32_t sample_duration = (demux_res.num_time_to_samples > 0) ?
+ demux_res.time_to_sample[demux_res.num_time_to_samples - 1].sample_duration :
+ frame_samples;
+
+ /* Currently limited to at most one frame of tail_trim.
+ * Seems to be enough.
+ */
+ if (ci->id3->tail_trim == 0 && sample_duration < frame_samples)
+ {
+ /* Subtract lead_trim just in case we decode a file with only
+ * one audio frame with actual data (lead_trim is usually zero
+ * here).
+ */
+ framelength = sample_duration - lead_trim;
+ }
+ else
+ {
+ framelength -= ci->id3->tail_trim;
+ }
+ }
+
+ if (framelength > 0)
+ {
+ ci->pcmbuf_insert(&decoder->time_out[0][lead_trim],
+ &decoder->time_out[1][lead_trim],
+ framelength);
+ sound_samples_done += framelength;
+ /* Update the elapsed-time indicator */
+ elapsed_time = ((uint64_t) sound_samples_done * 1000) /
+ ci->id3->frequency;
+ ci->set_elapsed(elapsed_time);
+ }
+
+ if (lead_trim > 0)
+ {
+ /* frame_info.samples can be 0 for frame 0. We still want to
+ * remove it from lead_trim, so do that during frame 1.
+ */
+ if (0 == i && 0 == frame_info.samples)
+ {
+ empty_first_frame = true;
+ }
+
+ lead_trim -= frame_samples;
+
+ if (lead_trim < 0)
+ {
+ lead_trim = 0;
+ }
+ }
+
+ ++i;
+ }
+
+ LOGF("AAC: Decoded %lu samples\n", (unsigned long)sound_samples_done);
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/adx.c b/lib/rbcodec/codecs/adx.c
new file mode 100644
index 0000000000..0c67fc8d6e
--- /dev/null
+++ b/lib/rbcodec/codecs/adx.c
@@ -0,0 +1,404 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * Copyright (C) 2006-2008 Adam Gashlin (hcs)
+ * Copyright (C) 2006 Jens Arnold
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <limits.h>
+#include "codeclib.h"
+#include "inttypes.h"
+#include "math.h"
+#include "lib/fixedpoint.h"
+
+CODEC_HEADER
+
+/* Maximum number of bytes to process in one iteration */
+#define WAV_CHUNK_SIZE (1024*2)
+
+/* Number of times to loop looped tracks when repeat is disabled */
+#define LOOP_TIMES 2
+
+/* Length of fade-out for looped tracks (milliseconds) */
+#define FADE_LENGTH 10000L
+
+/* Default high pass filter cutoff frequency is 500 Hz.
+ * Others can be set, but the default is nearly always used,
+ * and there is no way to determine if another was used, anyway.
+ */
+static const long cutoff = 500;
+
+static int16_t samples[WAV_CHUNK_SIZE] IBSS_ATTR;
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ /* we only render 16 bits */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ int channels;
+ int sampleswritten, i;
+ uint8_t *buf;
+ int32_t ch1_1, ch1_2, ch2_1, ch2_2; /* ADPCM history */
+ size_t n;
+ int endofstream; /* end of stream flag */
+ uint32_t avgbytespersec;
+ int looping; /* looping flag */
+ int loop_count; /* number of loops done so far */
+ int fade_count; /* countdown for fadeout */
+ int fade_frames; /* length of fade in frames */
+ off_t start_adr, end_adr; /* loop points */
+ off_t chanstart, bufoff;
+ /*long coef1=0x7298L,coef2=-0x3350L;*/
+ long coef1, coef2;
+ intptr_t param;
+
+ DEBUGF("ADX: next_track\n");
+ if (codec_init()) {
+ return CODEC_ERROR;
+ }
+ DEBUGF("ADX: after init\n");
+
+ /* init history */
+ ch1_1=ch1_2=ch2_1=ch2_2=0;
+
+ codec_set_replaygain(ci->id3);
+
+ /* Get header */
+ DEBUGF("ADX: request initial buffer\n");
+ ci->seek_buffer(0);
+ buf = ci->request_buffer(&n, 0x38);
+ if (!buf || n < 0x38) {
+ return CODEC_ERROR;
+ }
+ bufoff = 0;
+ DEBUGF("ADX: read size = %lx\n",(unsigned long)n);
+
+ /* Get file header for starting offset, channel count */
+
+ chanstart = ((buf[2] << 8) | buf[3]) + 4;
+ channels = buf[7];
+
+ /* useful for seeking and reporting current playback position */
+ avgbytespersec = ci->id3->frequency * 18 * channels / 32;
+ DEBUGF("avgbytespersec=%ld\n",(unsigned long)avgbytespersec);
+
+ /* calculate filter coefficients */
+
+ /**
+ * A simple table of these coefficients would be nice, but
+ * some very odd frequencies are used and if I'm going to
+ * interpolate I might as well just go all the way and
+ * calclate them precisely.
+ * Speed is not an issue as this only needs to be done once per file.
+ */
+ {
+ const int64_t big28 = 0x10000000LL;
+ const int64_t big32 = 0x100000000LL;
+ int64_t frequency = ci->id3->frequency;
+ int64_t phasemultiple = cutoff*big32/frequency;
+
+ long z;
+ int64_t a;
+ const int64_t b = (M_SQRT2*big28)-big28;
+ int64_t c;
+ int64_t d;
+
+ fp_sincos((unsigned long)phasemultiple,&z);
+
+ a = (M_SQRT2*big28) - (z >> 3);
+
+ /**
+ * In the long passed to fsqrt there are only 4 nonfractional bits,
+ * which is sufficient here, but this is the only reason why I don't
+ * use 32 fractional bits everywhere.
+ */
+ d = fp_sqrt((a+b)*(a-b)/big28,28);
+ c = (a-d)*big28/b;
+
+ coef1 = (c*8192) >> 28;
+ coef2 = (c*c/big28*-4096) >> 28;
+ DEBUGF("ADX: samprate=%ld ",(long)frequency);
+ DEBUGF("coef1 %04x ",(unsigned int)(coef1*4));
+ DEBUGF("coef2 %04x\n",(unsigned int)(coef2*-4));
+ }
+
+ /* Get loop data */
+
+ looping = 0; start_adr = 0; end_adr = 0;
+ if (!memcmp(buf+0x10,"\x01\xF4\x03",3)) {
+ /* Soul Calibur 2 style (type 03) */
+ DEBUGF("ADX: type 03 found\n");
+ /* check if header is too small for loop data */
+ if (chanstart-6 < 0x2c) looping=0;
+ else {
+ looping = (buf[0x18]) ||
+ (buf[0x19]) ||
+ (buf[0x1a]) ||
+ (buf[0x1b]);
+ end_adr = (buf[0x28]<<24) |
+ (buf[0x29]<<16) |
+ (buf[0x2a]<<8) |
+ (buf[0x2b]);
+
+ start_adr = (
+ (buf[0x1c]<<24) |
+ (buf[0x1d]<<16) |
+ (buf[0x1e]<<8) |
+ (buf[0x1f])
+ )/32*channels*18+chanstart;
+ }
+ } else if (!memcmp(buf+0x10,"\x01\xF4\x04",3)) {
+ /* Standard (type 04) */
+ DEBUGF("ADX: type 04 found\n");
+ /* check if header is too small for loop data */
+ if (chanstart-6 < 0x38) looping=0;
+ else {
+ looping = (buf[0x24]) ||
+ (buf[0x25]) ||
+ (buf[0x26]) ||
+ (buf[0x27]);
+ end_adr = (buf[0x34]<<24) |
+ (buf[0x35]<<16) |
+ (buf[0x36]<<8) |
+ buf[0x37];
+ start_adr = (
+ (buf[0x28]<<24) |
+ (buf[0x29]<<16) |
+ (buf[0x2a]<<8) |
+ (buf[0x2b])
+ )/32*channels*18+chanstart;
+ }
+ } else {
+ DEBUGF("ADX: error, couldn't determine ADX type\n");
+ return CODEC_ERROR;
+ }
+
+ /* is file using encryption */
+ if (buf[0x13]==0x08) {
+ DEBUGF("ADX: error, encrypted ADX not supported\n");
+ return false;
+ }
+
+ if (looping) {
+ DEBUGF("ADX: looped, start: %lx end: %lx\n",start_adr,end_adr);
+ } else {
+ DEBUGF("ADX: not looped\n");
+ }
+
+ /* advance to first frame */
+ DEBUGF("ADX: first frame at %lx\n",chanstart);
+ bufoff = chanstart;
+
+ /* get in position */
+ ci->seek_buffer(bufoff);
+ ci->set_elapsed(0);
+
+ /* setup pcm buffer format */
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ if (channels == 2) {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+ } else if (channels == 1) {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
+ } else {
+ DEBUGF("ADX CODEC_ERROR: more than 2 channels\n");
+ return CODEC_ERROR;
+ }
+
+ endofstream = 0;
+ loop_count = 0;
+ fade_count = -1; /* disable fade */
+ fade_frames = 1;
+
+ /* The main decoder loop */
+
+ while (!endofstream) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ /* do we need to loop? */
+ if (bufoff > end_adr-18*channels && looping) {
+ DEBUGF("ADX: loop!\n");
+ /* check for endless looping */
+ if (ci->loop_track()) {
+ loop_count=0;
+ fade_count = -1; /* disable fade */
+ } else {
+ /* otherwise start fade after LOOP_TIMES loops */
+ loop_count++;
+ if (loop_count >= LOOP_TIMES && fade_count < 0) {
+ /* frames to fade over */
+ fade_frames = FADE_LENGTH*ci->id3->frequency/32/1000;
+ /* volume relative to fade_frames */
+ fade_count = fade_frames;
+ DEBUGF("ADX: fade_frames = %d\n",fade_frames);
+ }
+ }
+ bufoff = start_adr;
+ ci->seek_buffer(bufoff);
+ }
+
+ /* do we need to seek? */
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ uint32_t newpos;
+
+ DEBUGF("ADX: seek to %ldms\n", (long)param);
+
+ endofstream = 0;
+ loop_count = 0;
+ fade_count = -1; /* disable fade */
+ fade_frames = 1;
+
+ newpos = (((uint64_t)avgbytespersec*param)
+ / (1000LL*18*channels))*(18*channels);
+ bufoff = chanstart + newpos;
+ while (bufoff > end_adr-18*channels) {
+ bufoff-=end_adr-start_adr;
+ loop_count++;
+ }
+ ci->seek_buffer(bufoff);
+
+ ci->set_elapsed(
+ ((end_adr-start_adr)*loop_count + bufoff-chanstart)*
+ 1000LL/avgbytespersec);
+
+ ci->seek_complete();
+ }
+
+ if (bufoff>ci->filesize-channels*18) break; /* End of stream */
+
+ sampleswritten=0;
+
+ while (
+ /* Is there data left in the file? */
+ (bufoff <= ci->filesize-(18*channels)) &&
+ /* Is there space in the output buffer? */
+ (sampleswritten <= WAV_CHUNK_SIZE-(32*channels)) &&
+ /* Should we be looping? */
+ ((!looping) || bufoff <= end_adr-18*channels))
+ {
+ /* decode first/only channel */
+ int32_t scale;
+ int32_t ch1_0, d;
+
+ /* fetch a frame */
+ buf = ci->request_buffer(&n, 18);
+
+ if (!buf || n!=18) {
+ DEBUGF("ADX: couldn't get buffer at %lx\n",
+ bufoff);
+ return CODEC_ERROR;
+ }
+
+ scale = ((buf[0] << 8) | (buf[1])) +1;
+
+ for (i = 2; i < 18; i++)
+ {
+ d = (buf[i] >> 4) & 15;
+ if (d & 8) d-= 16;
+ ch1_0 = d*scale + ((coef1*ch1_1 + coef2*ch1_2) >> 12);
+ if (ch1_0 > 32767) ch1_0 = 32767;
+ else if (ch1_0 < -32768) ch1_0 = -32768;
+ samples[sampleswritten] = ch1_0;
+ sampleswritten+=channels;
+ ch1_2 = ch1_1; ch1_1 = ch1_0;
+
+ d = buf[i] & 15;
+ if (d & 8) d -= 16;
+ ch1_0 = d*scale + ((coef1*ch1_1 + coef2*ch1_2) >> 12);
+ if (ch1_0 > 32767) ch1_0 = 32767;
+ else if (ch1_0 < -32768) ch1_0 = -32768;
+ samples[sampleswritten] = ch1_0;
+ sampleswritten+=channels;
+ ch1_2 = ch1_1; ch1_1 = ch1_0;
+ }
+ bufoff+=18;
+ ci->advance_buffer(18);
+
+ if (channels == 2) {
+ /* decode second channel */
+ int32_t scale;
+ int32_t ch2_0, d;
+
+ buf = ci->request_buffer(&n, 18);
+
+ if (!buf || n!=18) {
+ DEBUGF("ADX: couldn't get buffer at %lx\n",
+ bufoff);
+ return CODEC_ERROR;
+ }
+
+ scale = ((buf[0] << 8)|(buf[1]))+1;
+
+ sampleswritten-=63;
+
+ for (i = 2; i < 18; i++)
+ {
+ d = (buf[i] >> 4) & 15;
+ if (d & 8) d-= 16;
+ ch2_0 = d*scale + ((coef1*ch2_1 + coef2*ch2_2) >> 12);
+ if (ch2_0 > 32767) ch2_0 = 32767;
+ else if (ch2_0 < -32768) ch2_0 = -32768;
+ samples[sampleswritten] = ch2_0;
+ sampleswritten+=2;
+ ch2_2 = ch2_1; ch2_1 = ch2_0;
+
+ d = buf[i] & 15;
+ if (d & 8) d -= 16;
+ ch2_0 = d*scale + ((coef1*ch2_1 + coef2*ch2_2) >> 12);
+ if (ch2_0 > 32767) ch2_0 = 32767;
+ else if (ch2_0 < -32768) ch2_0 = -32768;
+ samples[sampleswritten] = ch2_0;
+ sampleswritten+=2;
+ ch2_2 = ch2_1; ch2_1 = ch2_0;
+ }
+ bufoff+=18;
+ ci->advance_buffer(18);
+ sampleswritten--; /* go back to first channel's next sample */
+ }
+
+ if (fade_count>0) {
+ fade_count--;
+ for (i=0;i<(channels==1?32:64);i++) samples[sampleswritten-i-1]=
+ ((int32_t)samples[sampleswritten-i-1])*fade_count/fade_frames;
+ if (fade_count==0) {endofstream=1; break;}
+ }
+ }
+
+ if (channels == 2)
+ sampleswritten >>= 1; /* make samples/channel */
+
+ ci->pcmbuf_insert(samples, NULL, sampleswritten);
+
+ ci->set_elapsed(
+ ((end_adr-start_adr)*loop_count + bufoff-chanstart)*
+ 1000LL/avgbytespersec);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/aiff.c b/lib/rbcodec/codecs/aiff.c
new file mode 100644
index 0000000000..333bcd0455
--- /dev/null
+++ b/lib/rbcodec/codecs/aiff.c
@@ -0,0 +1,350 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (c) 2005 Jvo Studer
+ * Copyright (c) 2009 Yoshihisa Uchida
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include "codecs/libpcm/support_formats.h"
+
+CODEC_HEADER
+
+#define FOURCC(c1, c2, c3, c4) \
+((((uint32_t)c1)<<24)|(((uint32_t)c2)<<16)|(((uint32_t)c3)<<8)|((uint32_t)c4))
+
+/* This codec supports the following AIFC compressionType formats */
+enum {
+ AIFC_FORMAT_PCM = FOURCC('N', 'O', 'N', 'E'), /* AIFC PCM Format (big endian) */
+ AIFC_FORMAT_ALAW = FOURCC('a', 'l', 'a', 'w'), /* AIFC ALaw compressed */
+ AIFC_FORMAT_MULAW = FOURCC('u', 'l', 'a', 'w'), /* AIFC uLaw compressed */
+ AIFC_FORMAT_IEEE_FLOAT32 = FOURCC('f', 'l', '3', '2'), /* AIFC IEEE float 32 bit */
+ AIFC_FORMAT_IEEE_FLOAT64 = FOURCC('f', 'l', '6', '4'), /* AIFC IEEE float 64 bit */
+ AIFC_FORMAT_QT_IMA_ADPCM = FOURCC('i', 'm', 'a', '4'), /* AIFC QuickTime IMA ADPCM */
+};
+
+static const struct pcm_entry pcm_codecs[] = {
+ { AIFC_FORMAT_PCM, get_linear_pcm_codec },
+ { AIFC_FORMAT_ALAW, get_itut_g711_alaw_codec },
+ { AIFC_FORMAT_MULAW, get_itut_g711_mulaw_codec },
+ { AIFC_FORMAT_IEEE_FLOAT32, get_ieee_float_codec },
+ { AIFC_FORMAT_IEEE_FLOAT64, get_ieee_float_codec },
+ { AIFC_FORMAT_QT_IMA_ADPCM, get_qt_ima_adpcm_codec },
+};
+
+#define PCM_SAMPLE_SIZE (1024*2)
+
+static int32_t samples[PCM_SAMPLE_SIZE] IBSS_ATTR;
+
+static const struct pcm_codec *get_codec(uint32_t formattag)
+{
+ unsigned i;
+ for (i = 0; i < sizeof(pcm_codecs)/sizeof(pcm_codecs[0]); i++)
+ if (pcm_codecs[i].format_tag == formattag)
+ return pcm_codecs[i].get_codec();
+
+ return NULL;
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ struct pcm_format format;
+ uint32_t bytesdone, decodedsamples;
+ /* rockbox: comment 'set but unused' variables
+ uint32_t num_sample_frames = 0;
+ */
+ size_t n;
+ int bufcount;
+ int endofstream;
+ unsigned char *buf;
+ uint8_t *aifbuf;
+ uint32_t offset2snd = 0;
+ off_t firstblockposn; /* position of the first block in file */
+ bool is_aifc = false;
+ const struct pcm_codec *codec;
+ uint32_t size;
+ intptr_t param;
+
+ if (codec_init()) {
+ return CODEC_ERROR;
+ }
+
+ codec_set_replaygain(ci->id3);
+
+ /* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ bytesdone = ci->id3->offset;
+
+ /* assume the AIFF header is less than 1024 bytes */
+ ci->seek_buffer(0);
+ buf = ci->request_buffer(&n, 1024);
+ if (n < 54) {
+ return CODEC_ERROR;
+ }
+
+ if (memcmp(buf, "FORM", 4) != 0)
+ {
+ DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[0]);
+ return CODEC_ERROR;
+ }
+ if (memcmp(&buf[8], "AIFF", 4) == 0)
+ is_aifc = false;
+ else if (memcmp(&buf[8], "AIFC", 4) == 0)
+ is_aifc = true;
+ else
+ {
+ DEBUGF("CODEC_ERROR: does not aiff format %4.4s\n", (char*)&buf[8]);
+ return CODEC_ERROR;
+ }
+
+ buf += 12;
+ n -= 12;
+
+ ci->memset(&format, 0, sizeof(struct pcm_format));
+ format.is_signed = true;
+ format.is_little_endian = false;
+
+ decodedsamples = 0;
+ codec = 0;
+
+ /* read until 'SSND' chunk, which typically is last */
+ while (format.numbytes == 0 && n >= 8)
+ {
+ /* chunkSize */
+ size = ((buf[4]<<24)|(buf[5]<<16)|(buf[6]<<8)|buf[7]);
+ if (memcmp(buf, "COMM", 4) == 0) {
+ if ((!is_aifc && size < 18) || (is_aifc && size < 22))
+ {
+ DEBUGF("CODEC_ERROR: 'COMM' chunk size=%lu < %d\n",
+ (unsigned long)size, (is_aifc)?22:18);
+ return CODEC_ERROR;
+ }
+ /* num_channels */
+ format.channels = ((buf[8]<<8)|buf[9]);
+ /* num_sample_frames */
+ /*
+ num_sample_frames = ((buf[10]<<24)|(buf[11]<<16)|(buf[12]<<8)
+ |buf[13]);
+ */
+
+ /* sample_size */
+ format.bitspersample = ((buf[14]<<8)|buf[15]);
+ /* sample_rate (don't use last 4 bytes, only integer fs) */
+ if (buf[16] != 0x40) {
+ DEBUGF("CODEC_ERROR: weird sampling rate (no @)\n");
+ return CODEC_ERROR;
+ }
+ format.samplespersec = ((buf[18]<<24)|(buf[19]<<16)|(buf[20]<<8)|buf[21])+1;
+ format.samplespersec >>= (16 + 14 - buf[17]);
+ /* compressionType (AIFC only) */
+ if (is_aifc)
+ {
+ format.formattag = (buf[26]<<24)|(buf[27]<<16)|(buf[28]<<8)|buf[29];
+
+ /*
+ * aiff's sample_size is uncompressed sound data size.
+ * But format.bitspersample is compressed sound data size.
+ */
+ if (format.formattag == AIFC_FORMAT_ALAW ||
+ format.formattag == AIFC_FORMAT_MULAW)
+ format.bitspersample = 8;
+ else if (format.formattag == AIFC_FORMAT_QT_IMA_ADPCM)
+ format.bitspersample = 4;
+ }
+ else
+ format.formattag = AIFC_FORMAT_PCM;
+ /* calc average bytes per second */
+ format.avgbytespersec = format.samplespersec*format.channels*format.bitspersample/8;
+ } else if (memcmp(buf, "SSND", 4)==0) {
+ if (format.bitspersample == 0) {
+ DEBUGF("CODEC_ERROR: unsupported chunk order\n");
+ return CODEC_ERROR;
+ }
+ /* offset2snd */
+ offset2snd = (buf[8]<<24)|(buf[9]<<16)|(buf[10]<<8)|buf[11];
+ /* block_size */
+ format.blockalign = ((buf[12]<<24)|(buf[13]<<16)|(buf[14]<<8)|buf[15]) >> 3;
+ if (format.blockalign == 0)
+ format.blockalign = format.channels * format.bitspersample >> 3;
+ format.numbytes = size - 8 - offset2snd;
+ size = 8 + offset2snd; /* advance to the beginning of data */
+ } else if (is_aifc && (memcmp(buf, "FVER", 4)==0)) {
+ /* Format Version Chunk (AIFC only chunk) */
+ /* skip this chunk */
+ } else {
+ DEBUGF("unsupported AIFF chunk: '%c%c%c%c', size=%lu\n",
+ buf[0], buf[1], buf[2], buf[3], (unsigned long)size);
+ }
+
+ size += 8 + (size & 0x01); /* odd chunk sizes must be padded */
+
+ buf += size;
+ if (n < size) {
+ DEBUGF("CODEC_ERROR: AIFF header size > 1024\n");
+ return CODEC_ERROR;
+ }
+ n -= size;
+ } /* while 'SSND' */
+
+ if (format.channels == 0) {
+ DEBUGF("CODEC_ERROR: 'COMM' chunk not found or 0-channels file\n");
+ return CODEC_ERROR;
+ }
+ if (format.numbytes == 0) {
+ DEBUGF("CODEC_ERROR: 'SSND' chunk not found or has zero length\n");
+ return CODEC_ERROR;
+ }
+
+ codec = get_codec(format.formattag);
+ if (codec == 0)
+ {
+ DEBUGF("CODEC_ERROR: AIFC does not support compressionType: 0x%x\n",
+ (unsigned int)format.formattag);
+ return CODEC_ERROR;
+ }
+
+ if (!codec->set_format(&format))
+ {
+ return CODEC_ERROR;
+ }
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+
+ if (format.channels == 2) {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+ } else if (format.channels == 1) {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
+ } else {
+ DEBUGF("CODEC_ERROR: more than 2 channels unsupported\n");
+ return CODEC_ERROR;
+ }
+
+ if (format.samplesperblock == 0)
+ {
+ DEBUGF("CODEC_ERROR: samplesperblock is 0\n");
+ return CODEC_ERROR;
+ }
+ if (format.blockalign == 0)
+ {
+ DEBUGF("CODEC_ERROR: blockalign is 0\n");
+ return CODEC_ERROR;
+ }
+
+ /* check chunksize */
+ if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels
+ > PCM_SAMPLE_SIZE)
+ format.chunksize = (PCM_SAMPLE_SIZE / format.blockalign) * format.blockalign;
+ if (format.chunksize == 0)
+ {
+ DEBUGF("CODEC_ERROR: chunksize is 0\n");
+ return CODEC_ERROR;
+ }
+
+ firstblockposn = 1024 - n;
+ ci->advance_buffer(firstblockposn);
+
+ /* make sure we're at the correct offset */
+ if (bytesdone > (uint32_t) firstblockposn) {
+ /* Round down to previous block */
+ struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
+ PCM_SEEK_POS, NULL);
+
+ if (newpos->pos > format.numbytes)
+ return CODEC_OK;
+
+ if (ci->seek_buffer(firstblockposn + newpos->pos))
+ {
+ bytesdone = newpos->pos;
+ decodedsamples = newpos->samples;
+ }
+ } else {
+ /* already where we need to be */
+ bytesdone = 0;
+ }
+
+ ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
+
+ /* The main decoder loop */
+ endofstream = 0;
+
+ while (!endofstream) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* 3rd args(read_buffer) is unnecessary in the format which AIFF supports. */
+ struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL);
+
+ if (newpos->pos > format.numbytes)
+ {
+ ci->set_elapsed(ci->id3->length);
+ ci->seek_complete();
+ break;
+ }
+
+ if (ci->seek_buffer(firstblockposn + newpos->pos))
+ {
+ bytesdone = newpos->pos;
+ decodedsamples = newpos->samples;
+ }
+
+ ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
+ ci->seek_complete();
+ }
+ aifbuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
+
+ if (n == 0)
+ break; /* End of stream */
+
+ if (bytesdone + n > format.numbytes) {
+ n = format.numbytes - bytesdone;
+ endofstream = 1;
+ }
+
+ if (codec->decode(aifbuf, n, samples, &bufcount) == CODEC_ERROR)
+ {
+ DEBUGF("codec error\n");
+ return CODEC_ERROR;
+ }
+
+ ci->pcmbuf_insert(samples, NULL, bufcount);
+
+ ci->advance_buffer(n);
+ bytesdone += n;
+ decodedsamples += bufcount;
+ if (bytesdone >= format.numbytes)
+ endofstream = 1;
+
+ ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/aiff_enc.c b/lib/rbcodec/codecs/aiff_enc.c
new file mode 100644
index 0000000000..fc44196eb0
--- /dev/null
+++ b/lib/rbcodec/codecs/aiff_enc.c
@@ -0,0 +1,400 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Antonius Hellmann
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <inttypes.h>
+#include "codeclib.h"
+
+CODEC_ENC_HEADER
+
+struct aiff_header
+{
+ uint8_t form_id[4]; /* 00h - 'FORM' */
+ uint32_t form_size; /* 04h - size of file - 8 */
+ uint8_t aiff_id[4]; /* 08h - 'AIFF' */
+ uint8_t comm_id[4]; /* 0Ch - 'COMM' */
+ int32_t comm_size; /* 10h - num_channels through sample_rate
+ (18) */
+ int16_t num_channels; /* 14h - 1=M, 2=S, etc. */
+ uint32_t num_sample_frames; /* 16h - num samples for each channel */
+ int16_t sample_size; /* 1ah - 1-32 bits per sample */
+ uint8_t sample_rate[10]; /* 1ch - IEEE 754 80-bit floating point */
+ uint8_t ssnd_id[4]; /* 26h - "SSND" */
+ int32_t ssnd_size; /* 2ah - size of chunk from offset to
+ end of pcm data */
+ uint32_t offset; /* 2eh - data offset from end of header */
+ uint32_t block_size; /* 32h - pcm data alignment */
+ /* 36h */
+} __attribute__((packed));
+
+#define PCM_DEPTH_BYTES 2
+#define PCM_DEPTH_BITS 16
+#define PCM_SAMP_PER_CHUNK 2048
+#define PCM_CHUNK_SIZE (PCM_SAMP_PER_CHUNK*4)
+
+/* Template headers */
+struct aiff_header aiff_header =
+{
+ { 'F', 'O', 'R', 'M' }, /* form_id */
+ 0, /* form_size (*) */
+ { 'A', 'I', 'F', 'F' }, /* aiff_id */
+ { 'C', 'O', 'M', 'M' }, /* comm_id */
+ htobe32(18), /* comm_size */
+ 0, /* num_channels (*) */
+ 0, /* num_sample_frames (*) */
+ htobe16(PCM_DEPTH_BITS), /* sample_size */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* sample_rate (*) */
+ { 'S', 'S', 'N', 'D' }, /* ssnd_id */
+ 0, /* ssnd_size (*) */
+ htobe32(0), /* offset */
+ htobe32(0), /* block_size */
+};
+
+/* (*) updated when finalizing file */
+
+static int num_channels IBSS_ATTR;
+static int rec_mono_mode IBSS_ATTR;
+static uint32_t sample_rate;
+static uint32_t enc_size;
+static int32_t err IBSS_ATTR;
+
+/* convert unsigned 32 bit value to 80-bit floating point number */
+STATICIRAM void uint32_h_to_ieee754_extended_be(uint8_t f[10], uint32_t l)
+ ICODE_ATTR;
+STATICIRAM void uint32_h_to_ieee754_extended_be(uint8_t f[10], uint32_t l)
+{
+ int32_t exp;
+
+ ci->memset(f, 0, 10);
+
+ if (l == 0)
+ return;
+
+ for (exp = 30; (l & (1ul << 31)) == 0; exp--)
+ l <<= 1;
+
+ /* sign always zero - bit 79 */
+ /* exponent is 0-31 (normalized: 31 - shift + 16383) - bits 64-78 */
+ f[0] = 0x40;
+ f[1] = (uint8_t)exp;
+ /* mantissa is value left justified with most significant non-zero
+ bit stored in bit 63 - bits 0-63 */
+ f[2] = (uint8_t)(l >> 24);
+ f[3] = (uint8_t)(l >> 16);
+ f[4] = (uint8_t)(l >> 8);
+ f[5] = (uint8_t)(l >> 0);
+} /* uint32_h_to_ieee754_extended_be */
+
+/* called version often - inline */
+static inline bool is_file_data_ok(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool is_file_data_ok(struct enc_file_event_data *data)
+{
+ return data->rec_file >= 0 && (long)data->chunk->flags >= 0;
+} /* is_file_data_ok */
+
+/* called version often - inline */
+static inline bool on_write_chunk(struct enc_file_event_data *data) ICODE_ATTR;
+static inline bool on_write_chunk(struct enc_file_event_data *data)
+{
+ if (!is_file_data_ok(data))
+ return false;
+
+ if (data->chunk->enc_data == NULL)
+ {
+#ifdef ROCKBOX_HAS_LOGF
+ ci->logf("aiff enc: NULL data");
+#endif
+ return true;
+ }
+
+ if (ci->write(data->rec_file, data->chunk->enc_data,
+ data->chunk->enc_size) != (ssize_t)data->chunk->enc_size)
+ return false;
+
+ data->num_pcm_samples += data->chunk->num_pcm;
+ return true;
+} /* on_write_chunk */
+
+static bool on_start_file(struct enc_file_event_data *data)
+{
+ if ((data->chunk->flags & CHUNKF_ERROR) || *data->filename == '\0')
+ return false;
+
+ data->rec_file = ci->open(data->filename, O_RDWR|O_CREAT|O_TRUNC, 0666);
+
+ if (data->rec_file < 0)
+ return false;
+
+ /* reset sample count */
+ data->num_pcm_samples = 0;
+
+ /* write template headers */
+ if (ci->write(data->rec_file, &aiff_header, sizeof (aiff_header))
+ != sizeof (aiff_header))
+ {
+ return false;
+ }
+
+ data->new_enc_size += sizeof(aiff_header);
+ return true;
+} /* on_start_file */
+
+static bool on_end_file(struct enc_file_event_data *data)
+{
+ /* update template headers */
+ struct aiff_header hdr;
+ uint32_t data_size;
+
+ if (!is_file_data_ok(data))
+ return false;
+
+ if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
+ ci->read(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr))
+ {
+ return false;
+ }
+
+ data_size = data->num_pcm_samples*num_channels*PCM_DEPTH_BYTES;
+
+ /* 'FORM' chunk */
+ hdr.form_size = htobe32(data_size + sizeof (hdr) - 8);
+
+ /* 'COMM' chunk */
+ hdr.num_channels = htobe16(num_channels);
+ hdr.num_sample_frames = htobe32(data->num_pcm_samples);
+ uint32_h_to_ieee754_extended_be(hdr.sample_rate, sample_rate);
+
+ /* 'SSND' chunk */
+ hdr.ssnd_size = htobe32(data_size + 8);
+
+ if (ci->lseek(data->rec_file, 0, SEEK_SET) != 0 ||
+ ci->write(data->rec_file, &hdr, sizeof (hdr)) != sizeof (hdr) ||
+ ci->close(data->rec_file) != 0)
+ {
+ return false;
+ }
+
+ data->rec_file = -1;
+
+ return true;
+} /* on_end_file */
+
+STATICIRAM void enc_events_callback(enum enc_events event, void *data)
+ ICODE_ATTR;
+STATICIRAM void enc_events_callback(enum enc_events event, void *data)
+{
+ switch (event)
+ {
+ case ENC_WRITE_CHUNK:
+ if (on_write_chunk((struct enc_file_event_data *)data))
+ return;
+
+ break;
+
+ case ENC_START_FILE:
+ if (on_start_file((struct enc_file_event_data *)data))
+ return;
+
+ break;
+
+ case ENC_END_FILE:
+ if (on_end_file((struct enc_file_event_data *)data))
+ return;
+
+ break;
+
+ default:
+ return;
+ }
+
+ /* Something failed above. Signal error back to core. */
+ ((struct enc_file_event_data *)data)->chunk->flags |= CHUNKF_ERROR;
+} /* enc_events_callback */
+
+/* convert native pcm samples to aiff format samples */
+static inline void sample_to_mono(uint32_t **src, uint32_t **dst)
+{
+ int32_t lr1, lr2;
+
+ switch(rec_mono_mode)
+ {
+ case 1:
+ /* mono = L */
+ lr1 = *(*src)++;
+ lr1 = lr1 >> 16;
+ lr2 = *(*src)++;
+ lr2 = lr2 >> 16;
+ break;
+ case 2:
+ /* mono = R */
+ lr1 = *(*src)++;
+ lr1 = (int16_t)lr1;
+ lr2 = *(*src)++;
+ lr2 = (int16_t)lr2;
+ break;
+ case 0:
+ default:
+ /* mono = (L+R)/2 */
+ lr1 = *(*src)++;
+ lr1 = (int16_t)lr1 + (lr1 >> 16) + err;
+ err = lr1 & 1;
+ lr1 >>= 1;
+
+ lr2 = *(*src)++;
+ lr2 = (int16_t)lr2 + (lr2 >> 16) + err;
+ err = lr2 & 1;
+ lr2 >>= 1;
+ break;
+ }
+ *(*dst)++ = htobe32((lr1 << 16) | (uint16_t)lr2);
+} /* sample_to_mono */
+
+STATICIRAM void chunk_to_aiff_format(uint32_t *src, uint32_t *dst) ICODE_ATTR;
+STATICIRAM void chunk_to_aiff_format(uint32_t *src, uint32_t *dst)
+{
+ if (num_channels == 1)
+ {
+ /* On big endian:
+ * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
+ * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
+ * |MMMMMMMMmmmmmmmm|MMMMMMMMmmmmmmmm|
+ *
+ * On little endian:
+ * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR|
+ * |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
+ * |MMMMMMMMmmmmmmmm|MMMMMMMMmmmmmmmm|
+ */
+ uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
+
+ do
+ {
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ sample_to_mono(&src, &dst);
+ }
+ while (src < src_end);
+ }
+ else
+ {
+#ifdef ROCKBOX_BIG_ENDIAN
+ /* |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr| =>
+ * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
+ */
+ ci->memcpy(dst, src, PCM_CHUNK_SIZE);
+#else
+ /* |llllllllLLLLLLLL|rrrrrrrrRRRRRRRR| =>
+ * |LLLLLLLLllllllll|RRRRRRRRrrrrrrrr|
+ */
+ uint32_t *src_end = src + PCM_SAMP_PER_CHUNK;
+
+ do
+ {
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ *dst++ = swap_odd_even32(*src++);
+ }
+ while (src < src_end);
+#endif
+ }
+} /* chunk_to_aiff_format */
+
+static bool init_encoder(void)
+{
+ struct enc_inputs inputs;
+ struct enc_parameters params;
+
+ if (ci->enc_get_inputs == NULL ||
+ ci->enc_set_parameters == NULL ||
+ ci->enc_get_chunk == NULL ||
+ ci->enc_finish_chunk == NULL ||
+ ci->enc_get_pcm_data == NULL )
+ return false;
+
+ ci->enc_get_inputs(&inputs);
+
+ if (inputs.config->afmt != AFMT_AIFF)
+ return false;
+
+ sample_rate = inputs.sample_rate;
+ num_channels = inputs.num_channels;
+ rec_mono_mode = inputs.rec_mono_mode;
+ err = 0;
+
+ /* configure the buffer system */
+ params.afmt = AFMT_AIFF;
+ enc_size = PCM_CHUNK_SIZE*inputs.num_channels / 2;
+ params.chunk_size = enc_size;
+ params.enc_sample_rate = sample_rate;
+ params.reserve_bytes = 0;
+ params.events_callback = enc_events_callback;
+ ci->enc_set_parameters(&params);
+
+ return true;
+} /* init_encoder */
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ if (!init_encoder())
+ return CODEC_ERROR;
+ }
+ else if (reason == CODEC_UNLOAD) {
+ /* reset parameters to initial state */
+ ci->enc_set_parameters(NULL);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ /* main encoding loop */
+ while (ci->get_command(NULL) != CODEC_ACTION_HALT)
+ {
+ uint32_t *src = (uint32_t *)ci->enc_get_pcm_data(PCM_CHUNK_SIZE);
+ struct enc_chunk_hdr *chunk;
+
+ if (src == NULL)
+ continue;
+
+ chunk = ci->enc_get_chunk();
+ chunk->enc_size = enc_size;
+ chunk->num_pcm = PCM_SAMP_PER_CHUNK;
+ chunk->enc_data = ENC_CHUNK_SKIP_HDR(chunk->enc_data, chunk);
+
+ chunk_to_aiff_format(src, (uint32_t *)chunk->enc_data);
+
+ ci->enc_finish_chunk();
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/alac.c b/lib/rbcodec/codecs/alac.c
new file mode 100644
index 0000000000..144d796e5f
--- /dev/null
+++ b/lib/rbcodec/codecs/alac.c
@@ -0,0 +1,146 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Dave Chapman
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include "libm4a/m4a.h"
+#include "libalac/decomp.h"
+
+CODEC_HEADER
+
+/* The maximum buffer size handled. This amount of bytes is buffered for each
+ * frame. */
+#define ALAC_BYTE_BUFFER_SIZE 32768
+
+static int32_t outputbuffer[ALAC_MAX_CHANNELS][ALAC_BLOCKSIZE] IBSS_ATTR;
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_NONINTERLEAVED);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, ALAC_OUTPUT_DEPTH-1);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ size_t n;
+ demux_res_t demux_res;
+ stream_t input_stream;
+ uint32_t samplesdone;
+ uint32_t elapsedtime = 0;
+ int samplesdecoded;
+ unsigned int i;
+ unsigned char* buffer;
+ alac_file alac;
+ intptr_t param;
+
+ /* Clean and initialize decoder structures */
+ memset(&demux_res , 0, sizeof(demux_res));
+ if (codec_init()) {
+ LOGF("ALAC: Error initialising codec\n");
+ return CODEC_ERROR;
+ }
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ codec_set_replaygain(ci->id3);
+
+ ci->seek_buffer(0);
+
+ stream_create(&input_stream,ci);
+
+ /* Read from ci->id3->offset before calling qtmovie_read. */
+ samplesdone = (uint32_t)(((uint64_t)(ci->id3->offset) * ci->id3->frequency) /
+ (ci->id3->bitrate*128));
+
+ /* if qtmovie_read returns successfully, the stream is up to
+ * the movie data, which can be used directly by the decoder */
+ if (!qtmovie_read(&input_stream, &demux_res)) {
+ LOGF("ALAC: Error initialising file\n");
+ return CODEC_ERROR;
+ }
+
+ /* initialise the sound converter */
+ alac_set_info(&alac, demux_res.codecdata);
+
+ /* Set i for first frame, seek to desired sample position for resuming. */
+ i=0;
+ if (samplesdone > 0) {
+ if (m4a_seek(&demux_res, &input_stream, samplesdone,
+ &samplesdone, (int*) &i)) {
+ elapsedtime = (samplesdone * 10) / (ci->id3->frequency / 100);
+ ci->set_elapsed(elapsedtime);
+ } else {
+ samplesdone = 0;
+ }
+ }
+
+ ci->set_elapsed(elapsedtime);
+
+ /* The main decoding loop */
+ while (i < demux_res.num_sample_byte_sizes) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ /* Request the required number of bytes from the input buffer */
+ buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);
+
+ /* Deal with any pending seek requests */
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ if (m4a_seek(&demux_res, &input_stream,
+ (param/10) * (ci->id3->frequency/100),
+ &samplesdone, (int *)&i)) {
+ elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
+ }
+ ci->set_elapsed(elapsedtime);
+ ci->seek_complete();
+ }
+
+ /* Request the required number of bytes from the input buffer */
+ buffer=ci->request_buffer(&n, ALAC_BYTE_BUFFER_SIZE);
+
+ /* Decode one block - returned samples will be host-endian */
+ samplesdecoded=alac_decode_frame(&alac, buffer, outputbuffer, ci->yield);
+ ci->yield();
+
+ /* Advance codec buffer by amount of consumed bytes */
+ ci->advance_buffer(alac.bytes_consumed);
+
+ /* Output the audio */
+ ci->pcmbuf_insert(outputbuffer[0], outputbuffer[1], samplesdecoded);
+
+ /* Update the elapsed-time indicator */
+ samplesdone+=samplesdecoded;
+ elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
+ ci->set_elapsed(elapsedtime);
+
+ i++;
+ }
+
+ LOGF("ALAC: Decoded %lu samples\n",(unsigned long)samplesdone);
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/ape.c b/lib/rbcodec/codecs/ape.c
new file mode 100644
index 0000000000..ed6ea21685
--- /dev/null
+++ b/lib/rbcodec/codecs/ape.c
@@ -0,0 +1,330 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2007 Dave Chapman
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include <codecs/demac/libdemac/demac.h>
+
+CODEC_HEADER
+
+#define BLOCKS_PER_LOOP 1024
+#define MAX_CHANNELS 2
+#define MAX_BYTESPERSAMPLE 3
+
+/* Monkey's Audio files have one seekpoint per frame. The framesize
+ varies between 73728 and 1179648 samples.
+
+ At the smallest framesize, 30000 frames would be 50155 seconds of
+ audio - almost 14 hours. This should be enough for any file a user
+ would want to play in Rockbox, given the 2GB FAT filesize (and 4GB
+ seektable entry size) limit.
+
+ This means the seektable is 120000 bytes, but we have a lot of
+ spare room in the codec buffer - the APE codec itself is small.
+*/
+
+#define MAX_SEEKPOINTS 30000
+static uint32_t seektablebuf[MAX_SEEKPOINTS];
+
+#define INPUT_CHUNKSIZE (32*1024)
+
+/* 1024*4 = 4096 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
+
+
+/* Given an ape_ctx and a sample to seek to, return the file position
+ to the frame containing that sample, and the number of samples to
+ skip in that frame.
+*/
+
+static bool ape_calc_seekpos(struct ape_ctx_t* ape_ctx,
+ uint32_t new_sample,
+ uint32_t* newframe,
+ uint32_t* filepos,
+ uint32_t* samplestoskip)
+{
+ uint32_t n;
+
+ n = new_sample / ape_ctx->blocksperframe;
+ if (n >= ape_ctx->numseekpoints)
+ {
+ /* We don't have a seekpoint for that frame */
+ return false;
+ }
+
+ *newframe = n;
+ *filepos = ape_ctx->seektable[n];
+ *samplestoskip = new_sample - (n * ape_ctx->blocksperframe);
+
+ return true;
+}
+
+/* The resume offset is a value in bytes - we need to
+ turn it into a frame number and samplestoskip value */
+
+static void ape_resume(struct ape_ctx_t* ape_ctx, size_t resume_offset,
+ uint32_t* currentframe, uint32_t* samplesdone,
+ uint32_t* samplestoskip, int* firstbyte)
+{
+ off_t newfilepos;
+ int64_t framesize;
+ int64_t offset;
+
+ *currentframe = 0;
+ *samplesdone = 0;
+ *samplestoskip = 0;
+
+ while ((*currentframe < ape_ctx->totalframes) &&
+ (*currentframe < ape_ctx->numseekpoints) &&
+ (resume_offset > ape_ctx->seektable[*currentframe]))
+ {
+ ++*currentframe;
+ *samplesdone += ape_ctx->blocksperframe;
+ }
+
+ if ((*currentframe > 0) &&
+ (ape_ctx->seektable[*currentframe] > resume_offset)) {
+ --*currentframe;
+ *samplesdone -= ape_ctx->blocksperframe;
+ }
+
+ newfilepos = ape_ctx->seektable[*currentframe];
+
+ /* APE's bytestream is weird... */
+ *firstbyte = 3 - (newfilepos & 3);
+ newfilepos &= ~3;
+
+ ci->seek_buffer(newfilepos);
+
+ /* We estimate where we were in the current frame, based on the
+ byte offset */
+ if (*currentframe < (ape_ctx->totalframes - 1)) {
+ framesize = ape_ctx->seektable[*currentframe+1] - ape_ctx->seektable[*currentframe];
+ offset = resume_offset - ape_ctx->seektable[*currentframe];
+
+ *samplestoskip = (offset * ape_ctx->blocksperframe) / framesize;
+ }
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, APE_OUTPUT_DEPTH-1);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ struct ape_ctx_t ape_ctx;
+ uint32_t samplesdone;
+ uint32_t elapsedtime;
+ size_t bytesleft;
+
+ uint32_t currentframe;
+ uint32_t newfilepos;
+ uint32_t samplestoskip;
+ int nblocks;
+ int bytesconsumed;
+ unsigned char* inbuffer;
+ uint32_t blockstodecode;
+ int res;
+ int firstbyte;
+ size_t resume_offset;
+ intptr_t param;
+
+ if (codec_init()) {
+ LOGF("APE: Error initialising codec\n");
+ return CODEC_ERROR;
+ }
+
+ /* Remember the resume position - when the codec is opened, the
+ playback engine will reset it. */
+ resume_offset = ci->id3->offset;
+
+ ci->seek_buffer(0);
+ 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");
+ return CODEC_ERROR;
+ }
+
+ /* Initialise the seektable for this file */
+ ape_ctx.seektable = seektablebuf;
+ ape_ctx.numseekpoints = MIN(MAX_SEEKPOINTS,ape_ctx.numseekpoints);
+
+ ci->advance_buffer(ape_ctx.seektablefilepos);
+
+ /* The seektable may be bigger than the guard buffer (32KB), so we
+ do a read() */
+ ci->read_filebuf(ape_ctx.seektable, ape_ctx.numseekpoints * sizeof(uint32_t));
+
+#ifdef ROCKBOX_BIG_ENDIAN
+ /* Byte-swap the little-endian seekpoints */
+ {
+ uint32_t i;
+
+ for(i = 0; i < ape_ctx.numseekpoints; i++)
+ ape_ctx.seektable[i] = swap32(ape_ctx.seektable[i]);
+ }
+#endif
+
+ /* Now advance the file position to the first frame */
+ ci->advance_buffer(ape_ctx.firstframe -
+ (ape_ctx.seektablefilepos +
+ ape_ctx.numseekpoints * sizeof(uint32_t)));
+
+ 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 */
+
+ if (resume_offset) {
+ /* The resume offset is a value in bytes - we need to
+ turn it into a frame number and samplestoskip value */
+
+ ape_resume(&ape_ctx, resume_offset,
+ &currentframe, &samplesdone, &samplestoskip, &firstbyte);
+ } else {
+ currentframe = 0;
+ samplesdone = 0;
+ samplestoskip = 0;
+ firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */
+ }
+
+ elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
+ ci->set_elapsed(elapsedtime);
+
+ /* Initialise the buffer */
+ inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
+
+ /* The main decoding loop - we decode the frames a small chunk at a time */
+ while (currentframe < ape_ctx.totalframes)
+ {
+frame_start:
+ /* 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)
+ {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ goto done;
+
+ /* Deal with any pending seek requests */
+ if (action == CODEC_ACTION_SEEK_TIME)
+ {
+ if (ape_calc_seekpos(&ape_ctx,
+ (param/10) * (ci->id3->frequency/100),
+ &currentframe,
+ &newfilepos,
+ &samplestoskip))
+ {
+ samplesdone = currentframe * ape_ctx.blocksperframe;
+
+ /* APE's bytestream is weird... */
+ firstbyte = 3 - (newfilepos & 3);
+ newfilepos &= ~3;
+
+ ci->seek_buffer(newfilepos);
+ inbuffer = ci->request_buffer(&bytesleft, INPUT_CHUNKSIZE);
+
+ elapsedtime = (samplesdone*10)/(ape_ctx.samplerate/100);
+ ci->set_elapsed(elapsedtime);
+ ci->seek_complete();
+ goto frame_start; /* Sorry... */
+ }
+
+ ci->seek_complete();
+ }
+
+ 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 %lu, error %d\n",(unsigned long)currentframe,res);
+ return CODEC_ERROR;
+ }
+
+ ci->yield();
+
+ if (samplestoskip > 0) {
+ if (samplestoskip < blockstodecode) {
+ ci->pcmbuf_insert(decoded0 + samplestoskip,
+ decoded1 + samplestoskip,
+ blockstodecode - samplestoskip);
+ samplestoskip = 0;
+ } else {
+ samplestoskip -= blockstodecode;
+ }
+ } else {
+ ci->pcmbuf_insert(decoded0, decoded1, blockstodecode);
+ }
+
+ samplesdone += blockstodecode;
+
+ if (!samplestoskip) {
+ /* Update the elapsed-time indicator */
+ 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++;
+ }
+
+done:
+ LOGF("APE: Decoded %lu samples\n",(unsigned long)samplesdone);
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/asap.c b/lib/rbcodec/codecs/asap.c
new file mode 100644
index 0000000000..19b39a44c4
--- /dev/null
+++ b/lib/rbcodec/codecs/asap.c
@@ -0,0 +1,140 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 Dominik Wenger
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include "libasap/asap.h"
+
+CODEC_HEADER
+
+#define CHUNK_SIZE (1024*2)
+
+static byte samples[CHUNK_SIZE] IBSS_ATTR; /* The sample buffer */
+static ASAP_State asap IBSS_ATTR; /* asap codec state */
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ /* Nothing to do */
+ return CODEC_OK;
+ (void)reason;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ int n_bytes;
+ int song;
+ int duration;
+ char* module;
+ int bytesPerSample =2;
+ intptr_t param;
+
+ if (codec_init()) {
+ DEBUGF("codec init failed\n");
+ return CODEC_ERROR;
+ }
+
+ codec_set_replaygain(ci->id3);
+
+ int bytes_done =0;
+ size_t filesize;
+ ci->seek_buffer(0);
+ module = ci->request_buffer(&filesize, ci->filesize);
+ if (!module || (size_t)filesize < (size_t)ci->filesize)
+ {
+ DEBUGF("loading error\n");
+ return CODEC_ERROR;
+ }
+
+ /*Init ASAP */
+ if (!ASAP_Load(&asap, ci->id3->path, module, filesize))
+ {
+ DEBUGF("%s: format not supported",ci->id3->path);
+ return CODEC_ERROR;
+ }
+
+ /* Make use of 44.1khz */
+ ci->configure(DSP_SET_FREQUENCY, 44100);
+ /* Sample depth is 16 bit little endian */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
+ /* Stereo or Mono output ? */
+ if(asap.module_info->channels ==1)
+ {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
+ bytesPerSample = 2;
+ }
+ else
+ {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+ bytesPerSample = 4;
+ }
+ /* reset eleapsed */
+ ci->set_elapsed(0);
+
+ song = asap.module_info->default_song;
+ duration = asap.module_info->durations[song];
+ if (duration < 0)
+ duration = 180 * 1000;
+
+ /* set id3 length, because metadata parse might not have done it */
+ ci->id3->length = duration;
+
+ ASAP_PlaySong(&asap, song, duration);
+ ASAP_MutePokeyChannels(&asap, 0);
+
+ /* The main decoder loop */
+ while (1) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* New time is ready in param */
+
+ /* seek to pos */
+ ASAP_Seek(&asap,param);
+ /* update bytes_done */
+ bytes_done = param*44.1*2;
+ /* update elapsed */
+ ci->set_elapsed((bytes_done / 2) / 44.1);
+ /* seek ready */
+ ci->seek_complete();
+ }
+
+ /* Generate a buffer full of Audio */
+ #ifdef ROCKBOX_LITTLE_ENDIAN
+ n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_LE);
+ #else
+ n_bytes = ASAP_Generate(&asap, samples, sizeof(samples), ASAP_FORMAT_S16_BE);
+ #endif
+
+ ci->pcmbuf_insert(samples, NULL, n_bytes /bytesPerSample);
+
+ bytes_done += n_bytes;
+ ci->set_elapsed((bytes_done / 2) / 44.1);
+
+ if(n_bytes != sizeof(samples))
+ break;
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/atrac3_oma.c b/lib/rbcodec/codecs/atrac3_oma.c
new file mode 100644
index 0000000000..50f7c8f163
--- /dev/null
+++ b/lib/rbcodec/codecs/atrac3_oma.c
@@ -0,0 +1,153 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Mohamed Tarek
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+
+#include "logf.h"
+#include "codeclib.h"
+#include "inttypes.h"
+#include "libatrac/atrac3.h"
+
+CODEC_HEADER
+
+#define FRAMESIZE ci->id3->bytesperframe
+#define BITRATE ci->id3->bitrate
+
+static ATRAC3Context q IBSS_ATTR;
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ /* Nothing to do */
+ return CODEC_OK;
+ (void)reason;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ static size_t buff_size;
+ int datasize, res, frame_counter, total_frames, seek_frame_offset;
+ uint8_t *bit_buffer;
+ int elapsed = 0;
+ size_t resume_offset;
+ intptr_t param;
+ enum codec_command_action action = CODEC_ACTION_NULL;
+
+ if (codec_init()) {
+ DEBUGF("codec init failed\n");
+ return CODEC_ERROR;
+ }
+
+ resume_offset = ci->id3->offset;
+
+ codec_set_replaygain(ci->id3);
+ ci->memset(&q,0,sizeof(ATRAC3Context));
+
+ ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
+ ci->configure(DSP_SET_STEREO_MODE, ci->id3->channels == 1 ?
+ STEREO_MONO : STEREO_NONINTERLEAVED);
+
+ ci->seek_buffer(0);
+
+ res = atrac3_decode_init(&q, ci->id3);
+ if(res < 0) {
+ DEBUGF("failed to initialize OMA atrac decoder\n");
+ return CODEC_ERROR;
+ }
+
+ total_frames = (ci->id3->filesize - ci->id3->first_frame_offset) / FRAMESIZE;
+ frame_counter = 0;
+
+ /* check for a mid-track resume and force a seek time accordingly */
+ if(resume_offset > ci->id3->first_frame_offset) {
+ resume_offset -= ci->id3->first_frame_offset;
+ /* calculate resume_offset in frames */
+ resume_offset = (int)resume_offset / FRAMESIZE;
+ param = (int)resume_offset * ((FRAMESIZE * 8)/BITRATE);
+ action = CODEC_ACTION_SEEK_TIME;
+ }
+ else {
+ ci->set_elapsed(0);
+ ci->seek_buffer(ci->id3->first_frame_offset);
+ }
+
+ /* The main decoder loop */
+ while(frame_counter < total_frames)
+ {
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* Do not allow seeking beyond the file's length */
+ if ((unsigned) param > ci->id3->length) {
+ ci->set_elapsed(ci->id3->length);
+ ci->seek_complete();
+ break;
+ }
+
+ /* Seek to the start of the track */
+ if (param == 0) {
+ elapsed = 0;
+ ci->set_elapsed(0);
+ ci->seek_buffer(ci->id3->first_frame_offset);
+ ci->seek_complete();
+ action = CODEC_ACTION_NULL;
+ continue;
+ }
+
+ seek_frame_offset = (param * BITRATE) / (8 * FRAMESIZE);
+ frame_counter = seek_frame_offset;
+ ci->seek_buffer(ci->id3->first_frame_offset + seek_frame_offset* FRAMESIZE);
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, FRAMESIZE);
+ elapsed = param;
+ ci->set_elapsed(elapsed);
+ ci->seek_complete();
+ }
+
+ action = CODEC_ACTION_NULL;
+
+ res = atrac3_decode_frame(FRAMESIZE, &q, &datasize, bit_buffer, FRAMESIZE);
+
+ if(res != (int)FRAMESIZE) {
+ DEBUGF("codec error\n");
+ return CODEC_ERROR;
+ }
+
+ if(datasize)
+ ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024,
+ q.samples_per_frame / ci->id3->channels);
+
+ elapsed += (FRAMESIZE * 8) / BITRATE;
+ ci->set_elapsed(elapsed);
+
+ ci->advance_buffer(FRAMESIZE);
+ frame_counter++;
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/atrac3_rm.c b/lib/rbcodec/codecs/atrac3_rm.c
new file mode 100644
index 0000000000..997507425e
--- /dev/null
+++ b/lib/rbcodec/codecs/atrac3_rm.c
@@ -0,0 +1,215 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Mohamed Tarek
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+
+#include "logf.h"
+#include "codeclib.h"
+#include "inttypes.h"
+#include "libatrac/atrac3.h"
+
+CODEC_HEADER
+
+static RMContext rmctx IBSS_ATTR_LARGE_IRAM;
+static RMPacket pkt IBSS_ATTR_LARGE_IRAM;
+static ATRAC3Context q IBSS_ATTR;
+
+static void init_rm(RMContext *rmctx)
+{
+ /* initialize the RMContext */
+ memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
+
+ /* and atrac3 expects extadata in id3v2buf, so we shall give it that */
+ memcpy(ci->id3->id3v2buf, (char*)rmctx->codec_extradata, rmctx->extradata_size*sizeof(char));
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ /* Nothing to do */
+ return CODEC_OK;
+ (void)reason;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ static size_t buff_size;
+ int datasize, res, consumed, i, time_offset;
+ uint8_t *bit_buffer;
+ uint16_t fs,sps,h;
+ uint32_t packet_count;
+ int scrambling_unit_size, num_units, elapsed = 0;
+ int playback_on = -1;
+ size_t resume_offset;
+ intptr_t param;
+ enum codec_command_action action = CODEC_ACTION_NULL;
+
+ if (codec_init()) {
+ DEBUGF("codec init failed\n");
+ return CODEC_ERROR;
+ }
+
+ resume_offset = ci->id3->offset;
+
+ codec_set_replaygain(ci->id3);
+ ci->memset(&rmctx,0,sizeof(RMContext));
+ ci->memset(&pkt,0,sizeof(RMPacket));
+ ci->memset(&q,0,sizeof(ATRAC3Context));
+
+ ci->seek_buffer(0);
+ init_rm(&rmctx);
+
+ ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 17); /* Remark: atrac3 uses s15.0 by default, s15.2 was hacked. */
+ ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
+ STEREO_MONO : STEREO_NONINTERLEAVED);
+
+ packet_count = rmctx.nb_packets;
+ rmctx.audio_framesize = rmctx.block_align;
+ rmctx.block_align = rmctx.sub_packet_size;
+ fs = rmctx.audio_framesize;
+ sps= rmctx.block_align;
+ h = rmctx.sub_packet_h;
+ scrambling_unit_size = h * (fs + PACKET_HEADER_SIZE);
+
+ res = atrac3_decode_init(&q, ci->id3);
+ if(res < 0) {
+ DEBUGF("failed to initialize RM atrac decoder\n");
+ return CODEC_ERROR;
+ }
+
+ /* check for a mid-track resume and force a seek time accordingly */
+ if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
+ resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ num_units = (int)resume_offset / scrambling_unit_size;
+ /* put number of subpackets to skip in resume_offset */
+ resume_offset /= (sps + PACKET_HEADER_SIZE);
+ param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
+ action = CODEC_ACTION_SEEK_TIME;
+ }
+ else {
+ ci->set_elapsed(0);
+ }
+
+ ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+
+ /* The main decoder loop */
+seek_start :
+ while((unsigned)elapsed < rmctx.duration)
+ {
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
+ consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
+ if(consumed < 0 && playback_on != 0) {
+ if(playback_on == -1) {
+ /* Error only if packet-parsing failed and playback hadn't started */
+ DEBUGF("rm_get_packet failed\n");
+ return CODEC_ERROR;
+ }
+ else
+ return CODEC_OK;
+ }
+
+ for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
+ {
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ return CODEC_OK;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* Do not allow seeking beyond the file's length */
+ if ((unsigned) param > ci->id3->length) {
+ ci->set_elapsed(ci->id3->length);
+ ci->seek_complete();
+ return CODEC_OK;
+ }
+
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+ packet_count = rmctx.nb_packets;
+ rmctx.audio_pkt_cnt = 0;
+ rmctx.frame_number = 0;
+
+ /* Seek to the start of the track */
+ if (param == 0) {
+ ci->set_elapsed(0);
+ ci->seek_complete();
+ action = CODEC_ACTION_NULL;
+ goto seek_start;
+ }
+ num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
+ consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
+ if(consumed < 0 && playback_on != 0) {
+ if(playback_on == -1) {
+ /* Error only if packet-parsing failed and playback hadn't started */
+ DEBUGF("rm_get_packet failed\n");
+ return CODEC_ERROR;
+ }
+ else
+ return CODEC_OK;
+ }
+
+ packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
+ rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate));
+ while(rmctx.audiotimestamp > (unsigned) param) {
+ rmctx.audio_pkt_cnt = 0;
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
+ consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
+ packet_count += rmctx.audio_pkt_cnt;
+ num_units--;
+ }
+ time_offset = param - rmctx.audiotimestamp;
+ i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
+ elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
+ ci->set_elapsed(elapsed);
+ ci->seek_complete();
+ }
+
+ action = CODEC_ACTION_NULL;
+
+ if(pkt.length)
+ res = atrac3_decode_frame(rmctx.block_align, &q, &datasize, pkt.frames[i], rmctx.block_align);
+ else /* indicates that there are no remaining frames */
+ return CODEC_OK;
+
+ if(res != rmctx.block_align) {
+ DEBUGF("codec error\n");
+ return CODEC_ERROR;
+ }
+
+ if(datasize)
+ ci->pcmbuf_insert(q.outSamples, q.outSamples + 1024, q.samples_per_frame / rmctx.nb_channels);
+ playback_on = 1;
+ elapsed = rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i;
+ ci->set_elapsed(elapsed);
+ rmctx.frame_number++;
+ }
+ packet_count -= rmctx.audio_pkt_cnt;
+ rmctx.audio_pkt_cnt = 0;
+ ci->advance_buffer(consumed);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/au.c b/lib/rbcodec/codecs/au.c
new file mode 100644
index 0000000000..cb75c7423d
--- /dev/null
+++ b/lib/rbcodec/codecs/au.c
@@ -0,0 +1,314 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 Yoshihisa Uchida
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include "codecs/libpcm/support_formats.h"
+
+CODEC_HEADER
+
+/* Sun Audio file (Au file format) codec
+ *
+ * References
+ * [1] Sun Microsystems, Inc., Header file for Audio, .au, 1992
+ * URL http://www.opengroup.org/public/pubs/external/auformat.html
+ * [2] Wikipedia, Au file format, URL: http://en.wikipedia.org/wiki/Sun_Audio
+ */
+
+#define PCM_SAMPLE_SIZE (1024*2)
+
+static int32_t samples[PCM_SAMPLE_SIZE] IBSS_ATTR;
+
+enum
+{
+ AU_FORMAT_UNSUPPORT = 0, /* unsupported format */
+ AU_FORMAT_MULAW, /* G.711 MULAW */
+ AU_FORMAT_PCM, /* Linear PCM */
+ AU_FORMAT_IEEE_FLOAT, /* IEEE float */
+ AU_FORMAT_ALAW, /* G.711 ALAW */
+};
+
+static const char support_formats[9][2] = {
+ { AU_FORMAT_UNSUPPORT, 0 }, /* encoding */
+ { AU_FORMAT_MULAW, 8 }, /* 1: G.711 MULAW */
+ { AU_FORMAT_PCM, 8 }, /* 2: Linear PCM 8bit (signed) */
+ { AU_FORMAT_PCM, 16 }, /* 3: Linear PCM 16bit (signed, big endian) */
+ { AU_FORMAT_PCM, 24 }, /* 4: Linear PCM 24bit (signed, big endian) */
+ { AU_FORMAT_PCM, 32 }, /* 5: Linear PCM 32bit (signed, big endian) */
+ { AU_FORMAT_IEEE_FLOAT, 32 }, /* 6: Linear PCM float 32bit (signed, big endian) */
+ { AU_FORMAT_IEEE_FLOAT, 64 }, /* 7: Linear PCM float 64bit (signed, big endian) */
+ /* encoding 8 - 26 unsupported. */
+ { AU_FORMAT_ALAW, 8 }, /* 27: G.711 ALAW */
+};
+
+static const struct pcm_entry au_codecs[] = {
+ { AU_FORMAT_MULAW, get_itut_g711_mulaw_codec },
+ { AU_FORMAT_PCM, get_linear_pcm_codec },
+ { AU_FORMAT_IEEE_FLOAT, get_ieee_float_codec },
+ { AU_FORMAT_ALAW, get_itut_g711_alaw_codec },
+};
+
+#define NUM_FORMATS 4
+
+static const struct pcm_codec *get_au_codec(uint32_t formattag)
+{
+ int i;
+
+ for (i = 0; i < NUM_FORMATS; i++)
+ {
+ if (au_codecs[i].format_tag == formattag)
+ {
+ if (au_codecs[i].get_codec)
+ return au_codecs[i].get_codec();
+ return 0;
+ }
+ }
+ return 0;
+}
+
+static unsigned int get_be32(uint8_t *buf)
+{
+ return (buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3];
+}
+
+static int convert_au_format(unsigned int encoding, struct pcm_format *fmt)
+{
+ fmt->formattag = AU_FORMAT_UNSUPPORT;
+ if (encoding < 8)
+ {
+ fmt->formattag = support_formats[encoding][0];
+ fmt->bitspersample = support_formats[encoding][1];
+ }
+ else if (encoding == 27)
+ {
+ fmt->formattag = support_formats[8][0];
+ fmt->bitspersample = support_formats[8][1];
+ }
+
+ return fmt->formattag;
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, PCM_OUTPUT_DEPTH-1);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ struct pcm_format format;
+ uint32_t bytesdone, decodedsamples;
+ size_t n;
+ int bufcount;
+ int endofstream;
+ unsigned char *buf;
+ uint8_t *aubuf;
+ off_t firstblockposn; /* position of the first block in file */
+ const struct pcm_codec *codec;
+ int offset = 0;
+ intptr_t param;
+
+ if (codec_init()) {
+ DEBUGF("codec_init() error\n");
+ return CODEC_ERROR;
+ }
+
+ codec_set_replaygain(ci->id3);
+
+ /* Need to save offset for later use (cleared indirectly by advance_buffer) */
+ bytesdone = ci->id3->offset;
+
+ ci->memset(&format, 0, sizeof(struct pcm_format));
+ format.is_signed = true;
+ format.is_little_endian = false;
+
+ /* set format */
+ ci->seek_buffer(0);
+ buf = ci->request_buffer(&n, 24);
+ if (n < 24 || (memcmp(buf, ".snd", 4) != 0))
+ {
+ /*
+ * headerless sun audio file
+ * It is decoded under conditions.
+ * format: G.711 mu-law
+ * channel: mono
+ * frequency: 8000 kHz
+ */
+ offset = 0;
+ format.formattag = AU_FORMAT_MULAW;
+ format.channels = 1;
+ format.bitspersample = 8;
+ format.numbytes = ci->id3->filesize;
+ }
+ else
+ {
+ /* parse header */
+
+ /* data offset */
+ offset = get_be32(buf + 4);
+ if (offset < 24)
+ {
+ DEBUGF("CODEC_ERROR: sun audio offset size is small: %d\n", offset);
+ return CODEC_ERROR;
+ }
+ /* data size */
+ format.numbytes = get_be32(buf + 8);
+ if (format.numbytes == (uint32_t)0xffffffff)
+ format.numbytes = ci->id3->filesize - offset;
+ /* encoding */
+ format.formattag = convert_au_format(get_be32(buf + 12), &format);
+ if (format.formattag == AU_FORMAT_UNSUPPORT)
+ {
+ DEBUGF("CODEC_ERROR: sun audio unsupport format: %d\n", get_be32(buf + 12));
+ return CODEC_ERROR;
+ }
+ /* skip sample rate */
+ format.channels = get_be32(buf + 20);
+ }
+
+ /* advance to first WAVE chunk */
+ ci->advance_buffer(offset);
+
+ firstblockposn = offset;
+
+ decodedsamples = 0;
+ codec = 0;
+
+ /* get codec */
+ codec = get_au_codec(format.formattag);
+ if (!codec)
+ {
+ DEBUGF("CODEC_ERROR: unsupport sun audio format: %x\n", (int)format.formattag);
+ return CODEC_ERROR;
+ }
+
+ if (!codec->set_format(&format))
+ {
+ return CODEC_ERROR;
+ }
+
+ if (format.numbytes == 0) {
+ DEBUGF("CODEC_ERROR: data size is 0\n");
+ return CODEC_ERROR;
+ }
+
+ /* check chunksize */
+ if ((format.chunksize / format.blockalign) * format.samplesperblock * format.channels
+ > PCM_SAMPLE_SIZE)
+ format.chunksize = (PCM_SAMPLE_SIZE / format.blockalign) * format.blockalign;
+ if (format.chunksize == 0)
+ {
+ DEBUGF("CODEC_ERROR: chunksize is 0\n");
+ return CODEC_ERROR;
+ }
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ if (format.channels == 2) {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+ } else if (format.channels == 1) {
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_MONO);
+ } else {
+ DEBUGF("CODEC_ERROR: more than 2 channels\n");
+ return CODEC_ERROR;
+ }
+
+ /* make sure we're at the correct offset */
+ if (bytesdone > (uint32_t) firstblockposn) {
+ /* Round down to previous block */
+ struct pcm_pos *newpos = codec->get_seek_pos(bytesdone - firstblockposn,
+ PCM_SEEK_POS, NULL);
+
+ if (newpos->pos > format.numbytes)
+ goto done;
+ if (ci->seek_buffer(firstblockposn + newpos->pos))
+ {
+ bytesdone = newpos->pos;
+ decodedsamples = newpos->samples;
+ }
+ } else {
+ /* already where we need to be */
+ bytesdone = 0;
+ }
+
+ ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
+
+ /* The main decoder loop */
+ endofstream = 0;
+
+ while (!endofstream) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* 3rd args(read_buffer) is unnecessary in the format which Sun Audio supports. */
+ struct pcm_pos *newpos = codec->get_seek_pos(param, PCM_SEEK_TIME, NULL);
+
+ if (newpos->pos > format.numbytes)
+ {
+ ci->set_elapsed(ci->id3->length);
+ ci->seek_complete();
+ break;
+ }
+
+ if (ci->seek_buffer(firstblockposn + newpos->pos))
+ {
+ bytesdone = newpos->pos;
+ decodedsamples = newpos->samples;
+ }
+
+ ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
+ ci->seek_complete();
+ }
+
+ aubuf = (uint8_t *)ci->request_buffer(&n, format.chunksize);
+ if (n == 0)
+ break; /* End of stream */
+ if (bytesdone + n > format.numbytes) {
+ n = format.numbytes - bytesdone;
+ endofstream = 1;
+ }
+
+ if (codec->decode(aubuf, n, samples, &bufcount) == CODEC_ERROR)
+ {
+ DEBUGF("codec error\n");
+ return CODEC_ERROR;
+ }
+
+ ci->pcmbuf_insert(samples, NULL, bufcount);
+ ci->advance_buffer(n);
+ bytesdone += n;
+ decodedsamples += bufcount;
+
+ if (bytesdone >= format.numbytes)
+ endofstream = 1;
+ ci->set_elapsed(decodedsamples*1000LL/ci->id3->frequency);
+ }
+
+done:
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/ay.c b/lib/rbcodec/codecs/ay.c
new file mode 100644
index 0000000000..b11ad84294
--- /dev/null
+++ b/lib/rbcodec/codecs/ay.c
@@ -0,0 +1,137 @@
+
+/* Ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
+
+#include <codecs/lib/codeclib.h>
+#include "libgme/ay_emu.h"
+
+CODEC_HEADER
+
+/* Maximum number of bytes to process in one iteration */
+#define CHUNK_SIZE (1024*2)
+
+static int16_t samples[CHUNK_SIZE] IBSS_ATTR;
+static struct Ay_Emu ay_emu;
+
+/****************** rockbox interface ******************/
+
+static void set_codec_track(int t, int multitrack) {
+ Ay_start_track(&ay_emu, t);
+
+ /* for loop mode we disable track limits */
+ if (!ci->loop_track()) {
+ Track_set_fade(&ay_emu, Track_get_length( &ay_emu, t ) - 4000, 4000);
+ }
+ if (multitrack) ci->set_elapsed(t*1000); /* t is track no to display */
+ else ci->set_elapsed(0);
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* we only render 16 bits */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
+
+ /* 44 Khz, Interleaved stereo */
+ ci->configure(DSP_SET_FREQUENCY, 44100);
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+
+ Ay_init(&ay_emu);
+ Ay_set_sample_rate(&ay_emu, 44100);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ blargg_err_t err;
+ uint8_t *buf;
+ size_t n;
+ int track, is_multitrack;
+ intptr_t param;
+ uint32_t elapsed_time;
+
+ /* reset values */
+ track = is_multitrack = 0;
+ elapsed_time = 0;
+
+ DEBUGF("AY: next_track\n");
+ if (codec_init()) {
+ return CODEC_ERROR;
+ }
+
+ codec_set_replaygain(ci->id3);
+
+ /* Read the entire file */
+ DEBUGF("AY: request file\n");
+ ci->seek_buffer(0);
+ buf = ci->request_buffer(&n, ci->filesize);
+ if (!buf || n < (size_t)ci->filesize) {
+ DEBUGF("AY: file load failed\n");
+ return CODEC_ERROR;
+ }
+
+ if ((err = Ay_load_mem(&ay_emu, buf, ci->filesize))) {
+ DEBUGF("AY: Ay_load_mem failed (%s)\n", err);
+ return CODEC_ERROR;
+ }
+
+ /* Update internal track count */
+ if (ay_emu.m3u.size > 0)
+ ay_emu.track_count = ay_emu.m3u.size;
+
+ /* Check if file has multiple tracks */
+ if (ay_emu.track_count > 1) {
+ is_multitrack = 1;
+ }
+
+next_track:
+ set_codec_track(track, is_multitrack);
+
+ /* The main decoder loop */
+ while (1) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ if (is_multitrack) {
+ track = param/1000;
+ ci->seek_complete();
+ if (track >= ay_emu.track_count) break;
+ goto next_track;
+ }
+
+ ci->set_elapsed(param);
+ elapsed_time = param;
+ Track_seek(&ay_emu, param);
+ ci->seek_complete();
+
+ /* Set fade again */
+ if (!ci->loop_track()) {
+ Track_set_fade(&ay_emu, Track_get_length( &ay_emu, track ) - 4000, 4000);
+ }
+ }
+
+ /* Generate audio buffer */
+ err = Ay_play(&ay_emu, CHUNK_SIZE, samples);
+ if (err || Track_ended(&ay_emu)) {
+ track++;
+ if (track >= ay_emu.track_count) break;
+ goto next_track;
+ }
+
+ ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE >> 1);
+
+ /* Set elapsed time for one track files */
+ if (!is_multitrack) {
+ elapsed_time += (CHUNK_SIZE / 2) * 10 / 441;
+ ci->set_elapsed(elapsed_time);
+ }
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/codec_crt0.c b/lib/rbcodec/codecs/codec_crt0.c
new file mode 100644
index 0000000000..e3c3321e54
--- /dev/null
+++ b/lib/rbcodec/codecs/codec_crt0.c
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2006 Tomasz Malesinski
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+#include "codecs.h"
+
+struct codec_api *ci DATA_ATTR;
+
+extern unsigned char plugin_bss_start[];
+extern unsigned char plugin_end_addr[];
+
+/* stub, the entry point is called via its reference in __header to
+ * avoid warning with certain compilers */
+int _start(void) {return 0;}
+
+enum codec_status codec_start(enum codec_entry_call_reason reason)
+{
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+ if (reason == CODEC_LOAD)
+ {
+#ifdef USE_IRAM
+ extern char iramcopy[], iramstart[], iramend[], iedata[], iend[];
+ size_t iram_size = iramend - iramstart;
+ size_t ibss_size = iend - iedata;
+ if (iram_size > 0 || ibss_size > 0)
+ {
+ ci->memcpy(iramstart, iramcopy, iram_size);
+ ci->memset(iedata, 0, ibss_size);
+ /* make the icache (if it exists) up to date with the new code */
+ ci->commit_discard_idcache();
+ /* barrier to prevent reordering iram copy and BSS clearing,
+ * because the BSS segment alias the IRAM copy.
+ */
+ asm volatile ("" ::: "memory");
+ }
+#endif /* PLUGIN_USE_IRAM */
+ ci->memset(plugin_bss_start, 0, plugin_end_addr - plugin_bss_start);
+ /* Some parts of bss may be used via a no-cache alias (at least
+ * portalplayer has this). If we don't clear the cache, those aliases
+ * may read garbage */
+ ci->commit_dcache();
+ }
+#endif /* CONFIG_PLATFORM */
+
+ /* Note: If for any reason codec_main would not be called with CODEC_LOAD
+ * because the above code failed then it must not be ever be called with
+ * any other value and some strategy to avoid doing so must be conceived */
+ return codec_main(reason);
+}
+
+#if defined(CPU_ARM) && (CONFIG_PLATFORM & PLATFORM_NATIVE)
+void __attribute__((naked)) __div0(void)
+{
+ asm volatile("bx %0" : : "r"(ci->__div0));
+}
+#endif
diff --git a/lib/rbcodec/codecs/codecs.h b/lib/rbcodec/codecs/codecs.h
new file mode 100644
index 0000000000..bad8cdd469
--- /dev/null
+++ b/lib/rbcodec/codecs/codecs.h
@@ -0,0 +1,291 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 Björn Stenberg
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef _CODECS_H_
+#define _CODECS_H_
+
+/* instruct simulator code to not redefine any symbols when compiling codecs.
+ (the CODEC macro is defined in codecs.make) */
+#ifdef CODEC
+#define NO_REDEFINES_PLEASE
+#endif
+
+#include <stdbool.h>
+#include <stdlib.h>
+#include "strlcpy.h"
+#include "config.h"
+#include "system.h"
+#include "metadata.h"
+#include "audio.h"
+#ifdef RB_PROFILE
+#include "profile.h"
+#include "thread.h"
+#endif
+#if (CONFIG_CODEC == SWCODEC)
+#ifdef HAVE_RECORDING
+#include "pcm_record.h"
+#endif
+#include "dsp.h"
+#include "dsp-util.h"
+#endif
+
+#include "gcc_extensions.h"
+#include "load_code.h"
+
+#ifdef CODEC
+#if defined(DEBUG) || defined(SIMULATOR)
+#undef DEBUGF
+#define DEBUGF ci->debugf
+#undef LDEBUGF
+#define LDEBUGF ci->debugf
+#else
+#define DEBUGF(...)
+#define LDEBUGF(...)
+#endif
+
+#ifdef ROCKBOX_HAS_LOGF
+#undef LOGF
+#define LOGF ci->logf
+#else
+#define LOGF(...)
+#endif
+
+#endif
+
+/* magic for normal codecs */
+#define CODEC_MAGIC 0x52434F44 /* RCOD */
+/* magic for encoder codecs */
+#define CODEC_ENC_MAGIC 0x52454E43 /* RENC */
+
+/* increase this every time the api struct changes */
+#define CODEC_API_VERSION 44
+
+/* update this to latest version if a change to the api struct breaks
+ backwards compatibility (and please take the opportunity to sort in any
+ new function which are "waiting" at the end of the function table) */
+#define CODEC_MIN_API_VERSION 43
+
+/* reasons for calling codec main entrypoint */
+enum codec_entry_call_reason {
+ CODEC_LOAD = 0,
+ CODEC_UNLOAD
+};
+
+/* codec return codes */
+enum codec_status {
+ CODEC_OK = 0,
+ CODEC_ERROR = -1,
+};
+
+/* codec command action codes */
+enum codec_command_action {
+ CODEC_ACTION_HALT = -1,
+ CODEC_ACTION_NULL = 0,
+ CODEC_ACTION_SEEK_TIME = 1,
+};
+
+/* NOTE: To support backwards compatibility, only add new functions at
+ the end of the structure. Every time you add a new function,
+ remember to increase CODEC_API_VERSION. If you make changes to the
+ existing APIs then also update CODEC_MIN_API_VERSION to current
+ version
+ */
+struct codec_api {
+ off_t filesize; /* Total file length */
+ off_t curpos; /* Current buffer position */
+
+ struct mp3entry *id3; /* TAG metadata pointer */
+ int audio_hid; /* Current audio handle */
+
+ /* The dsp instance to be used for audio output */
+ struct dsp_config *dsp;
+
+ /* Returns buffer to malloc array. Only codeclib should need this. */
+ void* (*codec_get_buffer)(size_t *size);
+ /* Insert PCM data into audio buffer for playback. Playback will start
+ automatically. */
+ void (*pcmbuf_insert)(const void *ch1, const void *ch2, int count);
+ /* Set song position in WPS (value in ms). */
+ void (*set_elapsed)(unsigned long value);
+
+ /* Read next <size> amount bytes from file buffer to <ptr>.
+ Will return number of bytes read or 0 if end of file. */
+ size_t (*read_filebuf)(void *ptr, size_t size);
+ /* Request pointer to file buffer which can be used to read
+ <realsize> amount of data. <reqsize> tells the buffer system
+ how much data it should try to allocate. If <realsize> is 0,
+ end of file is reached. */
+ void* (*request_buffer)(size_t *realsize, size_t reqsize);
+ /* Advance file buffer position by <amount> amount of bytes. */
+ void (*advance_buffer)(size_t amount);
+ /* Seek file buffer to position <newpos> beginning of file. */
+ bool (*seek_buffer)(size_t newpos);
+ /* Codec should call this function when it has done the seeking. */
+ void (*seek_complete)(void);
+ /* Update the current position */
+ void (*set_offset)(size_t value);
+ /* Configure different codec buffer parameters. */
+ void (*configure)(int setting, intptr_t value);
+ /* Obtain command action on what to do next */
+ enum codec_command_action (*get_command)(intptr_t *param);
+ /* Determine whether the track should be looped, if applicable. */
+ bool (*loop_track)(void);
+
+ /* kernel/ system */
+#if defined(CPU_ARM) && CONFIG_PLATFORM & PLATFORM_NATIVE
+ void (*__div0)(void);
+#endif
+ unsigned (*sleep)(unsigned ticks);
+ void (*yield)(void);
+
+#if NUM_CORES > 1
+ unsigned int
+ (*create_thread)(void (*function)(void), void* stack,
+ size_t stack_size, unsigned flags, const char *name
+ IF_PRIO(, int priority)
+ IF_COP(, unsigned int core));
+
+ void (*thread_thaw)(unsigned int thread_id);
+ void (*thread_wait)(unsigned int thread_id);
+ void (*semaphore_init)(struct semaphore *s, int max, int start);
+ int (*semaphore_wait)(struct semaphore *s, int timeout);
+ void (*semaphore_release)(struct semaphore *s);
+#endif /* NUM_CORES */
+
+ void (*commit_dcache)(void);
+ void (*commit_discard_dcache)(void);
+
+ /* strings and memory */
+ char* (*strcpy)(char *dst, const char *src);
+ size_t (*strlen)(const char *str);
+ int (*strcmp)(const char *, const char *);
+ char *(*strcat)(char *s1, const char *s2);
+ void* (*memset)(void *dst, int c, size_t length);
+ void* (*memcpy)(void *out, const void *in, size_t n);
+ void* (*memmove)(void *out, const void *in, size_t n);
+ int (*memcmp)(const void *s1, const void *s2, size_t n);
+ void *(*memchr)(const void *s1, int c, size_t n);
+
+#if defined(DEBUG) || defined(SIMULATOR)
+ void (*debugf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
+#endif
+#ifdef ROCKBOX_HAS_LOGF
+ void (*logf)(const char *fmt, ...) ATTRIBUTE_PRINTF(1, 2);
+#endif
+
+ /* Tremor requires qsort */
+ void (*qsort)(void *base, size_t nmemb, size_t size,
+ int(*compar)(const void *, const void *));
+
+#ifdef RB_PROFILE
+ void (*profile_thread)(void);
+ void (*profstop)(void);
+ void (*profile_func_enter)(void *this_fn, void *call_site);
+ void (*profile_func_exit)(void *this_fn, void *call_site);
+#endif
+
+#ifdef HAVE_RECORDING
+ void (*enc_get_inputs)(struct enc_inputs *inputs);
+ void (*enc_set_parameters)(struct enc_parameters *params);
+ struct enc_chunk_hdr * (*enc_get_chunk)(void);
+ void (*enc_finish_chunk)(void);
+ unsigned char * (*enc_get_pcm_data)(size_t size);
+ size_t (*enc_unget_pcm_data)(size_t size);
+
+ /* file */
+ int (*open)(const char* pathname, int flags, ...);
+ int (*close)(int fd);
+ ssize_t (*read)(int fd, void* buf, size_t count);
+ off_t (*lseek)(int fd, off_t offset, int whence);
+ ssize_t (*write)(int fd, const void* buf, size_t count);
+ int (*round_value_to_list32)(unsigned long value,
+ const unsigned long list[],
+ int count,
+ bool signd);
+#endif
+
+ /* new stuff at the end, sort into place next time
+ the API gets incompatible */
+ void (*commit_discard_idcache)(void);
+};
+
+/* codec header */
+struct codec_header {
+ struct lc_header lc_hdr; /* must be first */
+ enum codec_status(*entry_point)(enum codec_entry_call_reason reason);
+ enum codec_status(*run_proc)(void);
+ struct codec_api **api;
+};
+
+#ifdef CODEC
+#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
+/* plugin_* is correct, codecs use the plugin linker script */
+extern unsigned char plugin_start_addr[];
+extern unsigned char plugin_end_addr[];
+/* decoders */
+#define CODEC_HEADER \
+ const struct codec_header __header \
+ __attribute__ ((section (".header")))= { \
+ { CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
+ plugin_start_addr, plugin_end_addr }, codec_start, \
+ codec_run, &ci };
+/* encoders */
+#define CODEC_ENC_HEADER \
+ const struct codec_header __header \
+ __attribute__ ((section (".header")))= { \
+ { CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, \
+ plugin_start_addr, plugin_end_addr }, codec_start, \
+ codec_run, &ci };
+
+#else /* def SIMULATOR */
+/* decoders */
+#define CODEC_HEADER \
+ const struct codec_header __header \
+ __attribute__((visibility("default"))) = { \
+ { CODEC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
+ codec_start, codec_run, &ci };
+/* encoders */
+#define CODEC_ENC_HEADER \
+ const struct codec_header __header = { \
+ { CODEC_ENC_MAGIC, TARGET_ID, CODEC_API_VERSION, NULL, NULL }, \
+ codec_start, codec_run, &ci };
+#endif /* SIMULATOR */
+#endif /* CODEC */
+
+/* create full codec path from root filenames in audio_formats[]
+ assumes buffer size is MAX_PATH */
+void codec_get_full_path(char *path, const char *codec_root_fn);
+
+/* Returns pointer to and size of free codec RAM */
+void *codec_get_buffer_callback(size_t *size);
+
+/* defined by the codec loader (codec.c) */
+int codec_load_buf(int hid, struct codec_api *api);
+int codec_load_file(const char* codec, struct codec_api *api);
+int codec_run_proc(void);
+int codec_halt(void);
+int codec_close(void);
+
+/* defined by the codec */
+enum codec_status codec_start(enum codec_entry_call_reason reason);
+enum codec_status codec_main(enum codec_entry_call_reason reason);
+enum codec_status codec_run(void);
+
+#endif /* _CODECS_H_ */
diff --git a/lib/rbcodec/codecs/codecs.make b/lib/rbcodec/codecs/codecs.make
new file mode 100644
index 0000000000..919aef2024
--- /dev/null
+++ b/lib/rbcodec/codecs/codecs.make
@@ -0,0 +1,206 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+CODECDIR = $(RBCODEC_BLD)/codecs
+CODECS_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/SOURCES)
+OTHER_SRC += $(CODECS_SRC)
+
+CODECS := $(CODECS_SRC:.c=.codec)
+CODECS := $(subst $(RBCODECLIB_DIR),$(RBCODEC_BLD),$(CODECS))
+
+# the codec helper library
+include $(RBCODECLIB_DIR)/codecs/lib/libcodec.make
+OTHER_INC += -I$(RBCODECLIB_DIR)/codecs/lib
+
+# extra libraries
+CODEC_LIBS := $(EXTRA_LIBS) $(CODECLIB)
+
+# the codec libraries
+include $(RBCODECLIB_DIR)/codecs/demac/libdemac.make
+include $(RBCODECLIB_DIR)/codecs/liba52/liba52.make
+include $(RBCODECLIB_DIR)/codecs/libalac/libalac.make
+include $(RBCODECLIB_DIR)/codecs/libasap/libasap.make
+include $(RBCODECLIB_DIR)/codecs/libasf/libasf.make
+include $(RBCODECLIB_DIR)/codecs/libfaad/libfaad.make
+include $(RBCODECLIB_DIR)/codecs/libffmpegFLAC/libffmpegFLAC.make
+include $(RBCODECLIB_DIR)/codecs/libm4a/libm4a.make
+include $(RBCODECLIB_DIR)/codecs/libmad/libmad.make
+include $(RBCODECLIB_DIR)/codecs/libmusepack/libmusepack.make
+include $(RBCODECLIB_DIR)/codecs/libspc/libspc.make
+include $(RBCODECLIB_DIR)/codecs/libspeex/libspeex.make
+include $(RBCODECLIB_DIR)/codecs/libtremor/libtremor.make
+include $(RBCODECLIB_DIR)/codecs/libwavpack/libwavpack.make
+include $(RBCODECLIB_DIR)/codecs/libwma/libwma.make
+include $(RBCODECLIB_DIR)/codecs/libwmapro/libwmapro.make
+include $(RBCODECLIB_DIR)/codecs/libcook/libcook.make
+include $(RBCODECLIB_DIR)/codecs/librm/librm.make
+include $(RBCODECLIB_DIR)/codecs/libatrac/libatrac.make
+include $(RBCODECLIB_DIR)/codecs/libpcm/libpcm.make
+include $(RBCODECLIB_DIR)/codecs/libtta/libtta.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libay.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libgbs.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libhes.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libnsf.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libsgc.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libvgm.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libkss.make
+include $(RBCODECLIB_DIR)/codecs/libgme/libemu2413.make
+
+# compile flags for codecs
+CODECFLAGS = $(CFLAGS) $(RBCODEC_CFLAGS) -fstrict-aliasing \
+ -I$(RBCODECLIB_DIR)/codecs -I$(RBCODECLIB_DIR)/codecs/lib -DCODEC
+
+# set CODECFLAGS per codec lib, since gcc takes the last -Ox and the last
+# in a -ffoo -fno-foo pair, there is no need to filter them out
+$(A52LIB) : CODECFLAGS += -O1
+$(ALACLIB) : CODECFLAGS += -O1
+$(ASAPLIB) : CODECFLAGS += -O1
+$(ASFLIB) : CODECFLAGS += -O2
+$(ATRACLIB) : CODECFLAGS += -O1
+$(AYLIB) : CODECFLAGS += -O2
+$(COOKLIB): CODECFLAGS += -O1
+$(DEMACLIB) : CODECFLAGS += -O3
+$(FAADLIB) : CODECFLAGS += -O2
+$(FFMPEGFLACLIB) : CODECFLAGS += -O2
+$(GBSLIB) : CODECFLAGS += -O2
+$(HESLIB) : CODECFLAGS += -O2
+$(KSSLIB) : CODECFLAGS += -O2
+$(M4ALIB) : CODECFLAGS += -O3
+$(MUSEPACKLIB) : CODECFLAGS += -O1
+$(NSFLIB) : CODECFLAGS += -O2
+$(PCMSLIB) : CODECFLAGS += -O1
+$(RMLIB) : CODECFLAGS += -O3
+$(SGCLIB) : CODECFLAGS += -O2
+$(SPCLIB) : CODECFLAGS += -O1
+$(TREMORLIB) : CODECFLAGS += -O2
+$(TTALIB) : CODECFLAGS += -O2
+$(VGMLIB) : CODECFLAGS += -O2
+$(EMU2413LIB) : CODECFLAGS += -O3
+$(WAVPACKLIB) : CODECFLAGS += -O1
+$(WMALIB) : CODECFLAGS += -O2
+$(WMAPROLIB) : CODECFLAGS += -O1
+$(WMAVOICELIB) : CODECFLAGS += -O1
+
+# fine-tuning of CODECFLAGS per cpu arch
+ifeq ($(ARCH),arch_arm)
+ # redo per arm generation
+ $(ALACLIB) : CODECFLAGS += -O2
+ $(AYLIB) : CODECFLAGS += -O1
+ $(GBSLIB) : CODECFLAGS += -O1
+ $(HESLIB) : CODECFLAGS += -O1
+ $(KSSLIB) : CODECFLAGS += -O1
+ $(NSFLIB) : CODECFLAGS += -O1
+ $(SGCLIB) : CODECFLAGS += -O1
+ $(VGMLIB) : CODECFLAGS += -O1
+ $(EMU2413LIB) : CODECFLAGS += -O3
+ $(WAVPACKLIB) : CODECFLAGS += -O3
+else ifeq ($(ARCH),arch_m68k)
+ $(A52LIB) : CODECFLAGS += -O2
+ $(ASFLIB) : CODECFLAGS += -O3
+ $(ATRACLIB) : CODECFLAGS += -O2
+ $(COOKLIB): CODECFLAGS += -O2
+ $(DEMACLIB) : CODECFLAGS += -O2
+ $(SPCLIB) : CODECFLAGS += -O3
+ $(WMAPROLIB) : CODECFLAGS += -O3
+ $(WMAVOICELIB) : CODECFLAGS += -O2
+endif
+
+ifeq ($(MEMORYSIZE),2)
+ $(ASFLIB) : CODECFLAGS += -Os
+ $(WMALIB) : CODECFLAGS += -Os
+endif
+
+ifndef APP_TYPE
+ CONFIGFILE := $(FIRMDIR)/export/config/$(MODELNAME).h
+ CODEC_LDS := $(APPSDIR)/plugins/plugin.lds # codecs and plugins use same file
+ CODECLINK_LDS := $(CODECDIR)/codec.link
+endif
+
+CODEC_CRT0 := $(CODECDIR)/codec_crt0.o
+
+$(CODECS): $(CODEC_CRT0) $(CODECLINK_LDS)
+
+$(CODECLINK_LDS): $(CODEC_LDS) $(CONFIGFILE)
+ $(call PRINTS,PP $(@F))
+ $(shell mkdir -p $(dir $@))
+ $(call preprocess2file, $<, $@, -DCODEC)
+
+# codec/library dependencies
+$(CODECDIR)/spc.codec : $(CODECDIR)/libspc.a
+$(CODECDIR)/mpa.codec : $(CODECDIR)/libmad.a
+$(CODECDIR)/a52.codec : $(CODECDIR)/liba52.a
+$(CODECDIR)/flac.codec : $(CODECDIR)/libffmpegFLAC.a
+$(CODECDIR)/vorbis.codec : $(CODECDIR)/libtremor.a
+$(CODECDIR)/speex.codec : $(CODECDIR)/libspeex.a
+$(CODECDIR)/mpc.codec : $(CODECDIR)/libmusepack.a
+$(CODECDIR)/wavpack.codec : $(CODECDIR)/libwavpack.a
+$(CODECDIR)/alac.codec : $(CODECDIR)/libalac.a $(CODECDIR)/libm4a.a
+$(CODECDIR)/aac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/libm4a.a
+$(CODECDIR)/shorten.codec : $(CODECDIR)/libffmpegFLAC.a
+$(CODECDIR)/ape-pre.map : $(CODECDIR)/libdemac-pre.a
+$(CODECDIR)/ape.codec : $(CODECDIR)/libdemac.a
+$(CODECDIR)/wma.codec : $(CODECDIR)/libwma.a $(CODECDIR)/libasf.a
+$(CODECDIR)/wmapro.codec : $(CODECDIR)/libwmapro.a $(CODECDIR)/libasf.a
+$(CODECDIR)/wavpack_enc.codec: $(CODECDIR)/libwavpack.a
+$(CODECDIR)/asap.codec : $(CODECDIR)/libasap.a
+$(CODECDIR)/cook.codec : $(CODECDIR)/libcook.a $(CODECDIR)/librm.a
+$(CODECDIR)/raac.codec : $(CODECDIR)/libfaad.a $(CODECDIR)/librm.a
+$(CODECDIR)/a52_rm.codec : $(CODECDIR)/liba52.a $(CODECDIR)/librm.a
+$(CODECDIR)/atrac3_rm.codec : $(CODECDIR)/libatrac.a $(CODECDIR)/librm.a
+$(CODECDIR)/atrac3_oma.codec : $(CODECDIR)/libatrac.a
+$(CODECDIR)/aiff.codec : $(CODECDIR)/libpcm.a
+$(CODECDIR)/wav.codec : $(CODECDIR)/libpcm.a
+$(CODECDIR)/smaf.codec : $(CODECDIR)/libpcm.a
+$(CODECDIR)/au.codec : $(CODECDIR)/libpcm.a
+$(CODECDIR)/vox.codec : $(CODECDIR)/libpcm.a
+$(CODECDIR)/wav64.codec : $(CODECDIR)/libpcm.a
+$(CODECDIR)/tta.codec : $(CODECDIR)/libtta.a
+$(CODECDIR)/ay.codec : $(CODECDIR)/libay.a
+$(CODECDIR)/gbs.codec : $(CODECDIR)/libgbs.a
+$(CODECDIR)/hes.codec : $(CODECDIR)/libhes.a
+$(CODECDIR)/nsf.codec : $(CODECDIR)/libnsf.a $(CODECDIR)/libemu2413.a
+$(CODECDIR)/sgc.codec : $(CODECDIR)/libsgc.a $(CODECDIR)/libemu2413.a
+$(CODECDIR)/vgm.codec : $(CODECDIR)/libvgm.a $(CODECDIR)/libemu2413.a
+$(CODECDIR)/kss.codec : $(CODECDIR)/libkss.a $(CODECDIR)/libemu2413.a
+
+$(CODECS): $(CODEC_LIBS) # this must be last in codec dependency list
+
+# pattern rule for compiling codecs
+$(CODECDIR)/%.o: $(RBCODECLIB_DIR)/codecs/%.c
+ $(SILENT)mkdir -p $(dir $@)
+ $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) \
+ -I$(dir $<) $(CODECFLAGS) -c $< -o $@
+
+# pattern rule for compiling codecs
+$(CODECDIR)/%.o: $(RBCODECLIB_DIR)/codecs/%.S
+ $(SILENT)mkdir -p $(dir $@)
+ $(call PRINTS,CC $(subst $(ROOTDIR)/,,$<))$(CC) \
+ -I$(dir $<) $(CODECFLAGS) $(ASMFLAGS) -c $< -o $@
+
+ifdef APP_TYPE
+ CODECLDFLAGS = $(SHARED_LDFLAG) -Wl,--gc-sections -Wl,-Map,$(CODECDIR)/$*.map
+ CODECFLAGS += $(SHARED_CFLAGS) # <-- from Makefile
+else
+ CODECLDFLAGS = -T$(CODECLINK_LDS) -Wl,--gc-sections -Wl,-Map,$(CODECDIR)/$*.map
+ CODECFLAGS += -UDEBUG -DNDEBUG
+endif
+CODECLDFLAGS += $(GLOBAL_LDOPTS)
+
+$(CODECDIR)/%-pre.map: $(CODEC_CRT0) $(CODECLINK_LDS) $(CODECDIR)/%.o $(CODECS_LIBS)
+ $(call PRINTS,LD $(@F))$(CC) $(CODECFLAGS) -o $(CODECDIR)/$*-pre.elf \
+ $(filter %.o, $^) \
+ $(filter-out $(CODECLIB),$(filter %.a, $+)) $(CODECLIB) \
+ -lgcc $(subst .map,-pre.map,$(CODECLDFLAGS))
+
+$(CODECDIR)/%.codec: $(CODECDIR)/%.o
+ $(call PRINTS,LD $(@F))$(CC) $(CODECFLAGS) -o $(CODECDIR)/$*.elf \
+ $(filter %.o, $^) \
+ $(filter %.a, $+) \
+ -lgcc $(CODECLDFLAGS)
+ $(SILENT)$(call objcopy,$(CODECDIR)/$*.elf,$@)
diff --git a/lib/rbcodec/codecs/cook.c b/lib/rbcodec/codecs/cook.c
new file mode 100644
index 0000000000..55188aad36
--- /dev/null
+++ b/lib/rbcodec/codecs/cook.c
@@ -0,0 +1,202 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2009 Mohamed Tarek
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include <string.h>
+
+#include "logf.h"
+#include "codeclib.h"
+#include "inttypes.h"
+#include "libcook/cook.h"
+
+CODEC_HEADER
+
+static RMContext rmctx IBSS_ATTR_COOK_LARGE_IRAM;
+static RMPacket pkt IBSS_ATTR_COOK_LARGE_IRAM;
+static COOKContext q IBSS_ATTR;
+static int32_t rm_outbuf[2048] IBSS_ATTR_COOK_LARGE_IRAM MEM_ALIGN_ATTR;
+
+static void init_rm(RMContext *rmctx)
+{
+ memcpy(rmctx, (void*)(( (intptr_t)ci->id3->id3v2buf + 3 ) &~ 3), sizeof(RMContext));
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ /* Nothing to do */
+ return CODEC_OK;
+ (void)reason;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ static size_t buff_size;
+ int datasize, res, consumed, i, time_offset;
+ uint8_t *bit_buffer;
+ uint16_t fs,sps,h;
+ uint32_t packet_count;
+ int scrambling_unit_size, num_units;
+ size_t resume_offset;
+ intptr_t param = 0;
+ enum codec_command_action action = CODEC_ACTION_NULL;
+
+ if (codec_init()) {
+ DEBUGF("codec init failed\n");
+ return CODEC_ERROR;
+ }
+
+ resume_offset = ci->id3->offset;
+
+ codec_set_replaygain(ci->id3);
+ ci->memset(&rmctx,0,sizeof(RMContext));
+ ci->memset(&pkt,0,sizeof(RMPacket));
+ ci->memset(&q,0,sizeof(COOKContext));
+
+ ci->seek_buffer(0);
+
+ init_rm(&rmctx);
+
+ ci->configure(DSP_SET_FREQUENCY, ci->id3->frequency);
+ /* cook's sample representation is 21.11
+ * DSP_SET_SAMPLE_DEPTH = 11 (FRACT) + 16 (NATIVE) - 1 (SIGN) = 26 */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 26);
+ ci->configure(DSP_SET_STEREO_MODE, rmctx.nb_channels == 1 ?
+ STEREO_MONO : STEREO_NONINTERLEAVED);
+
+ packet_count = rmctx.nb_packets;
+ rmctx.audio_framesize = rmctx.block_align;
+ rmctx.block_align = rmctx.sub_packet_size;
+ fs = rmctx.audio_framesize;
+ sps= rmctx.block_align;
+ h = rmctx.sub_packet_h;
+ scrambling_unit_size = h * (fs + PACKET_HEADER_SIZE);
+
+ res =cook_decode_init(&rmctx, &q);
+ if(res < 0) {
+ DEBUGF("failed to initialize cook decoder\n");
+ return CODEC_ERROR;
+ }
+
+ /* check for a mid-track resume and force a seek time accordingly */
+ if(resume_offset > rmctx.data_offset + DATA_HEADER_SIZE) {
+ resume_offset -= rmctx.data_offset + DATA_HEADER_SIZE;
+ num_units = (int)resume_offset / scrambling_unit_size;
+ /* put number of subpackets to skip in resume_offset */
+ resume_offset /= (sps + PACKET_HEADER_SIZE);
+ param = (int)resume_offset * ((sps * 8 * 1000)/rmctx.bit_rate);
+ action = CODEC_ACTION_SEEK_TIME;
+ }
+ else {
+ ci->set_elapsed(0);
+ }
+
+ ci->advance_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+
+ /* The main decoder loop */
+seek_start :
+ while(packet_count)
+ {
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
+ consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
+ if(consumed < 0) {
+ DEBUGF("rm_get_packet failed\n");
+ return CODEC_ERROR;
+ }
+
+ for(i = 0; i < rmctx.audio_pkt_cnt*(fs/sps) ; i++)
+ {
+ if (action == CODEC_ACTION_NULL)
+ action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ return CODEC_OK;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ /* Do not allow seeking beyond the file's length */
+ if ((unsigned) param > ci->id3->length) {
+ ci->set_elapsed(ci->id3->length);
+ ci->seek_complete();
+ return CODEC_OK;
+ }
+
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE);
+ packet_count = rmctx.nb_packets;
+ rmctx.audio_pkt_cnt = 0;
+ rmctx.frame_number = 0;
+
+ /* Seek to the start of the track */
+ if (param == 0) {
+ ci->set_elapsed(0);
+ ci->seek_complete();
+ action = CODEC_ACTION_NULL;
+ goto seek_start;
+ }
+ num_units = (param/(sps*1000*8/rmctx.bit_rate))/(h*(fs/sps));
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * num_units);
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
+ consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
+ if(consumed < 0) {
+ DEBUGF("rm_get_packet failed\n");
+ ci->seek_complete();
+ return CODEC_ERROR;
+ }
+ packet_count = rmctx.nb_packets - rmctx.audio_pkt_cnt * num_units;
+ rmctx.frame_number = (param/(sps*1000*8/rmctx.bit_rate));
+ while(rmctx.audiotimestamp > (unsigned) param) {
+ rmctx.audio_pkt_cnt = 0;
+ ci->seek_buffer(rmctx.data_offset + DATA_HEADER_SIZE + consumed * (num_units-1));
+ bit_buffer = (uint8_t *) ci->request_buffer(&buff_size, scrambling_unit_size);
+ consumed = rm_get_packet(&bit_buffer, &rmctx, &pkt);
+ packet_count += rmctx.audio_pkt_cnt;
+ num_units--;
+ }
+ time_offset = param - rmctx.audiotimestamp;
+ i = (time_offset/((sps * 8 * 1000)/rmctx.bit_rate));
+ ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);
+ ci->seek_complete();
+ }
+
+ action = CODEC_ACTION_NULL;
+
+ res = cook_decode_frame(&rmctx,&q, rm_outbuf, &datasize, pkt.frames[i], rmctx.block_align);
+ rmctx.frame_number++;
+
+ /* skip the first two frames; no valid audio */
+ if(rmctx.frame_number < 3) continue;
+
+ if(res != rmctx.block_align) {
+ DEBUGF("codec error\n");
+ return CODEC_ERROR;
+ }
+
+ ci->pcmbuf_insert(rm_outbuf,
+ rm_outbuf+q.samples_per_channel,
+ q.samples_per_channel);
+ ci->set_elapsed(rmctx.audiotimestamp+(1000*8*sps/rmctx.bit_rate)*i);
+ }
+ packet_count -= rmctx.audio_pkt_cnt;
+ rmctx.audio_pkt_cnt = 0;
+ ci->advance_buffer(consumed);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/demac/COPYING b/lib/rbcodec/codecs/demac/COPYING
new file mode 100644
index 0000000000..d511905c16
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/COPYING
@@ -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.
diff --git a/lib/rbcodec/codecs/demac/Makefile b/lib/rbcodec/codecs/demac/Makefile
new file mode 100644
index 0000000000..7843be6e49
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/Makefile
@@ -0,0 +1,42 @@
+# $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 -g -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) $(CFLAGS) -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
+
+clean:
+ rm -f $(OUTPUT) $(OBJS) *~ */*~
diff --git a/lib/rbcodec/codecs/demac/README b/lib/rbcodec/codecs/demac/README
new file mode 100644
index 0000000000..73a1c22485
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/README
@@ -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
+"lib/rbcodec/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/lib/rbcodec/codecs/demac demac
+
+Or browse the source code online here:
+
+http://svn.rockbox.org/viewvc.cgi/trunk/lib/rbcodec/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.
diff --git a/lib/rbcodec/codecs/demac/demac.c b/lib/rbcodec/codecs/demac/demac.c
new file mode 100644
index 0000000000..3e97fff2c9
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/demac.c
@@ -0,0 +1,281 @@
+/*
+
+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/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 == 8) {
+ for (i = 0 ; i < blockstodecode ; i++)
+ {
+ /* 8 bit WAV uses unsigned samples */
+ *(p++) = (decoded0[i] + 0x80) & 0xff;
+
+ if (ape_ctx.channels == 2) {
+ *(p++) = (decoded1[i] + 0x80) & 0xff;
+ }
+ }
+ } else if (ape_ctx.bps == 16) {
+ for (i = 0 ; i < blockstodecode ; i++)
+ {
+ sample16 = decoded0[i];
+ *(p++) = sample16 & 0xff;
+ *(p++) = (sample16 >> 8) & 0xff;
+
+ if (ape_ctx.channels == 2) {
+ sample16 = decoded1[i];
+ *(p++) = sample16 & 0xff;
+ *(p++) = (sample16 >> 8) & 0xff;
+ }
+ }
+ } else if (ape_ctx.bps == 24) {
+ for (i = 0 ; i < blockstodecode ; i++)
+ {
+ sample32 = decoded0[i];
+ *(p++) = sample32 & 0xff;
+ *(p++) = (sample32 >> 8) & 0xff;
+ *(p++) = (sample32 >> 16) & 0xff;
+
+ if (ape_ctx.channels == 2) {
+ sample32 = decoded1[i];
+ *(p++) = sample32 & 0xff;
+ *(p++) = (sample32 >> 8) & 0xff;
+ *(p++) = (sample32 >> 16) & 0xff;
+ }
+ }
+ }
+
+#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;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac.make b/lib/rbcodec/codecs/demac/libdemac.make
new file mode 100644
index 0000000000..6f64b2ff10
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac.make
@@ -0,0 +1,35 @@
+# __________ __ ___.
+# Open \______ \ ____ ____ | | _\_ |__ _______ ___
+# Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+# Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+# Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+# \/ \/ \/ \/ \/
+# $Id$
+#
+
+# libdemac
+DEMACLIB := $(CODECDIR)/libdemac.a
+DEMACLIB_SRC := $(call preprocess, $(RBCODECLIB_DIR)/codecs/demac/libdemac/SOURCES)
+DEMACLIB_OBJ := $(call c2obj, $(DEMACLIB_SRC))
+OTHER_SRC += $(DEMACLIB_SRC)
+ifeq ($(ARCH),arch_arm)
+OTHER_SRC += $(RBCODECLIB_DIR)/codecs/demac/libdemac/udiv32_arm-pre.S
+endif
+DEMACLIB_PRE := $(subst .a,-pre.a,$(DEMACLIB))
+DEMACLIB_OBJ_PRE := $(subst udiv32_arm.o,udiv32_arm-pre.o,$(DEMACLIB_OBJ))
+
+$(DEMACLIB_PRE): $(DEMACLIB_OBJ_PRE)
+ $(SILENT)$(shell rm -f $@)
+ $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
+
+$(DEMACLIB): $(DEMACLIB_OBJ)
+ $(SILENT)$(shell rm -f $@)
+ $(call PRINTS,AR $(@F))$(AR) rcs $@ $^ >/dev/null
+
+$(CODECDIR)/ape_free_iram.h: $(CODECDIR)/ape-pre.map
+ $(call PRINTS,GEN $(@F))perl -an \
+ -e 'if(/^PLUGIN_IRAM/){$$istart=hex($$F[1]);$$ilen=hex($$F[2])}' \
+ -e 'if(/iend = /){$$iend=hex($$F[0]);}' \
+ -e '}{if($$ilen){print"#define FREE_IRAM ".($$ilen+$$istart-$$iend)."\n";}' \
+ $(CODECDIR)/ape-pre.map \
+ > $@
diff --git a/lib/rbcodec/codecs/demac/libdemac/SOURCES b/lib/rbcodec/codecs/demac/libdemac/SOURCES
new file mode 100644
index 0000000000..018f35a73c
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/SOURCES
@@ -0,0 +1,15 @@
+predictor.c
+#ifdef CPU_ARM
+predictor-arm.S
+udiv32_arm.S
+#elif defined CPU_COLDFIRE
+predictor-cf.S
+#endif
+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
diff --git a/lib/rbcodec/codecs/demac/libdemac/crc.c b/lib/rbcodec/codecs/demac/libdemac/crc.c
new file mode 100644
index 0000000000..fa3ea89d7e
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/crc.c
@@ -0,0 +1,120 @@
+/*
+
+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 "demac.h"
+
+static const 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;
+}
+
diff --git a/lib/rbcodec/codecs/demac/libdemac/decoder.c b/lib/rbcodec/codecs/demac/libdemac/decoder.c
new file mode 100644
index 0000000000..b0339a75d9
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/decoder.c
@@ -0,0 +1,216 @@
+/*
+
+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"
+#include "demac_config.h"
+
+/* Statically allocate the filter buffers */
+
+#ifdef FILTER256_IRAM
+static filter_int filterbuf32[(32*3 + FILTER_HISTORY_SIZE) * 2]
+ IBSS_ATTR_DEMAC MEM_ALIGN_ATTR;
+ /* 2432 or 4864 bytes */
+static filter_int filterbuf256[(256*3 + FILTER_HISTORY_SIZE) * 2]
+ IBSS_ATTR_DEMAC MEM_ALIGN_ATTR;
+ /* 5120 or 10240 bytes */
+#define FILTERBUF64 filterbuf256
+#define FILTERBUF32 filterbuf32
+#define FILTERBUF16 filterbuf32
+#else
+static filter_int filterbuf64[(64*3 + FILTER_HISTORY_SIZE) * 2]
+ IBSS_ATTR_DEMAC MEM_ALIGN_ATTR;
+ /* 2432 or 4864 bytes */
+static filter_int filterbuf256[(256*3 + FILTER_HISTORY_SIZE) * 2]
+ MEM_ALIGN_ATTR; /* 5120 or 10240 bytes */
+#define FILTERBUF64 filterbuf64
+#define FILTERBUF32 filterbuf64
+#define FILTERBUF16 filterbuf64
+#endif
+
+/* This is only needed for "insane" files, and no current Rockbox targets
+ can hope to decode them in realtime, except the Gigabeat S (at 528MHz). */
+static filter_int filterbuf1280[(1280*3 + FILTER_HISTORY_SIZE) * 2]
+ IBSS_ATTR_DEMAC_INSANEBUF MEM_ALIGN_ATTR;
+ /* 17408 or 34816 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->predictor);
+
+ switch (ape_ctx->compressiontype)
+ {
+ case 2000:
+ init_filter_16_11(FILTERBUF16);
+ break;
+
+ case 3000:
+ init_filter_64_11(FILTERBUF64);
+ 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 ICODE_ATTR_DEMAC decode_chunk(struct ape_ctx_t* ape_ctx,
+ unsigned char* inbuffer, int* firstbyte,
+ int* bytesconsumed,
+ int32_t* decoded0, int32_t* decoded1,
+ int count)
+{
+ 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|APE_FRAMECODE_STEREO_SILENCE))
+ == APE_FRAMECODE_PSEUDO_STEREO)) {
+
+ entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed,
+ decoded0, NULL, count);
+
+ if (ape_ctx->frameflags & APE_FRAMECODE_MONO_SILENCE) {
+ /* We are pure silence, so we're done. */
+ return 0;
+ }
+
+ switch (ape_ctx->compressiontype)
+ {
+ case 2000:
+ apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count);
+ break;
+
+ case 3000:
+ apply_filter_64_11(ape_ctx->fileversion,0,decoded0,count);
+ break;
+
+ case 4000:
+ apply_filter_32_10(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count);
+ break;
+
+ case 5000:
+ apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_1280_15(ape_ctx->fileversion,0,decoded0,count);
+ }
+
+ /* Now apply the predictor decoding */
+ predictor_decode_mono(&ape_ctx->predictor,decoded0,count);
+
+ if (ape_ctx->channels==2) {
+ /* Pseudo-stereo - copy left channel to right channel */
+ while (count--)
+ {
+ left = *decoded0;
+ *(decoded1++) = *(decoded0++) = SCALE(left);
+ }
+ }
+#ifdef ROCKBOX
+ else {
+ /* Scale to output depth */
+ while (count--)
+ {
+ left = *decoded0;
+ *(decoded0++) = SCALE(left);
+ }
+ }
+#endif
+ } else { /* Stereo */
+ entropy_decode(ape_ctx, inbuffer, firstbyte, bytesconsumed,
+ decoded0, decoded1, count);
+
+ if ((ape_ctx->frameflags & APE_FRAMECODE_STEREO_SILENCE)
+ == APE_FRAMECODE_STEREO_SILENCE) {
+ /* We are pure silence, so we're done. */
+ return 0;
+ }
+
+ /* Apply filters - compression type 1000 doesn't have any */
+ switch (ape_ctx->compressiontype)
+ {
+ case 2000:
+ apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_16_11(ape_ctx->fileversion,1,decoded1,count);
+ break;
+
+ case 3000:
+ apply_filter_64_11(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_64_11(ape_ctx->fileversion,1,decoded1,count);
+ break;
+
+ case 4000:
+ apply_filter_32_10(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_32_10(ape_ctx->fileversion,1,decoded1,count);
+ apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_256_13(ape_ctx->fileversion,1,decoded1,count);
+ break;
+
+ case 5000:
+ apply_filter_16_11(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_16_11(ape_ctx->fileversion,1,decoded1,count);
+ apply_filter_256_13(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_256_13(ape_ctx->fileversion,1,decoded1,count);
+ apply_filter_1280_15(ape_ctx->fileversion,0,decoded0,count);
+ apply_filter_1280_15(ape_ctx->fileversion,1,decoded1,count);
+ }
+
+ /* Now apply the predictor decoding */
+ predictor_decode_stereo(&ape_ctx->predictor,decoded0,decoded1,count);
+
+ /* Decorrelate and scale to output depth */
+ while (count--)
+ {
+ left = *decoded1 - (*decoded0 / 2);
+ right = left + *decoded0;
+
+ *(decoded0++) = SCALE(left);
+ *(decoded1++) = SCALE(right);
+ }
+ }
+ return 0;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/decoder.h b/lib/rbcodec/codecs/demac/libdemac/decoder.h
new file mode 100644
index 0000000000..aeac569509
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/decoder.h
@@ -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
diff --git a/lib/rbcodec/codecs/demac/libdemac/demac.h b/lib/rbcodec/codecs/demac/libdemac/demac.h
new file mode 100644
index 0000000000..696b2aba73
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/demac.h
@@ -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
diff --git a/lib/rbcodec/codecs/demac/libdemac/demac_config.h b/lib/rbcodec/codecs/demac/libdemac/demac_config.h
new file mode 100644
index 0000000000..fa4f008036
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/demac_config.h
@@ -0,0 +1,145 @@
+/*
+
+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 _DEMAC_CONFIG_H
+#define _DEMAC_CONFIG_H
+
+/* Build-time choices for libdemac.
+ * Note that this file is included by both .c and .S files. */
+
+#ifdef ROCKBOX
+
+#include "config.h"
+
+#ifndef __ASSEMBLER__
+#include "codeclib.h"
+#include <codecs.h>
+#endif
+
+#define APE_OUTPUT_DEPTH 29
+
+/* On ARMv4, using 32 bit ints for the filters is faster. */
+#if defined(CPU_ARM) && (ARM_ARCH == 4)
+#define FILTER_BITS 32
+#endif
+
+#if !defined(CPU_PP) && !defined(CPU_S5L870X)
+#define FILTER256_IRAM
+#endif
+
+#if CONFIG_CPU == PP5002 || defined(CPU_S5L870X)
+/* Code and data IRAM for speed (PP5002 has a broken cache), not enough IRAM
+ * for the insane filter buffer. Reciprocal table for division in IRAM. */
+#define ICODE_SECTION_DEMAC_ARM .icode
+#define ICODE_ATTR_DEMAC ICODE_ATTR
+#define ICONST_ATTR_DEMAC ICONST_ATTR
+#define IBSS_ATTR_DEMAC IBSS_ATTR
+#define IBSS_ATTR_DEMAC_INSANEBUF
+
+#elif CONFIG_CPU == PP5020
+/* Code and small data in DRAM for speed (PP5020 IRAM isn't completely single
+ * cycle). Insane filter buffer not in IRAM in favour of reciprocal table for
+ * divison. Decoded data buffers should be in IRAM (defined by the caller). */
+#define ICODE_SECTION_DEMAC_ARM .text
+#define ICODE_ATTR_DEMAC
+#define ICONST_ATTR_DEMAC
+#define IBSS_ATTR_DEMAC
+#define IBSS_ATTR_DEMAC_INSANEBUF
+
+#elif CONFIG_CPU == PP5022
+/* Code in DRAM, data in IRAM. Insane filter buffer not in IRAM in favour of
+ * reciprocal table for divison */
+#define ICODE_SECTION_DEMAC_ARM .text
+#define ICODE_ATTR_DEMAC
+#define ICONST_ATTR_DEMAC ICONST_ATTR
+#define IBSS_ATTR_DEMAC IBSS_ATTR
+#define IBSS_ATTR_DEMAC_INSANEBUF
+
+#else
+/* Code in DRAM, data in IRAM, including insane filter buffer. */
+#define ICODE_SECTION_DEMAC_ARM .text
+#define ICODE_ATTR_DEMAC
+#define ICONST_ATTR_DEMAC ICONST_ATTR
+#define IBSS_ATTR_DEMAC IBSS_ATTR
+#define IBSS_ATTR_DEMAC_INSANEBUF IBSS_ATTR
+#endif
+
+#else /* !ROCKBOX */
+
+#define APE_OUTPUT_DEPTH (ape_ctx->bps)
+
+#define MEM_ALIGN_ATTR __attribute__((aligned(16)))
+ /* adjust to target architecture for best performance */
+
+#define ICODE_ATTR_DEMAC
+#define ICONST_ATTR_DEMAC
+#define IBSS_ATTR_DEMAC
+#define IBSS_ATTR_DEMAC_INSANEBUF
+
+/* Use to give gcc hints on which branch is most likely taken */
+#if defined(__GNUC__) && __GNUC__ >= 3
+#define LIKELY(x) __builtin_expect(!!(x), 1)
+#define UNLIKELY(x) __builtin_expect(!!(x), 0)
+#else
+#define LIKELY(x) (x)
+#define UNLIKELY(x) (x)
+#endif
+
+#endif /* !ROCKBOX */
+
+/* Defaults */
+
+#ifndef FILTER_HISTORY_SIZE
+#define FILTER_HISTORY_SIZE 512
+#endif
+
+#ifndef PREDICTOR_HISTORY_SIZE
+#define PREDICTOR_HISTORY_SIZE 512
+#endif
+
+#ifndef FILTER_BITS
+#define FILTER_BITS 16
+#endif
+
+
+#ifndef __ASSEMBLER__
+
+#if defined(CPU_ARM) && (ARM_ARCH < 5 || defined(USE_IRAM))
+/* optimised unsigned integer division for ARMv4, in IRAM */
+unsigned udiv32_arm(unsigned a, unsigned b);
+#define UDIV32(a, b) udiv32_arm(a, b)
+#else
+/* default */
+#define UDIV32(a, b) (a / b)
+#endif
+
+#include <inttypes.h>
+#if FILTER_BITS == 32
+typedef int32_t filter_int;
+#elif FILTER_BITS == 16
+typedef int16_t filter_int;
+#endif
+#endif
+
+#endif /* _DEMAC_CONFIG_H */
diff --git a/lib/rbcodec/codecs/demac/libdemac/entropy.c b/lib/rbcodec/codecs/demac/libdemac/entropy.c
new file mode 100644
index 0000000000..1cef979808
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/entropy.c
@@ -0,0 +1,464 @@
+/*
+
+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 "demac_config.h"
+
+#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_DEMAC =
+{
+ 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_DEMAC =
+{
+ 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_DEMAC =
+{
+ 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_DEMAC =
+{
+ 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 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. 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_DEMAC;
+static int bytebufferoffset IBSS_ATTR_DEMAC;
+
+static inline void skip_byte(void)
+{
+ bytebufferoffset--;
+ bytebuffer += bytebufferoffset & 4;
+ bytebufferoffset &= 3;
+}
+
+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 IBSS_ATTR_DEMAC;
+
+/* 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)
+{
+ range_dec_normalize();
+ rc.help = UDIV32(rc.range, tot_f);
+ return UDIV32(rc.low, rc.help);
+}
+
+static inline int range_decode_culshift(int shift)
+{
+ range_dec_normalize();
+ rc.help = rc.range >> shift;
+ return UDIV32(rc.low, rc.help);
+}
+
+
+/* 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)
+{
+ rc.low -= rc.help * lt_f;
+ 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 unsigned 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 */
+}
+
+/*
+ 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_DEMAC;
+static struct rice_t riceY IBSS_ATTR_DEMAC;
+
+static inline void update_rice(struct rice_t* rice, int x)
+{
+ rice->ksum += ((x + 1) / 2) - ((rice->ksum + 16) >> 5);
+
+ if (UNLIKELY(rice->k == 0)) {
+ rice->k = 1;
+ } else {
+ uint32_t lim = 1 << (rice->k + 4);
+ if (UNLIKELY(rice->ksum < lim)) {
+ rice->k--;
+ } else if (UNLIKELY(rice->ksum >= 2 * lim)) {
+ rice->k++;
+ }
+ }
+}
+
+static inline int entropy_decode3980(struct rice_t* rice)
+{
+ int base, x, pivot, overflow;
+
+ pivot = rice->ksum >> 5;
+ if (UNLIKELY(pivot == 0))
+ pivot=1;
+
+ overflow = range_get_symbol_3980();
+
+ if (UNLIKELY(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_culshift(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 (UNLIKELY(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;
+}
+
+void ICODE_ATTR_DEMAC 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_LEFT_SILENCE)
+ && ((ape_ctx->frameflags & APE_FRAMECODE_RIGHT_SILENCE)
+ || (decoded1 == NULL))) {
+ /* We are pure silence, just memset the output buffer. */
+ memset(decoded0, 0, blockstodecode * sizeof(int32_t));
+ if (decoded1 != NULL)
+ memset(decoded1, 0, blockstodecode * sizeof(int32_t));
+ } else {
+ if (ape_ctx->fileversion > 3970) {
+ while (LIKELY(blockstodecode--)) {
+ *(decoded0++) = entropy_decode3980(&riceY);
+ if (decoded1 != NULL)
+ *(decoded1++) = entropy_decode3980(&riceX);
+ }
+ } else {
+ while (LIKELY(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;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/entropy.h b/lib/rbcodec/codecs/demac/libdemac/entropy.h
new file mode 100644
index 0000000000..fac2a44d99
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/entropy.h
@@ -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);
+
+void entropy_decode(struct ape_ctx_t* ape_ctx,
+ unsigned char* inbuffer, int* firstbyte,
+ int* bytesconsumed,
+ int32_t* decoded0, int32_t* decoded1,
+ int blockstodecode);
+
+#endif
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter.c b/lib/rbcodec/codecs/demac/libdemac/filter.c
new file mode 100644
index 0000000000..903885cf00
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter.c
@@ -0,0 +1,296 @@
+/*
+
+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 "demac_config.h"
+
+#if FILTER_BITS == 32
+
+#if defined(CPU_ARM) && (ARM_ARCH == 4)
+#include "vector_math32_armv4.h"
+#else
+#include "vector_math_generic.h"
+#endif
+
+#else /* FILTER_BITS == 16 */
+
+#ifdef CPU_COLDFIRE
+#include "vector_math16_cf.h"
+#elif defined(CPU_ARM) && (ARM_ARCH >= 7)
+#include "vector_math16_armv7.h"
+#elif defined(CPU_ARM) && (ARM_ARCH >= 6)
+#include "vector_math16_armv6.h"
+#elif defined(CPU_ARM) && (ARM_ARCH >= 5)
+/* Assume all our ARMv5 targets are ARMv5te(j) */
+#include "vector_math16_armv5te.h"
+#elif (defined(__i386__) || defined(__i486__)) && defined(__MMX__) \
+ || defined(__x86_64__)
+#include "vector_math16_mmx.h"
+#else
+#include "vector_math_generic.h"
+#endif
+
+#endif /* FILTER_BITS */
+
+struct filter_t {
+ filter_int* coeffs; /* ORDER entries */
+
+ /* We store all the filter delays in a single buffer */
+ filter_int* history_end;
+
+ filter_int* delay;
+ filter_int* 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 */
+
+/* Convert from (32-FRACBITS).FRACBITS fixed-point format to an
+ integer (rounding to nearest). */
+#define FP_HALF (1 << (FRACBITS - 1)) /* 0.5 in fixed-point format. */
+#define FP_TO_INT(x) ((x + FP_HALF) >> FRACBITS) /* round(x) */
+
+#ifdef CPU_ARM
+#if ARM_ARCH >= 6
+#define SATURATE(x) ({int __res; asm("ssat %0, #16, %1" : "=r"(__res) : "r"(x)); __res; })
+#else /* ARM_ARCH < 6 */
+/* Keeping the asr #31 outside of the asm allows loads to be scheduled between
+ it and the rest of the block on ARM9E, with the load's result latency filled
+ by the other calculations. */
+#define SATURATE(x) ({ \
+ int __res = (x) >> 31; \
+ asm volatile ( \
+ "teq %0, %1, asr #15\n\t" \
+ "moveq %0, %1\n\t" \
+ "eorne %0, %0, #0xff\n\t" \
+ "eorne %0, %0, #0x7f00" \
+ : "+r" (__res) : "r" (x) : "cc" \
+ ); \
+ __res; \
+})
+#endif /* ARM_ARCH */
+#else /* CPU_ARM */
+#define SATURATE(x) (LIKELY((x) == (int16_t)(x)) ? (x) : ((x) >> 31) ^ 0x7FFF)
+#endif
+
+/* Apply the filter with state f to count entries in data[] */
+
+static void ICODE_ATTR_DEMAC do_apply_filter_3980(struct filter_t* f,
+ int32_t* data, int count)
+{
+ int res;
+ int absres;
+
+#ifdef PREPARE_SCALARPRODUCT
+ PREPARE_SCALARPRODUCT
+#endif
+
+ while(LIKELY(count--))
+ {
+#ifdef FUSED_VECTOR_MATH
+ if (LIKELY(*data != 0)) {
+ if (*data < 0)
+ res = vector_sp_add(f->coeffs, f->delay - ORDER,
+ f->adaptcoeffs - ORDER);
+ else
+ res = vector_sp_sub(f->coeffs, f->delay - ORDER,
+ f->adaptcoeffs - ORDER);
+ } else {
+ res = scalarproduct(f->coeffs, f->delay - ORDER);
+ }
+ res = FP_TO_INT(res);
+#else
+ res = FP_TO_INT(scalarproduct(f->coeffs, f->delay - ORDER));
+
+ if (LIKELY(*data != 0)) {
+ if (*data < 0)
+ vector_add(f->coeffs, f->adaptcoeffs - ORDER);
+ else
+ vector_sub(f->coeffs, f->adaptcoeffs - ORDER);
+ }
+#endif
+
+ 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 (UNLIKELY(absres > 3 * f->avg))
+ *f->adaptcoeffs = ((res >> 25) & 64) - 32;
+ else if (3 * absres > 4 * f->avg)
+ *f->adaptcoeffs = ((res >> 26) & 32) - 16;
+ else if (LIKELY(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 (UNLIKELY(f->delay == f->history_end)) {
+ memmove(f->coeffs + ORDER, f->delay - (ORDER*2),
+ (ORDER*2) * sizeof(filter_int));
+ f->adaptcoeffs = f->coeffs + ORDER*2;
+ f->delay = f->coeffs + ORDER*3;
+ }
+ }
+}
+
+static void ICODE_ATTR_DEMAC do_apply_filter_3970(struct filter_t* f,
+ int32_t* data, int count)
+{
+ int res;
+
+#ifdef PREPARE_SCALARPRODUCT
+ PREPARE_SCALARPRODUCT
+#endif
+
+ while(LIKELY(count--))
+ {
+#ifdef FUSED_VECTOR_MATH
+ if (LIKELY(*data != 0)) {
+ if (*data < 0)
+ res = vector_sp_add(f->coeffs, f->delay - ORDER,
+ f->adaptcoeffs - ORDER);
+ else
+ res = vector_sp_sub(f->coeffs, f->delay - ORDER,
+ f->adaptcoeffs - ORDER);
+ } else {
+ res = scalarproduct(f->coeffs, f->delay - ORDER);
+ }
+ res = FP_TO_INT(res);
+#else
+ res = FP_TO_INT(scalarproduct(f->coeffs, f->delay - ORDER));
+
+ if (LIKELY(*data != 0)) {
+ if (*data < 0)
+ vector_add(f->coeffs, f->adaptcoeffs - ORDER);
+ else
+ vector_sub(f->coeffs, f->adaptcoeffs - ORDER);
+ }
+#endif
+
+ /* 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 (UNLIKELY(f->delay == f->history_end)) {
+ memmove(f->coeffs + ORDER, f->delay - (ORDER*2),
+ (ORDER*2) * sizeof(filter_int));
+ f->adaptcoeffs = f->coeffs + ORDER*2;
+ f->delay = f->coeffs + ORDER*3;
+ }
+ }
+}
+
+static struct filter_t filter[2] IBSS_ATTR_DEMAC;
+
+static void do_init_filter(struct filter_t* f, filter_int* buf)
+{
+ f->coeffs = buf;
+ f->history_end = buf + ORDER*3 + FILTER_HISTORY_SIZE;
+
+ /* Init pointers */
+ f->adaptcoeffs = f->coeffs + ORDER*2;
+ f->delay = f->coeffs + ORDER*3;
+
+ /* Zero coefficients and history buffer */
+ memset(f->coeffs, 0, ORDER*3 * sizeof(filter_int));
+
+ /* Zero the running average */
+ f->avg = 0;
+}
+
+void INIT_FILTER(filter_int* buf)
+{
+ do_init_filter(&filter[0], buf);
+ do_init_filter(&filter[1], buf + ORDER*3 + FILTER_HISTORY_SIZE);
+}
+
+void ICODE_ATTR_DEMAC APPLY_FILTER(int fileversion, int channel,
+ int32_t* data, int count)
+{
+ if (fileversion >= 3980)
+ do_apply_filter_3980(&filter[channel], data, count);
+ else
+ do_apply_filter_3970(&filter[channel], data, count);
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter.h b/lib/rbcodec/codecs/demac/libdemac/filter.h
new file mode 100644
index 0000000000..609ea12496
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter.h
@@ -0,0 +1,50 @@
+/*
+
+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 "demac_config.h"
+
+void init_filter_16_11(filter_int* buf);
+void apply_filter_16_11(int fileversion, int channel,
+ int32_t* decoded, int count);
+
+void init_filter_64_11(filter_int* buf);
+void apply_filter_64_11(int fileversion, int channel,
+ int32_t* decoded, int count);
+
+void init_filter_32_10(filter_int* buf);
+void apply_filter_32_10(int fileversion, int channel,
+ int32_t* decoded, int count);
+
+void init_filter_256_13(filter_int* buf);
+void apply_filter_256_13(int fileversion, int channel,
+ int32_t* decoded, int count);
+
+void init_filter_1280_15(filter_int* buf);
+void apply_filter_1280_15(int fileversion, int channel,
+ int32_t* decoded, int count);
+
+#endif
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter_1280_15.c b/lib/rbcodec/codecs/demac/libdemac/filter_1280_15.c
new file mode 100644
index 0000000000..f2301fb02a
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter_1280_15.c
@@ -0,0 +1,32 @@
+/*
+
+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 "demac_config.h"
+#ifndef FILTER256_IRAM
+#undef ICODE_ATTR_DEMAC
+#define ICODE_ATTR_DEMAC
+#endif
+#define ORDER 1280
+#define FRACBITS 15
+#include "filter.c"
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter_16_11.c b/lib/rbcodec/codecs/demac/libdemac/filter_16_11.c
new file mode 100644
index 0000000000..94c56e247f
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter_16_11.c
@@ -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"
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter_256_13.c b/lib/rbcodec/codecs/demac/libdemac/filter_256_13.c
new file mode 100644
index 0000000000..9e4b9fcb13
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter_256_13.c
@@ -0,0 +1,32 @@
+/*
+
+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 "demac_config.h"
+#ifndef FILTER256_IRAM
+#undef ICODE_ATTR_DEMAC
+#define ICODE_ATTR_DEMAC
+#endif
+#define ORDER 256
+#define FRACBITS 13
+#include "filter.c"
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter_32_10.c b/lib/rbcodec/codecs/demac/libdemac/filter_32_10.c
new file mode 100644
index 0000000000..5ec85089db
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter_32_10.c
@@ -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"
diff --git a/lib/rbcodec/codecs/demac/libdemac/filter_64_11.c b/lib/rbcodec/codecs/demac/libdemac/filter_64_11.c
new file mode 100644
index 0000000000..cd74fa5f6b
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/filter_64_11.c
@@ -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"
diff --git a/lib/rbcodec/codecs/demac/libdemac/parser.c b/lib/rbcodec/codecs/demac/libdemac/parser.c
new file mode 100644
index 0000000000..2af4a292b8
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/parser.c
@@ -0,0 +1,402 @@
+/*
+
+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 "inttypes.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#include "parser.h"
+
+#ifdef APE_MAX
+#undef APE_MAX
+#endif
+#define APE_MAX(a,b) ((a)>(b)?(a):(b))
+
+
+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->seektablefilepos = ape_ctx->junklength +
+ ape_ctx->descriptorlength +
+ ape_ctx->headerlength;
+
+ ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->descriptorlength +
+ ape_ctx->headerlength + ape_ctx->seektablelength +
+ ape_ctx->wavheaderlength;
+ } else {
+ ape_ctx->headerlength = 32;
+ 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 + 12);
+ ape_ctx->wavheaderlength = get_uint32(buf + 16);
+ ape_ctx->totalframes = get_uint32(buf + 24);
+ ape_ctx->finalframeblocks = get_uint32(buf + 28);
+
+ if (ape_ctx->formatflags & MAC_FORMAT_FLAG_HAS_PEAK_LEVEL)
+ {
+ ape_ctx->headerlength += 4;
+ }
+
+ if (ape_ctx->formatflags & MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS)
+ {
+ ape_ctx->seektablelength = get_uint32(buf + ape_ctx->headerlength);
+ ape_ctx->seektablelength *= sizeof(int32_t);
+ ape_ctx->headerlength += 4;
+ } 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;
+
+ ape_ctx->seektablefilepos = ape_ctx->junklength + ape_ctx->headerlength +
+ ape_ctx->wavheaderlength;
+
+ ape_ctx->firstframe = ape_ctx->junklength + ape_ctx->headerlength +
+ ape_ctx->wavheaderlength + ape_ctx->seektablelength;
+ }
+
+ ape_ctx->totalsamples = ape_ctx->finalframeblocks;
+ if (ape_ctx->totalframes > 1)
+ ape_ctx->totalsamples += ape_ctx->blocksperframe * (ape_ctx->totalframes-1);
+
+ ape_ctx->numseekpoints = APE_MAX(ape_ctx->maxseekpoints,
+ ape_ctx->seektablelength / sizeof(int32_t));
+
+ 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 */
diff --git a/lib/rbcodec/codecs/demac/libdemac/parser.h b/lib/rbcodec/codecs/demac/libdemac/parser.h
new file mode 100644
index 0000000000..6f07deac12
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/parser.h
@@ -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>
+#include "demac_config.h"
+
+/* 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_LEFT_SILENCE 1 /* same as mono */
+#define APE_FRAMECODE_RIGHT_SILENCE 2
+#define APE_FRAMECODE_STEREO_SILENCE 3 /* combined */
+#define APE_FRAMECODE_PSEUDO_STEREO 4
+
+#define PREDICTOR_ORDER 8
+/* Total size of all predictor histories - 50 * sizeof(int32_t) */
+#define PREDICTOR_SIZE 50
+
+
+/* NOTE: This struct is used in predictor-arm.S - any updates need to
+ be reflected there. */
+
+struct predictor_t
+{
+ /* Filter histories */
+ int32_t* buf;
+
+ int32_t YlastA;
+ int32_t XlastA;
+
+ /* NOTE: The order of the next four fields is important for
+ predictor-arm.S */
+ int32_t YfilterB;
+ int32_t XfilterA;
+ int32_t XfilterB;
+ int32_t YfilterA;
+
+ /* Adaption co-efficients */
+ int32_t YcoeffsA[4];
+ int32_t XcoeffsA[4];
+ int32_t YcoeffsB[5];
+ int32_t XcoeffsB[5];
+ int32_t historybuffer[PREDICTOR_HISTORY_SIZE + PREDICTOR_SIZE];
+};
+
+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; /* Seektable buffer */
+ uint32_t maxseekpoints; /* Max seekpoints we can store (size of seektable buffer) */
+ uint32_t numseekpoints; /* Number of seekpoints */
+ int seektablefilepos; /* Location in .ape file of seektable */
+
+ /* Decoder state */
+ uint32_t CRC;
+ int frameflags;
+ int currentframeblocks;
+ int blocksdecoded;
+ struct predictor_t predictor;
+};
+
+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
diff --git a/lib/rbcodec/codecs/demac/libdemac/predictor-arm.S b/lib/rbcodec/codecs/demac/libdemac/predictor-arm.S
new file mode 100644
index 0000000000..92a78ed9b4
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/predictor-arm.S
@@ -0,0 +1,702 @@
+/*
+
+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 "demac_config.h"
+
+ .section ICODE_SECTION_DEMAC_ARM,"ax",%progbits
+
+ .align 2
+
+/* NOTE: The following need to be kept in sync with parser.h */
+
+#define YDELAYA 200
+#define YDELAYB 168
+#define XDELAYA 136
+#define XDELAYB 104
+#define YADAPTCOEFFSA 72
+#define XADAPTCOEFFSA 56
+#define YADAPTCOEFFSB 40
+#define XADAPTCOEFFSB 20
+
+/* struct predictor_t members: */
+#define buf 0 /* int32_t* buf */
+
+#define YlastA 4 /* int32_t YlastA; */
+#define XlastA 8 /* int32_t XlastA; */
+
+#define YfilterB 12 /* int32_t YfilterB; */
+#define XfilterA 16 /* int32_t XfilterA; */
+
+#define XfilterB 20 /* int32_t XfilterB; */
+#define YfilterA 24 /* int32_t YfilterA; */
+
+#define YcoeffsA 28 /* int32_t YcoeffsA[4]; */
+#define XcoeffsA 44 /* int32_t XcoeffsA[4]; */
+#define YcoeffsB 60 /* int32_t YcoeffsB[5]; */
+#define XcoeffsB 80 /* int32_t XcoeffsB[5]; */
+
+#define historybuffer 100 /* int32_t historybuffer[] */
+
+@ Macro for loading 2 registers, for various ARM versions.
+@ Registers must start with an even register, and must be consecutive.
+
+.macro LDR2OFS reg1, reg2, base, offset
+#if ARM_ARCH >= 6
+ ldrd \reg1, [\base, \offset]
+#else /* ARM_ARCH < 6 */
+#ifdef CPU_ARM7TDMI
+ add \reg1, \base, \offset
+ ldmia \reg1, {\reg1, \reg2}
+#else /* ARM9 (v4 and v5) is faster this way */
+ ldr \reg1, [\base, \offset]
+ ldr \reg2, [\base, \offset+4]
+#endif
+#endif /* ARM_ARCH */
+.endm
+
+@ Macro for storing 2 registers, for various ARM versions.
+@ Registers must start with an even register, and must be consecutive.
+
+.macro STR2OFS reg1, reg2, base, offset
+#if ARM_ARCH >= 6
+ strd \reg1, [\base, \offset]
+#else
+ str \reg1, [\base, \offset]
+ str \reg2, [\base, \offset+4]
+#endif
+.endm
+
+ .global predictor_decode_stereo
+ .type predictor_decode_stereo,%function
+
+@ Register usage:
+@
+@ r0-r11 - scratch
+@ r12 - struct predictor_t* p
+@ r14 - int32_t* p->buf
+
+@ void predictor_decode_stereo(struct predictor_t* p,
+@ int32_t* decoded0,
+@ int32_t* decoded1,
+@ int count)
+
+predictor_decode_stereo:
+ stmdb sp!, {r1-r11, lr}
+
+ @ r1 (decoded0) is [sp]
+ @ r2 (decoded1) is [sp, #4]
+ @ r3 (count) is [sp, #8]
+
+ mov r12, r0 @ r12 := p
+ ldr r14, [r0] @ r14 := p->buf
+
+loop:
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@ PREDICTOR Y
+
+@ Predictor Y, Filter A
+
+ ldr r11, [r12, #YlastA] @ r11 := p->YlastA
+
+ add r2, r14, #YDELAYA-12 @ r2 := &p->buf[YDELAYA-3]
+ ldmia r2, {r2, r3, r10} @ r2 := p->buf[YDELAYA-3]
+ @ r3 := p->buf[YDELAYA-2]
+ @ r10 := p->buf[YDELAYA-1]
+
+ add r6, r12, #YcoeffsA
+ ldmia r6, {r6 - r9} @ r6 := p->YcoeffsA[0]
+ @ r7 := p->YcoeffsA[1]
+ @ r8 := p->YcoeffsA[2]
+ @ r9 := p->YcoeffsA[3]
+
+ subs r10, r11, r10 @ r10 := r11 - r10
+
+ STR2OFS r10, r11, r14, #YDELAYA-4
+ @ p->buf[YDELAYA-1] = r10
+ @ p->buf[YDELAYA] = r11
+
+ mul r0, r11, r6 @ r0 := p->buf[YDELAYA] * p->YcoeffsA[0]
+ mla r0, r10, r7, r0 @ r0 += p->buf[YDELAYA-1] * p->YcoeffsA[1]
+ mla r0, r3, r8, r0 @ r0 += p->buf[YDELAYA-2] * p->YcoeffsA[2]
+ mla r0, r2, r9, r0 @ r0 += p->buf[YDELAYA-3] * p->YcoeffsA[3]
+
+ @ flags were set above, in the subs instruction
+ mvngt r10, #0
+ movlt r10, #1 @ r10 := SIGN(r10) (see .c for SIGN macro)
+
+ cmp r11, #0
+ mvngt r11, #0
+ movlt r11, #1 @ r11 := SIGN(r11) (see .c for SIGN macro)
+
+ STR2OFS r10, r11, r14, #YADAPTCOEFFSA-4
+ @ p->buf[YADAPTCOEFFSA-1] := r10
+ @ p->buf[YADAPTCOEFFSA] := r11
+
+ @ NOTE: r0 now contains predictionA - don't overwrite.
+
+@ Predictor Y, Filter B
+
+ LDR2OFS r6, r7, r12, #YfilterB @ r6 := p->YfilterB
+ @ r7 := p->XfilterA
+
+ add r2, r14, #YDELAYB-16 @ r2 := &p->buf[YDELAYB-4]
+ ldmia r2, {r2 - r4, r10} @ r2 := p->buf[YDELAYB-4]
+ @ r3 := p->buf[YDELAYB-3]
+ @ r4 := p->buf[YDELAYB-2]
+ @ r10 := p->buf[YDELAYB-1]
+
+ rsb r6, r6, r6, lsl #5 @ r6 := r6 * 32 - r6 ( == r6*31)
+ sub r11, r7, r6, asr #5 @ r11 (p->buf[YDELAYB]) := r7 - (r6 >> 5)
+
+ str r7, [r12, #YfilterB] @ p->YfilterB := r7 (p->XfilterA)
+
+ add r5, r12, #YcoeffsB
+ ldmia r5, {r5 - r9} @ r5 := p->YcoeffsB[0]
+ @ r6 := p->YcoeffsB[1]
+ @ r7 := p->YcoeffsB[2]
+ @ r8 := p->YcoeffsB[3]
+ @ r9 := p->YcoeffsB[4]
+
+ subs r10, r11, r10 @ r10 := r11 - r10
+
+ STR2OFS r10, r11, r14, #YDELAYB-4
+ @ p->buf[YDELAYB-1] = r10
+ @ p->buf[YDELAYB] = r11
+
+ mul r1, r11, r5 @ r1 := p->buf[YDELAYB] * p->YcoeffsB[0]
+ mla r1, r10, r6, r1 @ r1 += p->buf[YDELAYB-1] * p->YcoeffsB[1]
+ mla r1, r4, r7, r1 @ r1 += p->buf[YDELAYB-2] * p->YcoeffsB[2]
+ mla r1, r3, r8, r1 @ r1 += p->buf[YDELAYB-3] * p->YcoeffsB[3]
+ mla r1, r2, r9, r1 @ r1 += p->buf[YDELAYB-4] * p->YcoeffsB[4]
+
+ @ flags were set above, in the subs instruction
+ mvngt r10, #0
+ movlt r10, #1 @ r10 := SIGN(r10) (see .c for SIGN macro)
+
+ cmp r11, #0
+ mvngt r11, #0
+ movlt r11, #1 @ r11 := SIGN(r11) (see .c for SIGN macro)
+
+ STR2OFS r10, r11, r14, #YADAPTCOEFFSB-4
+ @ p->buf[YADAPTCOEFFSB-1] := r10
+ @ p->buf[YADAPTCOEFFSB] := r11
+
+ @ r0 still contains predictionA
+ @ r1 contains predictionB
+
+ @ Finish Predictor Y
+
+ ldr r2, [sp] @ r2 := decoded0
+ add r0, r0, r1, asr #1 @ r0 := r0 + (r1 >> 1)
+ ldr r4, [r12, #YfilterA] @ r4 := p->YfilterA
+ ldr r3, [r2] @ r3 := *decoded0
+ rsb r4, r4, r4, lsl #5 @ r4 := r4 * 32 - r4 ( == r4*31)
+ add r1, r3, r0, asr #10 @ r1 := r3 + (r0 >> 10)
+ str r1, [r12, #YlastA] @ p->YlastA := r1
+ add r1, r1, r4, asr #5 @ r1 := r1 + (r4 >> 5)
+ str r1, [r12, #YfilterA] @ p->YfilterA := r1
+
+ @ r1 contains p->YfilterA
+ @ r2 contains decoded0
+ @ r3 contains *decoded0
+
+ @ r5, r6, r7, r8, r9 contain p->YcoeffsB[0..4]
+ @ r10, r11 contain p->buf[YADAPTCOEFFSB-1] and p->buf[YADAPTCOEFFSB]
+
+ str r1, [r2], #4 @ *(decoded0++) := r1 (p->YfilterA)
+ str r2, [sp] @ save decoded0
+ cmp r3, #0
+ beq 3f
+
+ add r2, r14, #YADAPTCOEFFSB-16
+ ldmia r2, {r2 - r4} @ r2 := p->buf[YADAPTCOEFFSB-4]
+ @ r3 := p->buf[YADAPTCOEFFSB-3]
+ @ r4 := p->buf[YADAPTCOEFFSB-2]
+ blt 1f
+
+ @ *decoded0 > 0
+
+ sub r5, r5, r11 @ r5 := p->YcoeffsB[0] - p->buf[YADAPTCOEFFSB]
+ sub r6, r6, r10 @ r6 := p->YcoeffsB[1] - p->buf[YADAPTCOEFFSB-1]
+ sub r9, r9, r2 @ r9 := p->YcoeffsB[4] - p->buf[YADAPTCOEFFSB-4]
+ sub r8, r8, r3 @ r8 := p->YcoeffsB[3] - p->buf[YADAPTCOEFFSB-3]
+ sub r7, r7, r4 @ r7 := p->YcoeffsB[2] - p->buf[YADAPTCOEFFSB-2]
+
+ add r0, r12, #YcoeffsB
+ stmia r0, {r5 - r9} @ Save p->YcoeffsB[]
+
+ add r1, r12, #YcoeffsA
+ ldmia r1, {r2 - r5} @ r2 := p->YcoeffsA[0]
+ @ r3 := p->YcoeffsA[1]
+ @ r4 := p->YcoeffsA[2]
+ @ r5 := p->YcoeffsA[3]
+
+ add r6, r14, #YADAPTCOEFFSA-12
+ ldmia r6, {r6 - r9} @ r6 := p->buf[YADAPTCOEFFSA-3]
+ @ r7 := p->buf[YADAPTCOEFFSA-2]
+ @ r8 := p->buf[YADAPTCOEFFSA-1]
+ @ r9 := p->buf[YADAPTCOEFFSA]
+
+ sub r5, r5, r6 @ r5 := p->YcoeffsA[3] - p->buf[YADAPTCOEFFSA-3]
+ sub r4, r4, r7 @ r4 := p->YcoeffsA[2] - p->buf[YADAPTCOEFFSA-2]
+ sub r3, r3, r8 @ r3 := p->YcoeffsA[1] - p->buf[YADAPTCOEFFSA-1]
+ sub r2, r2, r9 @ r2 := p->YcoeffsA[0] - p->buf[YADAPTCOEFFSA]
+
+ b 2f
+
+
+1: @ *decoded0 < 0
+
+ add r5, r5, r11 @ r5 := p->YcoeffsB[0] + p->buf[YADAPTCOEFFSB]
+ add r6, r6, r10 @ r6 := p->YcoeffsB[1] + p->buf[YADAPTCOEFFSB-1]
+ add r9, r9, r2 @ r9 := p->YcoeffsB[4] + p->buf[YADAPTCOEFFSB-4]
+ add r8, r8, r3 @ r9 := p->YcoeffsB[3] + p->buf[YADAPTCOEFFSB-3]
+ add r7, r7, r4 @ r8 := p->YcoeffsB[2] + p->buf[YADAPTCOEFFSB-2]
+
+ add r0, r12, #YcoeffsB
+ stmia r0, {r5 - r9} @ Save p->YcoeffsB[]
+
+ add r1, r12, #YcoeffsA
+ ldmia r1, {r2 - r5} @ r2 := p->YcoeffsA[0]
+ @ r3 := p->YcoeffsA[1]
+ @ r4 := p->YcoeffsA[2]
+ @ r5 := p->YcoeffsA[3]
+
+ add r6, r14, #YADAPTCOEFFSA-12
+ ldmia r6, {r6 - r9} @ r6 := p->buf[YADAPTCOEFFSA-3]
+ @ r7 := p->buf[YADAPTCOEFFSA-2]
+ @ r8 := p->buf[YADAPTCOEFFSA-1]
+ @ r9 := p->buf[YADAPTCOEFFSA]
+
+ add r5, r5, r6 @ r5 := p->YcoeffsA[3] + p->buf[YADAPTCOEFFSA-3]
+ add r4, r4, r7 @ r4 := p->YcoeffsA[2] + p->buf[YADAPTCOEFFSA-2]
+ add r3, r3, r8 @ r3 := p->YcoeffsA[1] + p->buf[YADAPTCOEFFSA-1]
+ add r2, r2, r9 @ r2 := p->YcoeffsA[0] + p->buf[YADAPTCOEFFSA]
+
+2:
+ stmia r1, {r2 - r5} @ Save p->YcoeffsA
+
+3:
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@ PREDICTOR X
+
+@ Predictor X, Filter A
+
+ ldr r11, [r12, #XlastA] @ r11 := p->XlastA
+
+ add r2, r14, #XDELAYA-12 @ r2 := &p->buf[XDELAYA-3]
+ ldmia r2, {r2, r3, r10} @ r2 := p->buf[XDELAYA-3]
+ @ r3 := p->buf[XDELAYA-2]
+ @ r10 := p->buf[XDELAYA-1]
+
+ add r6, r12, #XcoeffsA
+ ldmia r6, {r6 - r9} @ r6 := p->XcoeffsA[0]
+ @ r7 := p->XcoeffsA[1]
+ @ r8 := p->XcoeffsA[2]
+ @ r9 := p->XcoeffsA[3]
+
+ subs r10, r11, r10 @ r10 := r11 - r10
+
+ STR2OFS r10, r11, r14, #XDELAYA-4
+ @ p->buf[XDELAYA-1] = r10
+ @ p->buf[XDELAYA] = r11
+
+ mul r0, r11, r6 @ r0 := p->buf[XDELAYA] * p->XcoeffsA[0]
+ mla r0, r10, r7, r0 @ r0 += p->buf[XDELAYA-1] * p->XcoeffsA[1]
+ mla r0, r3, r8, r0 @ r0 += p->buf[XDELAYA-2] * p->XcoeffsA[2]
+ mla r0, r2, r9, r0 @ r0 += p->buf[XDELAYA-3] * p->XcoeffsA[3]
+
+ @ flags were set above, in the subs instruction
+ mvngt r10, #0
+ movlt r10, #1 @ r10 := SIGN(r10) (see .c for SIGN macro)
+
+ cmp r11, #0
+ mvngt r11, #0
+ movlt r11, #1 @ r11 := SIGN(r11) (see .c for SIGN macro)
+
+ STR2OFS r10, r11, r14, #XADAPTCOEFFSA-4
+ @ p->buf[XADAPTCOEFFSA-1] := r10
+ @ p->buf[XADAPTCOEFFSA] := r11
+
+ @ NOTE: r0 now contains predictionA - don't overwrite.
+
+@ Predictor X, Filter B
+
+ LDR2OFS r6, r7, r12, #XfilterB @ r6 := p->XfilterB
+ @ r7 := p->YfilterA
+
+ add r2, r14, #XDELAYB-16 @ r2 := &p->buf[XDELAYB-4]
+ ldmia r2, {r2 - r4, r10} @ r2 := p->buf[XDELAYB-4]
+ @ r3 := p->buf[XDELAYB-3]
+ @ r4 := p->buf[XDELAYB-2]
+ @ r10 := p->buf[XDELAYB-1]
+
+ rsb r6, r6, r6, lsl #5 @ r6 := r2 * 32 - r6 ( == r6*31)
+ sub r11, r7, r6, asr #5 @ r11 (p->buf[XDELAYB]) := r7 - (r6 >> 5)
+
+ str r7, [r12, #XfilterB] @ p->XfilterB := r7 (p->YfilterA)
+
+ add r5, r12, #XcoeffsB
+ ldmia r5, {r5 - r9} @ r5 := p->XcoeffsB[0]
+ @ r6 := p->XcoeffsB[1]
+ @ r7 := p->XcoeffsB[2]
+ @ r8 := p->XcoeffsB[3]
+ @ r9 := p->XcoeffsB[4]
+
+ subs r10, r11, r10 @ r10 := r11 - r10
+
+ STR2OFS r10, r11, r14, #XDELAYB-4
+ @ p->buf[XDELAYB-1] = r10
+ @ p->buf[XDELAYB] = r11
+
+ mul r1, r11, r5 @ r1 := p->buf[XDELAYB] * p->XcoeffsB[0]
+ mla r1, r10, r6, r1 @ r1 += p->buf[XDELAYB-1] * p->XcoeffsB[1]
+ mla r1, r4, r7, r1 @ r1 += p->buf[XDELAYB-2] * p->XcoeffsB[2]
+ mla r1, r3, r8, r1 @ r1 += p->buf[XDELAYB-3] * p->XcoeffsB[3]
+ mla r1, r2, r9, r1 @ r1 += p->buf[XDELAYB-4] * p->XcoeffsB[4]
+
+ @ flags were set above, in the subs instruction
+ mvngt r10, #0
+ movlt r10, #1 @ r10 := SIGN(r10) (see .c for SIGN macro)
+
+ cmp r11, #0
+ mvngt r11, #0
+ movlt r11, #1 @ r11 := SIGN(r11) (see .c for SIGN macro)
+
+ STR2OFS r10, r11, r14, #XADAPTCOEFFSB-4
+ @ p->buf[XADAPTCOEFFSB-1] := r10
+ @ p->buf[XADAPTCOEFFSB] := r11
+
+ @ r0 still contains predictionA
+ @ r1 contains predictionB
+
+ @ Finish Predictor X
+
+ ldr r2, [sp, #4] @ r2 := decoded1
+ add r0, r0, r1, asr #1 @ r0 := r0 + (r1 >> 1)
+ ldr r4, [r12, #XfilterA] @ r4 := p->XfilterA
+ ldr r3, [r2] @ r3 := *decoded1
+ rsb r4, r4, r4, lsl #5 @ r4 := r4 * 32 - r4 ( == r4*31)
+ add r1, r3, r0, asr #10 @ r1 := r3 + (r0 >> 10)
+ str r1, [r12, #XlastA] @ p->XlastA := r1
+ add r1, r1, r4, asr #5 @ r1 := r1 + (r4 >> 5)
+ str r1, [r12, #XfilterA] @ p->XfilterA := r1
+
+ @ r1 contains p->XfilterA
+ @ r2 contains decoded1
+ @ r3 contains *decoded1
+
+ @ r5, r6, r7, r8, r9 contain p->XcoeffsB[0..4]
+ @ r10, r11 contain p->buf[XADAPTCOEFFSB-1] and p->buf[XADAPTCOEFFSB]
+
+ str r1, [r2], #4 @ *(decoded1++) := r1 (p->XfilterA)
+ str r2, [sp, #4] @ save decoded1
+ cmp r3, #0
+ beq 3f
+
+ add r2, r14, #XADAPTCOEFFSB-16
+ ldmia r2, {r2 - r4} @ r2 := p->buf[XADAPTCOEFFSB-4]
+ @ r3 := p->buf[XADAPTCOEFFSB-3]
+ @ r4 := p->buf[XADAPTCOEFFSB-2]
+ blt 1f
+
+ @ *decoded1 > 0
+
+ sub r5, r5, r11 @ r5 := p->XcoeffsB[0] - p->buf[XADAPTCOEFFSB]
+ sub r6, r6, r10 @ r6 := p->XcoeffsB[1] - p->buf[XADAPTCOEFFSB-1]
+ sub r9, r9, r2 @ r9 := p->XcoeffsB[4] - p->buf[XADAPTCOEFFSB-4]
+ sub r8, r8, r3 @ r8 := p->XcoeffsB[3] - p->buf[XADAPTCOEFFSB-3]
+ sub r7, r7, r4 @ r7 := p->XcoeffsB[2] - p->buf[XADAPTCOEFFSB-2]
+
+ add r0, r12, #XcoeffsB
+ stmia r0, {r5 - r9} @ Save p->XcoeffsB[]
+
+ add r1, r12, #XcoeffsA
+ ldmia r1, {r2 - r5} @ r2 := p->XcoeffsA[0]
+ @ r3 := p->XcoeffsA[1]
+ @ r4 := p->XcoeffsA[2]
+ @ r5 := p->XcoeffsA[3]
+
+ add r6, r14, #XADAPTCOEFFSA-12
+ ldmia r6, {r6 - r9} @ r6 := p->buf[XADAPTCOEFFSA-3]
+ @ r7 := p->buf[XADAPTCOEFFSA-2]
+ @ r8 := p->buf[XADAPTCOEFFSA-1]
+ @ r9 := p->buf[XADAPTCOEFFSA]
+
+ sub r5, r5, r6 @ r5 := p->XcoeffsA[3] - p->buf[XADAPTCOEFFSA-3]
+ sub r4, r4, r7 @ r4 := p->XcoeffsA[2] - p->buf[XADAPTCOEFFSA-2]
+ sub r3, r3, r8 @ r3 := p->XcoeffsA[1] - p->buf[XADAPTCOEFFSA-1]
+ sub r2, r2, r9 @ r2 := p->XcoeffsA[0] - p->buf[XADAPTCOEFFSA]
+
+ b 2f
+
+
+1: @ *decoded1 < 0
+
+ add r5, r5, r11 @ r5 := p->XcoeffsB[0] + p->buf[XADAPTCOEFFSB]
+ add r6, r6, r10 @ r6 := p->XcoeffsB[1] + p->buf[XADAPTCOEFFSB-1]
+ add r9, r9, r2 @ r9 := p->XcoeffsB[4] + p->buf[XADAPTCOEFFSB-4]
+ add r8, r8, r3 @ r8 := p->XcoeffsB[3] + p->buf[XADAPTCOEFFSB-3]
+ add r7, r7, r4 @ r7 := p->XcoeffsB[2] + p->buf[XADAPTCOEFFSB-2]
+
+ add r0, r12, #XcoeffsB
+ stmia r0, {r5 - r9} @ Save p->XcoeffsB[]
+
+ add r1, r12, #XcoeffsA
+ ldmia r1, {r2 - r5} @ r2 := p->XcoeffsA[0]
+ @ r3 := p->XcoeffsA[1]
+ @ r4 := p->XcoeffsA[2]
+ @ r5 := p->XcoeffsA[3]
+
+ add r6, r14, #XADAPTCOEFFSA-12
+ ldmia r6, {r6 - r9} @ r6 := p->buf[XADAPTCOEFFSA-3]
+ @ r7 := p->buf[XADAPTCOEFFSA-2]
+ @ r8 := p->buf[XADAPTCOEFFSA-1]
+ @ r9 := p->buf[XADAPTCOEFFSA]
+
+ add r5, r5, r6 @ r5 := p->XcoeffsA[3] + p->buf[XADAPTCOEFFSA-3]
+ add r4, r4, r7 @ r4 := p->XcoeffsA[2] + p->buf[XADAPTCOEFFSA-2]
+ add r3, r3, r8 @ r3 := p->XcoeffsA[1] + p->buf[XADAPTCOEFFSA-1]
+ add r2, r2, r9 @ r2 := p->XcoeffsA[0] + p->buf[XADAPTCOEFFSA]
+
+2:
+ stmia r1, {r2 - r5} @ Save p->XcoeffsA
+
+3:
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@ COMMON
+
+ add r14, r14, #4 @ p->buf++
+
+ add r11, r12, #historybuffer @ r11 := &p->historybuffer[0]
+
+ sub r10, r14, #PREDICTOR_HISTORY_SIZE*4
+ @ r10 := p->buf - PREDICTOR_HISTORY_SIZE
+
+ ldr r0, [sp, #8]
+ cmp r10, r11
+ beq move_hist @ The history buffer is full, we need to do a memmove
+
+ @ Check loop count
+ subs r0, r0, #1
+ strne r0, [sp, #8]
+ bne loop
+
+done:
+ str r14, [r12] @ Save value of p->buf
+ add sp, sp, #12 @ Don't bother restoring r1-r3
+#ifdef ROCKBOX
+ ldmpc regs=r4-r11
+#else
+ ldmia sp!, {r4 - r11, pc}
+#endif
+
+move_hist:
+ @ dest = r11 (p->historybuffer)
+ @ src = r14 (p->buf)
+ @ n = 200
+
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+
+ ldr r0, [sp, #8]
+ add r14, r12, #historybuffer @ p->buf = &p->historybuffer[0]
+
+ @ Check loop count
+ subs r0, r0, #1
+ strne r0, [sp, #8]
+ bne loop
+
+ b done
+ .size predictor_decode_stereo, .-predictor_decode_stereo
+
+ .global predictor_decode_mono
+ .type predictor_decode_mono,%function
+
+@ Register usage:
+@
+@ r0-r11 - scratch
+@ r12 - struct predictor_t* p
+@ r14 - int32_t* p->buf
+
+@ void predictor_decode_mono(struct predictor_t* p,
+@ int32_t* decoded0,
+@ int count)
+
+predictor_decode_mono:
+ stmdb sp!, {r1, r2, r4-r11, lr}
+
+ @ r1 (decoded0) is [sp]
+ @ r2 (count) is [sp, #4]
+
+ mov r12, r0 @ r12 := p
+ ldr r14, [r0] @ r14 := p->buf
+
+loopm:
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@ PREDICTOR
+
+ ldr r11, [r12, #YlastA] @ r11 := p->YlastA
+
+ add r2, r14, #YDELAYA-12 @ r2 := &p->buf[YDELAYA-3]
+ ldmia r2, {r2, r3, r10} @ r2 := p->buf[YDELAYA-3]
+ @ r3 := p->buf[YDELAYA-2]
+ @ r10 := p->buf[YDELAYA-1]
+
+ add r5, r12, #YcoeffsA @ r5 := &p->YcoeffsA[0]
+ ldmia r5, {r6 - r9} @ r6 := p->YcoeffsA[0]
+ @ r7 := p->YcoeffsA[1]
+ @ r8 := p->YcoeffsA[2]
+ @ r9 := p->YcoeffsA[3]
+
+ subs r10, r11, r10 @ r10 := r11 - r10
+
+ STR2OFS r10, r11, r14, #YDELAYA-4
+ @ p->buf[YDELAYA-1] = r10
+ @ p->buf[YDELAYA] = r11
+
+ mul r0, r11, r6 @ r0 := p->buf[YDELAYA] * p->YcoeffsA[0]
+ mla r0, r10, r7, r0 @ r0 += p->buf[YDELAYA-1] * p->YcoeffsA[1]
+ mla r0, r3, r8, r0 @ r0 += p->buf[YDELAYA-2] * p->YcoeffsA[2]
+ mla r0, r2, r9, r0 @ r0 += p->buf[YDELAYA-3] * p->YcoeffsA[3]
+
+ @ flags were set above, in the subs instruction
+ mvngt r10, #0
+ movlt r10, #1 @ r10 := SIGN(r10) (see .c for SIGN macro)
+
+ cmp r11, #0
+ mvngt r11, #0
+ movlt r11, #1 @ r11 := SIGN(r11) (see .c for SIGN macro)
+
+ STR2OFS r10, r11, r14, #YADAPTCOEFFSA-4
+ @ p->buf[YADAPTCOEFFSA-1] := r10
+ @ p->buf[YADAPTCOEFFSA] := r11
+
+ ldr r2, [sp] @ r2 := decoded0
+ ldr r4, [r12, #YfilterA] @ r4 := p->YfilterA
+ ldr r3, [r2] @ r3 := *decoded0
+ rsb r4, r4, r4, lsl #5 @ r4 := r4 * 32 - r4 ( == r4*31)
+ add r1, r3, r0, asr #10 @ r1 := r3 + (r0 >> 10)
+ str r1, [r12, #YlastA] @ p->YlastA := r1
+ add r1, r1, r4, asr #5 @ r1 := r1 + (r4 >> 5)
+ str r1, [r12, #YfilterA] @ p->YfilterA := r1
+
+ @ r1 contains p->YfilterA
+ @ r2 contains decoded0
+ @ r3 contains *decoded0
+
+ @ r6, r7, r8, r9 contain p->YcoeffsA[0..3]
+ @ r10, r11 contain p->buf[YADAPTCOEFFSA-1] and p->buf[YADAPTCOEFFSA]
+
+ str r1, [r2], #4 @ *(decoded0++) := r1 (p->YfilterA)
+ str r2, [sp] @ save decoded0
+ cmp r3, #0
+ beq 3f
+
+ LDR2OFS r2, r3, r14, #YADAPTCOEFFSA-12
+ @ r2 := p->buf[YADAPTCOEFFSA-3]
+ @ r3 := p->buf[YADAPTCOEFFSA-2]
+ blt 1f
+
+ @ *decoded0 > 0
+
+ sub r6, r6, r11 @ r6 := p->YcoeffsA[0] - p->buf[YADAPTCOEFFSA]
+ sub r7, r7, r10 @ r7 := p->YcoeffsA[1] - p->buf[YADAPTCOEFFSA-1]
+ sub r9, r9, r2 @ r9 := p->YcoeffsA[3] - p->buf[YADAPTCOEFFSA-3]
+ sub r8, r8, r3 @ r8 := p->YcoeffsA[2] - p->buf[YADAPTCOEFFSA-2]
+
+ b 2f
+
+1: @ *decoded0 < 0
+
+ add r6, r6, r11 @ r6 := p->YcoeffsA[0] + p->buf[YADAPTCOEFFSA]
+ add r7, r7, r10 @ r7 := p->YcoeffsA[1] + p->buf[YADAPTCOEFFSA-1]
+ add r9, r9, r2 @ r9 := p->YcoeffsA[3] + p->buf[YADAPTCOEFFSA-3]
+ add r8, r8, r3 @ r8 := p->YcoeffsA[2] + p->buf[YADAPTCOEFFSA-2]
+
+2:
+ stmia r5, {r6 - r9} @ Save p->YcoeffsA
+
+3:
+
+@@@@@@@@@@@@@@@@@@@@@@@@@@@ COMMON
+
+ add r14, r14, #4 @ p->buf++
+
+ add r11, r12, #historybuffer @ r11 := &p->historybuffer[0]
+
+ sub r10, r14, #PREDICTOR_HISTORY_SIZE*4
+ @ r10 := p->buf - PREDICTOR_HISTORY_SIZE
+
+ ldr r0, [sp, #4]
+ cmp r10, r11
+ beq move_histm @ The history buffer is full, we need to do a memmove
+
+ @ Check loop count
+ subs r0, r0, #1
+ strne r0, [sp, #4]
+ bne loopm
+
+donem:
+ str r14, [r12] @ Save value of p->buf
+ add sp, sp, #8 @ Don't bother restoring r1, r2
+#ifdef ROCKBOX
+ ldmpc regs=r4-r11
+#else
+ ldmia sp!, {r4 - r11, pc}
+#endif
+
+move_histm:
+ @ dest = r11 (p->historybuffer)
+ @ src = r14 (p->buf)
+ @ n = 200
+
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+ ldmia r14!, {r0-r9} @ 40 bytes
+ stmia r11!, {r0-r9}
+
+ ldr r0, [sp, #4]
+ add r14, r12, #historybuffer @ p->buf = &p->historybuffer[0]
+
+ @ Check loop count
+ subs r0, r0, #1
+ strne r0, [sp, #4]
+ bne loopm
+
+ b donem
+ .size predictor_decode_mono, .-predictor_decode_mono
diff --git a/lib/rbcodec/codecs/demac/libdemac/predictor-cf.S b/lib/rbcodec/codecs/demac/libdemac/predictor-cf.S
new file mode 100644
index 0000000000..fc1d901a59
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/predictor-cf.S
@@ -0,0 +1,660 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+Coldfire predictor copyright (C) 2007 Jens Arnold
+
+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 "demac_config.h"
+
+/* NOTE: The following need to be kept in sync with parser.h */
+
+#define YDELAYA 200
+#define YDELAYB 168
+#define XDELAYA 136
+#define XDELAYB 104
+#define YADAPTCOEFFSA 72
+#define XADAPTCOEFFSA 56
+#define YADAPTCOEFFSB 40
+#define XADAPTCOEFFSB 20
+
+/* struct predictor_t members: */
+#define buf 0 /* int32_t* buf */
+
+#define YlastA 4 /* int32_t YlastA; */
+#define XlastA 8 /* int32_t XlastA; */
+
+#define YfilterB 12 /* int32_t YfilterB; */
+#define XfilterA 16 /* int32_t XfilterA; */
+
+#define XfilterB 20 /* int32_t XfilterB; */
+#define YfilterA 24 /* int32_t YfilterA; */
+
+#define YcoeffsA 28 /* int32_t YcoeffsA[4]; */
+#define XcoeffsA 44 /* int32_t XcoeffsA[4]; */
+#define YcoeffsB 60 /* int32_t YcoeffsB[5]; */
+#define XcoeffsB 80 /* int32_t XcoeffsB[5]; */
+
+#define historybuffer 100 /* int32_t historybuffer[] */
+
+
+ .text
+
+ .align 2
+
+ .global predictor_decode_stereo
+ .type predictor_decode_stereo,@function
+
+| void predictor_decode_stereo(struct predictor_t* p,
+| int32_t* decoded0,
+| int32_t* decoded1,
+| int count)
+
+predictor_decode_stereo:
+ lea.l (-12*4,%sp), %sp
+ movem.l %d2-%d7/%a2-%a6, (4,%sp)
+
+ movem.l (12*4+8,%sp), %a3-%a5 | %a3 = decoded0
+ | %a4 = decoded1
+ move.l %a5, (%sp) | (%sp) = count
+
+ move.l #0, %macsr | signed integer mode
+ move.l (12*4+4,%sp), %a6 | %a6 = p
+ move.l (%a6), %a5 | %a5 = p->buf
+
+.loop:
+
+ | ***** PREDICTOR Y *****
+
+ | Predictor Y, Filter A
+
+ move.l (YlastA,%a6), %d3 | %d3 = p->YlastA
+
+ movem.l (YDELAYA-12,%a5), %d0-%d2 | %d0 = p->buf[YDELAYA-3]
+ | %d1 = p->buf[YDELAYA-2]
+ | %d2 = p->buf[YDELAYA-1]
+
+ move.l %d3, (YDELAYA,%a5) | p->buf[YDELAYA] = %d3
+
+ sub.l %d3, %d2
+ neg.l %d2 | %d2 = %d3 - %d2
+
+ move.l %d2, (YDELAYA-4,%a5) | p->buf[YDELAYA-1] = %d2
+
+ movem.l (YcoeffsA,%a6), %d4-%d7 | %d4 = p->YcoeffsA[0]
+ | %d5 = p->YcoeffsA[1]
+ | %d6 = p->YcoeffsA[2]
+ | %d7 = p->YcoeffsA[3]
+
+ mac.l %d3, %d4, %acc0 | %acc0 = p->buf[YDELAYA] * p->YcoeffsA[0]
+ mac.l %d2, %d5, %acc0 | %acc0 += p->buf[YDELAYA-1] * p->YcoeffsA[1]
+ mac.l %d1, %d6, %acc0 | %acc0 += p->buf[YDELAYA-2] * p->YcoeffsA[2]
+ mac.l %d0, %d7, %acc0 | %acc0 += p->buf[YDELAYA-3] * p->YcoeffsA[3]
+
+ tst.l %d2
+ beq.s 1f
+ spl.b %d2 | pos: 0x??????ff, neg: 0x??????00
+ extb.l %d2 | pos: 0xffffffff, neg: 0x00000000
+ or.l #1, %d2 | pos: 0xffffffff, neg: 0x00000001
+1: | %d2 = SIGN(%d2)
+ move.l %d2, (YADAPTCOEFFSA-4,%a5) | p->buf[YADAPTCOEFFSA-1] = %d2
+
+ tst.l %d3
+ beq.s 1f
+ spl.b %d3
+ extb.l %d3
+ or.l #1, %d3
+1: | %d3 = SIGN(%d3)
+ move.l %d3, (YADAPTCOEFFSA,%a5) | p->buf[YADAPTCOEFFSA] = %d3
+
+ | Predictor Y, Filter B
+
+ movem.l (YfilterB,%a6), %d2-%d3 | %d2 = p->YfilterB
+ | %d3 = p->XfilterA
+ move.l %d3, (YfilterB,%a6) | p->YfilterB = %d3
+
+ move.l %d2, %d1 | %d1 = %d2
+ lsl.l #5, %d2 | %d2 = %d2 * 32
+ sub.l %d1, %d2 | %d2 -= %d1 (== 31 * old_d2)
+ asr.l #5, %d2 | %d2 >>= 5
+ sub.l %d2, %d3 | %d3 -= %d2
+
+ movem.l (YDELAYB-16,%a5), %d4-%d7 | %d4 = p->buf[YDELAYB-4]
+ | %d5 = p->buf[YDELAYB-3]
+ | %d6 = p->buf[YDELAYB-2]
+ | %d7 = p->buf[YDELAYB-1]
+ sub.l %d3, %d7
+ neg.l %d7 | %d7 = %d3 - %d7
+
+ move.l %d7, (YDELAYB-4,%a5) | p->buf[YDELAYB-1] = %d7
+
+ movem.l (YcoeffsB,%a6), %d1-%d2/%a0-%a2 | %d1 = p->YcoeffsB[0]
+ | %d2 = p->YcoeffsB[1]
+ | %a0 = p->YcoeffsB[2]
+ | %a1 = p->YcoeffsB[3]
+ | %a2 = p->YcoeffsB[4]
+
+ mac.l %d3, %d1, %acc1 | %acc1 = p->buf[YDELAYB] * p->YcoeffsB[0]
+ mac.l %d7, %d2, %acc1 | %acc1 += p->buf[YDELAYB-1] * p->YcoeffsB[1]
+ mac.l %d6, %a0, %acc1 | %acc1 += p->buf[YDELAYB-2] * p->YcoeffsB[2]
+ mac.l %d5, %a1, %acc1 | %acc1 += p->buf[YDELAYB-3] * p->YcoeffsB[3]
+ mac.l %d4, %a2, %acc1 | %acc1 += p->buf[YDELAYB-4] * p->YcoeffsB[4]
+
+ move.l %d3, (YDELAYB, %a5) | p->buf[YDELAYB] = %d3
+
+ tst.l %d7
+ beq.s 1f
+ spl.b %d7
+ extb.l %d7
+ or.l #1, %d7
+1: | %d7 = SIGN(%d7)
+ move.l %d7, (YADAPTCOEFFSB-4,%a5) | p->buf[YADAPTCOEFFSB-1] = %d7
+ tst.l %d3
+ beq.s 1f
+ spl.b %d3
+ extb.l %d3
+ or.l #1, %d3
+1: | %d3 = SIGN(%d3)
+ move.l %d3, (YADAPTCOEFFSB, %a5) | p->buf[YADAPTCOEFFSB] = %d3
+
+ | %d1, %d2, %a0, %a1, %a2 contain p->YcoeffsB[0..4]
+ | %d7, %d3 contain p->buf[YADAPTCOEFFSB-1] and p->buf[YADAPTCOEFFSB]
+
+ move.l (%a3), %d0 | %d0 = *decoded0
+ beq.s 3f
+
+ movem.l (YADAPTCOEFFSB-16,%a5), %d4-%d6 | %d4 = p->buf[YADAPTCOEFFSB-4]
+ | %d5 = p->buf[YADAPTCOEFFSB-3]
+ | %d6 = p->buf[YADAPTCOEFFSB-2]
+
+ bmi.s 1f | flags still valid here
+
+ | *decoded0 > 0
+
+ sub.l %d3, %d1 | %d1 = p->YcoeffsB[0] - p->buf[YADAPTCOEFFSB]
+ sub.l %d7, %d2 | %d2 = p->YcoeffsB[1] - p->buf[YADAPTCOEFFSB-1]
+ sub.l %d6, %a0 | %a0 = p->YcoeffsB[2] - p->buf[YADAPTCOEFFSB-2]
+ sub.l %d5, %a1 | %a1 = p->YcoeffsB[3] - p->buf[YADAPTCOEFFSB-3]
+ sub.l %d4, %a2 | %a2 = p->YcoeffsB[4] - p->buf[YADAPTCOEFFSB-4]
+
+ movem.l %d1-%d2/%a0-%a2, (YcoeffsB,%a6) | Save p->YcoeffsB[]
+
+ movem.l (YcoeffsA,%a6), %d4-%d7 | %d4 = p->YcoeffsA[0]
+ | %d5 = p->YcoeffsA[1]
+ | %d6 = p->YcoeffsA[2]
+ | %d7 = p->YcoeffsA[3]
+
+ movem.l (YADAPTCOEFFSA-12,%a5), %d2/%a0-%a2
+ | %d2 = p->buf[YADAPTCOEFFSA-3]
+ | %a0 = p->buf[YADAPTCOEFFSA-2]
+ | %a1 = p->buf[YADAPTCOEFFSA-1]
+ | %a2 = p->buf[YADAPTCOEFFSA]
+
+ sub.l %a2, %d4 | %d4 = p->YcoeffsA[0] - p->buf[YADAPTCOEFFSA]
+ sub.l %a1, %d5 | %d5 = p->YcoeffsA[1] - p->buf[YADAPTCOEFFSA-1]
+ sub.l %a0, %d6 | %d6 = p->YcoeffsA[2] - p->buf[YADAPTCOEFFSA-2]
+ sub.l %d2, %d7 | %d7 = p->YcoeffsA[3] - p->buf[YADAPTCOEFFSA-3]
+
+ bra.s 2f
+
+1: | *decoded0 < 0
+
+ add.l %d3, %d1 | %d1 = p->YcoeffsB[0] + p->buf[YADAPTCOEFFSB]
+ add.l %d7, %d2 | %d2 = p->YcoeffsB[1] + p->buf[YADAPTCOEFFSB-1]
+ add.l %d6, %a0 | %a0 = p->YcoeffsB[2] + p->buf[YADAPTCOEFFSB-2]
+ add.l %d5, %a1 | %a1 = p->YcoeffsB[3] + p->buf[YADAPTCOEFFSB-3]
+ add.l %d4, %a2 | %a2 = p->YcoeffsB[4] + p->buf[YADAPTCOEFFSB-4]
+
+ movem.l %d1-%d2/%a0-%a2, (YcoeffsB,%a6) | Save p->YcoeffsB[]
+
+ movem.l (YcoeffsA,%a6), %d4-%d7 | %d4 = p->YcoeffsA[0]
+ | %d5 = p->YcoeffsA[1]
+ | %d6 = p->YcoeffsA[2]
+ | %d7 = p->YcoeffsA[3]
+
+ movem.l (YADAPTCOEFFSA-12,%a5), %d2/%a0-%a2
+ | %d2 = p->buf[YADAPTCOEFFSA-3]
+ | %a0 = p->buf[YADAPTCOEFFSA-2]
+ | %a1 = p->buf[YADAPTCOEFFSA-1]
+ | %a2 = p->buf[YADAPTCOEFFSA]
+
+ add.l %a2, %d4 | %d4 = p->YcoeffsA[0] + p->buf[YADAPTCOEFFSA]
+ add.l %a1, %d5 | %d5 = p->YcoeffsA[1] + p->buf[YADAPTCOEFFSA-1]
+ add.l %a0, %d6 | %d6 = p->YcoeffsA[2] + p->buf[YADAPTCOEFFSA-2]
+ add.l %d2, %d7 | %d7 = p->YcoeffsA[3] + p->buf[YADAPTCOEFFSA-3]
+
+2:
+ movem.l %d4-%d7, (YcoeffsA,%a6) | Save p->YcoeffsA[]
+
+3:
+ | Finish Predictor Y
+
+ movclr.l %acc0, %d1 | %d1 = predictionA
+ movclr.l %acc1, %d2 | %d2 = predictionB
+ asr.l #1, %d2
+ add.l %d2, %d1 | %d1 += (%d2 >> 1)
+ asr.l #8, %d1
+ asr.l #2, %d1 | %d1 >>= 10
+ add.l %d0, %d1 | %d1 += %d0
+ move.l %d1, (YlastA,%a6) | p->YlastA = %d1
+
+ move.l (YfilterA,%a6), %d2 | %d2 = p->YfilterA
+ move.l %d2, %d0
+ lsl.l #5, %d2
+ sub.l %d0, %d2 | %d2 = 31 * %d2
+ asr.l #5, %d2 | %d2 >>= 5
+ add.l %d1, %d2
+ move.l %d2, (YfilterA,%a6) | p->YfilterA = %d2
+
+ | *decoded0 stored 2 instructions down, avoiding pipeline stall
+
+ | ***** PREDICTOR X *****
+
+ | Predictor X, Filter A
+
+ move.l (XlastA,%a6), %d3 | %d3 = p->XlastA
+
+ move.l %d2, (%a3)+ | *(decoded0++) = %d2 (p->YfilterA)
+
+ movem.l (XDELAYA-12,%a5), %d0-%d2 | %d0 = p->buf[XDELAYA-3]
+ | %d1 = p->buf[XDELAYA-2]
+ | %d2 = p->buf[XDELAYA-1]
+
+ move.l %d3, (XDELAYA,%a5) | p->buf[XDELAYA] = %d3
+
+ sub.l %d3, %d2
+ neg.l %d2 | %d2 = %d3 -%d2
+
+ move.l %d2, (XDELAYA-4,%a5) | p->buf[XDELAYA-1] = %d2
+
+ movem.l (XcoeffsA,%a6), %d4-%d7 | %d4 = p->XcoeffsA[0]
+ | %d5 = p->XcoeffsA[1]
+ | %d6 = p->XcoeffsA[2]
+ | %d7 = p->XcoeffsA[3]
+
+ mac.l %d3, %d4, %acc0 | %acc0 = p->buf[XDELAYA] * p->XcoeffsA[0]
+ mac.l %d2, %d5, %acc0 | %acc0 += p->buf[XDELAYA-1] * p->XcoeffsA[1]
+ mac.l %d1, %d6, %acc0 | %acc0 += p->buf[XDELAYA-2] * p->XcoeffsA[2]
+ mac.l %d0, %d7, %acc0 | %acc0 += p->buf[XDELAYA-3] * p->XcoeffsA[3]
+
+ tst.l %d2
+ beq.s 1f
+ spl.b %d2 | pos: 0x??????ff, neg: 0x??????00
+ extb.l %d2 | pos: 0xffffffff, neg: 0x00000000
+ or.l #1, %d2 | pos: 0xffffffff, neg: 0x00000001
+1: | %d2 = SIGN(%d2)
+ move.l %d2, (XADAPTCOEFFSA-4,%a5) | p->buf[XADAPTCOEFFSA-1] = %d2
+
+ tst.l %d3
+ beq.s 1f
+ spl.b %d3
+ extb.l %d3
+ or.l #1, %d3
+1: | %d3 = SIGN(%d3)
+ move.l %d3, (XADAPTCOEFFSA,%a5) | p->buf[XADAPTCOEFFSA] = %d3
+
+ | Predictor X, Filter B
+
+ movem.l (XfilterB,%a6), %d2-%d3 | %d2 = p->XfilterB
+ | %d3 = p->YfilterA
+ move.l %d3, (XfilterB,%a6) | p->XfilterB = %d3
+
+ move.l %d2, %d1 | %d1 = %d2
+ lsl.l #5, %d2 | %d2 = %d2 * 32
+ sub.l %d1, %d2 | %d2 -= %d1 (== 31 * old_d2)
+ asr.l #5, %d2 | %d2 >>= 5
+ sub.l %d2, %d3 | %d3 -= %d2
+
+ movem.l (XDELAYB-16,%a5), %d4-%d7 | %d4 = p->buf[XDELAYB-4]
+ | %d5 = p->buf[XDELAYB-3]
+ | %d6 = p->buf[XDELAYB-2]
+ | %d7 = p->buf[XDELAYB-1]
+ sub.l %d3, %d7
+ neg.l %d7 | %d7 = %d3 - %d7
+
+ move.l %d7, (XDELAYB-4,%a5) | p->buf[XDELAYB-1] = %d7
+
+ movem.l (XcoeffsB,%a6), %d1-%d2/%a0-%a2 | %d1 = p->XcoeffsB[0]
+ | %d2 = p->XcoeffsB[1]
+ | %a0 = p->XcoeffsB[2]
+ | %a1 = p->XcoeffsB[3]
+ | %a2 = p->XcoeffsB[4]
+
+ mac.l %d3, %d1, %acc1 | %acc1 = p->buf[XDELAYB] * p->XcoeffsB[0]
+ mac.l %d7, %d2, %acc1 | %acc1 += p->buf[XDELAYB-1] * p->XcoeffsB[1]
+ mac.l %d6, %a0, %acc1 | %acc1 += p->buf[XDELAYB-2] * p->XcoeffsB[2]
+ mac.l %d5, %a1, %acc1 | %acc1 += p->buf[XDELAYB-3] * p->XcoeffsB[3]
+ mac.l %d4, %a2, %acc1 | %acc1 += p->buf[XDELAYB-4] * p->XcoeffsB[4]
+
+ move.l %d3, (XDELAYB, %a5) | p->buf[XDELAYB] = %d3
+
+ tst.l %d7
+ beq.s 1f
+ spl.b %d7
+ extb.l %d7
+ or.l #1, %d7
+1: | %d7 = SIGN(%d7)
+ move.l %d7, (XADAPTCOEFFSB-4,%a5) | p->buf[XADAPTCOEFFSB-1] = %d7
+
+ tst.l %d3
+ beq.s 1f
+ spl.b %d3
+ extb.l %d3
+ or.l #1, %d3
+1: | %d3 = SIGN(%d3)
+ move.l %d3, (XADAPTCOEFFSB, %a5) | p->buf[XADAPTCOEFFSB] = %d3
+
+ | %d1, %d2, %a0, %a1, %a2 contain p->XcoeffsB[0..4]
+ | %d7, %d3 contain p->buf[XADAPTCOEFFSB-1] and p->buf[XADAPTCOEFFSB]
+
+ move.l (%a4), %d0 | %d0 = *decoded1
+ beq.s 3f
+
+ movem.l (XADAPTCOEFFSB-16,%a5), %d4-%d6 | %d4 = p->buf[XADAPTCOEFFSB-4]
+ | %d5 = p->buf[XADAPTCOEFFSB-3]
+ | %d6 = p->buf[XADAPTCOEFFSB-2]
+
+ bmi.s 1f | flags still valid here
+
+ | *decoded1 > 0
+
+ sub.l %d3, %d1 | %d1 = p->XcoeffsB[0] - p->buf[XADAPTCOEFFSB]
+ sub.l %d7, %d2 | %d2 = p->XcoeffsB[1] - p->buf[XADAPTCOEFFSB-1]
+ sub.l %d6, %a0 | %a0 = p->XcoeffsB[2] - p->buf[XADAPTCOEFFSB-2]
+ sub.l %d5, %a1 | %a1 = p->XcoeffsB[3] - p->buf[XADAPTCOEFFSB-3]
+ sub.l %d4, %a2 | %a2 = p->XcoeffsB[4] - p->buf[XADAPTCOEFFSB-4]
+
+ movem.l %d1-%d2/%a0-%a2, (XcoeffsB,%a6) | Save p->XcoeffsB[]
+
+ movem.l (XcoeffsA,%a6), %d4-%d7 | %d4 = p->XcoeffsA[0]
+ | %d5 = p->XcoeffsA[1]
+ | %d6 = p->XcoeffsA[2]
+ | %d7 = p->XcoeffsA[3]
+
+ movem.l (XADAPTCOEFFSA-12,%a5), %d2/%a0-%a2
+ | %d2 = p->buf[XADAPTCOEFFSA-3]
+ | %a0 = p->buf[XADAPTCOEFFSA-2]
+ | %a1 = p->buf[XADAPTCOEFFSA-1]
+ | %a2 = p->buf[XADAPTCOEFFSA]
+
+ sub.l %a2, %d4 | %d4 = p->XcoeffsA[0] - p->buf[XADAPTCOEFFSA]
+ sub.l %a1, %d5 | %d5 = p->XcoeffsA[1] - p->buf[XADAPTCOEFFSA-1]
+ sub.l %a0, %d6 | %d6 = p->XcoeffsA[2] - p->buf[XADAPTCOEFFSA-2]
+ sub.l %d2, %d7 | %d7 = p->XcoeffsA[3] - p->buf[XADAPTCOEFFSA-3]
+
+ bra.s 2f
+
+1: | *decoded1 < 0
+
+ add.l %d3, %d1 | %d1 = p->XcoeffsB[0] + p->buf[XADAPTCOEFFSB]
+ add.l %d7, %d2 | %d2 = p->XcoeffsB[1] + p->buf[XADAPTCOEFFSB-1]
+ add.l %d6, %a0 | %a0 = p->XcoeffsB[2] + p->buf[XADAPTCOEFFSB-2]
+ add.l %d5, %a1 | %a1 = p->XcoeffsB[3] + p->buf[XADAPTCOEFFSB-3]
+ add.l %d4, %a2 | %a2 = p->XcoeffsB[4] + p->buf[XADAPTCOEFFSB-4]
+
+ movem.l %d1-%d2/%a0-%a2, (XcoeffsB,%a6) | Save p->XcoeffsB[]
+
+ movem.l (XcoeffsA,%a6), %d4-%d7 | %d4 = p->XcoeffsA[0]
+ | %d5 = p->XcoeffsA[1]
+ | %d6 = p->XcoeffsA[2]
+ | %d7 = p->XcoeffsA[3]
+
+ movem.l (XADAPTCOEFFSA-12,%a5), %d2/%a0-%a2
+ | %d2 = p->buf[XADAPTCOEFFSA-3]
+ | %a0 = p->buf[XADAPTCOEFFSA-2]
+ | %a1 = p->buf[XADAPTCOEFFSA-1]
+ | %a2 = p->buf[XADAPTCOEFFSA]
+
+ add.l %a2, %d4 | %d4 = p->XcoeffsA[0] + p->buf[XADAPTCOEFFSA]
+ add.l %a1, %d5 | %d5 = p->XcoeffsA[1] + p->buf[XADAPTCOEFFSA-1]
+ add.l %a0, %d6 | %d6 = p->XcoeffsA[2] + p->buf[XADAPTCOEFFSA-2]
+ add.l %d2, %d7 | %d7 = p->XcoeffsA[3] + p->buf[XADAPTCOEFFSA-3]
+
+2:
+ movem.l %d4-%d7, (XcoeffsA,%a6) | Save p->XcoeffsA[]
+
+3:
+ | Finish Predictor X
+
+ movclr.l %acc0, %d1 | %d1 = predictionA
+ movclr.l %acc1, %d2 | %d2 = predictionB
+ asr.l #1, %d2
+ add.l %d2, %d1 | %d1 += (%d2 >> 1)
+ asr.l #8, %d1
+ asr.l #2, %d1 | %d1 >>= 10
+ add.l %d0, %d1 | %d1 += %d0
+ move.l %d1, (XlastA,%a6) | p->XlastA = %d1
+
+ move.l (XfilterA,%a6), %d2 | %d2 = p->XfilterA
+ move.l %d2, %d0
+ lsl.l #5, %d2
+ sub.l %d0, %d2 | %d2 = 31 * %d2
+ asr.l #5, %d2 | %d6 >>= 2
+ add.l %d1, %d2
+ move.l %d2, (XfilterA,%a6) | p->XfilterA = %d2
+
+ | *decoded1 stored 3 instructions down, avoiding pipeline stall
+
+ | ***** COMMON *****
+
+ addq.l #4, %a5 | p->buf++
+ lea.l (historybuffer+PREDICTOR_HISTORY_SIZE*4,%a6), %a2
+ | %a2 = &p->historybuffer[PREDICTOR_HISTORY_SIZE]
+
+ move.l %d2, (%a4)+ | *(decoded1++) = %d2 (p->XfilterA)
+
+ cmp.l %a2, %a5
+ beq.s .move_hist | History buffer is full, we need to do a memmove
+
+ subq.l #1, (%sp) | decrease loop count
+ bne.w .loop
+
+.done:
+ move.l %a5, (%a6) | Save value of p->buf
+ movem.l (4,%sp), %d2-%d7/%a2-%a6
+ lea.l (12*4,%sp), %sp
+ rts
+
+.move_hist:
+ lea.l (historybuffer,%a6), %a2
+
+ | dest = %a2 (p->historybuffer)
+ | src = %a5 (p->buf)
+ | n = 200
+
+ movem.l (%a5), %d0-%d7/%a0-%a1 | 40 bytes
+ movem.l %d0-%d7/%a0-%a1, (%a2)
+ movem.l (40,%a5), %d0-%d7/%a0-%a1 | 40 bytes
+ movem.l %d0-%d7/%a0-%a1, (40,%a2)
+ movem.l (80,%a5), %d0-%d7/%a0-%a1 | 40 bytes
+ movem.l %d0-%d7/%a0-%a1, (80,%a2)
+ movem.l (120,%a5), %d0-%d7/%a0-%a1 | 40 bytes
+ movem.l %d0-%d7/%a0-%a1, (120,%a2)
+ movem.l (160,%a5), %d0-%d7/%a0-%a1 | 40 bytes
+ movem.l %d0-%d7/%a0-%a1, (160,%a2)
+
+ move.l %a2, %a5 | p->buf = &p->historybuffer[0]
+
+ subq.l #1, (%sp) | decrease loop count
+ bne.w .loop
+
+ bra.s .done
+ .size predictor_decode_stereo, .-predictor_decode_stereo
+
+
+ .global predictor_decode_mono
+ .type predictor_decode_mono,@function
+
+| void predictor_decode_mono(struct predictor_t* p,
+| int32_t* decoded0,
+| int count)
+
+predictor_decode_mono:
+ lea.l (-11*4,%sp), %sp
+ movem.l %d2-%d7/%a2-%a6, (%sp)
+
+ move.l #0, %macsr | signed integer mode
+
+ move.l (11*4+4,%sp), %a6 | %a6 = p
+ move.l (11*4+8,%sp), %a4 | %a4 = decoded0
+ move.l (11*4+12,%sp), %d7 | %d7 = count
+ move.l (%a6), %a5 | %a5 = p->buf
+
+ move.l (YlastA,%a6), %d3 | %d3 = p->YlastA
+
+.loopm:
+
+ | ***** PREDICTOR *****
+
+ movem.l (YDELAYA-12,%a5), %d0-%d2 | %d0 = p->buf[YDELAYA-3]
+ | %d1 = p->buf[YDELAYA-2]
+ | %d2 = p->buf[YDELAYA-1]
+
+ move.l %d3, (YDELAYA,%a5) | p->buf[YDELAYA] = %d3
+
+ sub.l %d3, %d2
+ neg.l %d2 | %d2 = %d3 - %d2
+
+ move.l %d2, (YDELAYA-4,%a5) | p->buf[YDELAYA-1] = %d2
+
+ movem.l (YcoeffsA,%a6), %a0-%a3 | %a0 = p->YcoeffsA[0]
+ | %a1 = p->YcoeffsA[1]
+ | %a2 = p->YcoeffsA[2]
+ | %a3 = p->YcoeffsA[3]
+
+ mac.l %d3, %a0, %acc0 | %acc0 = p->buf[YDELAYA] * p->YcoeffsA[0]
+ mac.l %d2, %a1, %acc0 | %acc0 += p->buf[YDELAYA-1] * p->YcoeffsA[1]
+ mac.l %d1, %a2, %acc0 | %acc0 += p->buf[YDELAYA-2] * p->YcoeffsA[2]
+ mac.l %d0, %a3, %acc0 | %acc0 += p->buf[YDELAYA-3] * p->YcoeffsA[3]
+
+ tst.l %d2
+ beq.s 1f
+ spl.b %d2 | pos: 0x??????ff, neg: 0x??????00
+ extb.l %d2 | pos: 0xffffffff, neg: 0x00000000
+ or.l #1, %d2 | pos: 0xffffffff, neg: 0x00000001
+1: | %d2 = SIGN(%d2)
+ move.l %d2, (YADAPTCOEFFSA-4,%a5) | p->buf[YADAPTCOEFFSA-1] = %d2
+
+ tst.l %d3
+ beq.s 1f
+ spl.b %d3
+ extb.l %d3
+ or.l #1, %d3
+1: | %d3 = SIGN(%d3)
+ move.l %d3, (YADAPTCOEFFSA,%a5) | p->buf[YADAPTCOEFFSA] = %d3
+
+ move.l (%a4), %d0 | %d0 = *decoded0
+ beq.s 3f
+
+ movem.l (YADAPTCOEFFSA-12,%a5),%d4-%d5 | %d4 = p->buf[YADAPTCOEFFSA-3]
+ | %d5 = p->buf[YADAPTCOEFFSA-2]
+
+ bmi.s 1f | flags still valid here
+
+ | *decoded0 > 0
+
+ sub.l %d3, %a0 | %a0 = p->YcoeffsA[0] - p->buf[YADAPTCOEFFSA]
+ sub.l %d2, %a1 | %a1 = p->YcoeffsA[1] - p->buf[YADAPTCOEFFSA-1]
+ sub.l %d5, %a2 | %a2 = p->YcoeffsA[2] - p->buf[YADAPTCOEFFSA-2]
+ sub.l %d4, %a3 | %a3 = p->YcoeffsA[3] - p->buf[YADAPTCOEFFSA-3]
+
+ bra.s 2f
+
+1: | *decoded0 < 0
+
+ add.l %d3, %a0 | %a0 = p->YcoeffsA[0] - p->buf[YADAPTCOEFFSA]
+ add.l %d2, %a1 | %a1 = p->YcoeffsA[1] - p->buf[YADAPTCOEFFSA-1]
+ add.l %d5, %a2 | %a2 = p->YcoeffsA[2] - p->buf[YADAPTCOEFFSA-2]
+ add.l %d4, %a3 | %a3 = p->YcoeffsA[3] - p->buf[YADAPTCOEFFSA-3]
+
+2:
+ movem.l %a0-%a3, (YcoeffsA,%a6) | save p->YcoeffsA[]
+
+3:
+ | Finish Predictor
+
+ movclr.l %acc0, %d3 | %d3 = predictionA
+ asr.l #8, %d3
+ asr.l #2, %d3 | %d3 >>= 10
+ add.l %d0, %d3 | %d3 += %d0
+
+ move.l (YfilterA,%a6), %d2 | %d2 = p->YfilterA
+ move.l %d2, %d0
+ lsl.l #5, %d2
+ sub.l %d0, %d2 | %d2 = 31 * %d2
+ asr.l #5, %d2 | %d2 >>= 5
+ add.l %d3, %d2
+ move.l %d2, (YfilterA,%a6) | p->YfilterA = %d2
+
+ | *decoded0 stored 3 instructions down, avoiding pipeline stall
+
+ | ***** COMMON *****
+
+ addq.l #4, %a5 | p->buf++
+ lea.l (historybuffer+PREDICTOR_HISTORY_SIZE*4,%a6), %a3
+ | %a3 = &p->historybuffer[PREDICTOR_HISTORY_SIZE]
+
+ move.l %d2, (%a4)+ | *(decoded0++) = %d2 (p->YfilterA)
+
+ cmp.l %a3, %a5
+ beq.s .move_histm | History buffer is full, we need to do a memmove
+
+ subq.l #1, %d7 | decrease loop count
+ bne.w .loopm
+
+ move.l %d3, (YlastA,%a6) | %d3 = p->YlastA
+
+.donem:
+ move.l %a5, (%a6) | Save value of p->buf
+ movem.l (%sp), %d2-%d7/%a2-%a6
+ lea.l (11*4,%sp), %sp
+ rts
+
+.move_histm:
+ move.l %d3, (YlastA,%a6) | %d3 = p->YlastA
+
+ lea.l (historybuffer,%a6), %a3
+
+ | dest = %a3 (p->historybuffer)
+ | src = %a5 (p->buf)
+ | n = 200
+
+ movem.l (%a5), %d0-%d6/%a0-%a2 | 40 bytes
+ movem.l %d0-%d6/%a0-%a2, (%a3)
+ movem.l (40,%a5), %d0-%d6/%a0-%a2 | 40 bytes
+ movem.l %d0-%d6/%a0-%a2, (40,%a3)
+ movem.l (80,%a5), %d0-%d6/%a0-%a2 | 40 bytes
+ movem.l %d0-%d6/%a0-%a2, (80,%a3)
+ movem.l (120,%a5), %d0-%d6/%a0-%a2 | 40 bytes
+ movem.l %d0-%d6/%a0-%a2, (120,%a3)
+ movem.l (160,%a5), %d0-%d6/%a0-%a2 | 40 bytes
+ movem.l %d0-%d6/%a0-%a2, (160,%a3)
+
+ move.l %a3, %a5 | p->buf = &p->historybuffer[0]
+
+ move.l (YlastA,%a6), %d3 | %d3 = p->YlastA
+
+ subq.l #1, %d7 | decrease loop count
+ bne.w .loopm
+
+ bra.s .donem
+ .size predictor_decode_mono, .-predictor_decode_mono
diff --git a/lib/rbcodec/codecs/demac/libdemac/predictor.c b/lib/rbcodec/codecs/demac/libdemac/predictor.c
new file mode 100644
index 0000000000..45912dddbd
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/predictor.c
@@ -0,0 +1,271 @@
+/*
+
+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 "demac_config.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
+};
+
+#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)
+
+void init_predictor_decoder(struct predictor_t* p)
+{
+ /* Zero the history buffers */
+ memset(p->historybuffer, 0, PREDICTOR_SIZE * sizeof(int32_t));
+ p->buf = p->historybuffer;
+
+ /* Initialise and zero the co-efficients */
+ memcpy(p->YcoeffsA, initial_coeffs, sizeof(initial_coeffs));
+ memcpy(p->XcoeffsA, initial_coeffs, sizeof(initial_coeffs));
+ memset(p->YcoeffsB, 0, sizeof(p->YcoeffsB));
+ memset(p->XcoeffsB, 0, sizeof(p->XcoeffsB));
+
+ p->YfilterA = 0;
+ p->YfilterB = 0;
+ p->YlastA = 0;
+
+ p->XfilterA = 0;
+ p->XfilterB = 0;
+ p->XlastA = 0;
+}
+
+#if !defined(CPU_ARM) && !defined(CPU_COLDFIRE)
+void ICODE_ATTR_DEMAC predictor_decode_stereo(struct predictor_t* p,
+ int32_t* decoded0,
+ int32_t* decoded1,
+ int count)
+{
+ int32_t predictionA, predictionB;
+
+ while (LIKELY(count--))
+ {
+ /* Predictor Y */
+ p->buf[YDELAYA] = p->YlastA;
+ p->buf[YADAPTCOEFFSA] = SIGN(p->buf[YDELAYA]);
+
+ p->buf[YDELAYA-1] = p->buf[YDELAYA] - p->buf[YDELAYA-1];
+ p->buf[YADAPTCOEFFSA-1] = SIGN(p->buf[YDELAYA-1]);
+
+ predictionA = (p->buf[YDELAYA] * p->YcoeffsA[0]) +
+ (p->buf[YDELAYA-1] * p->YcoeffsA[1]) +
+ (p->buf[YDELAYA-2] * p->YcoeffsA[2]) +
+ (p->buf[YDELAYA-3] * p->YcoeffsA[3]);
+
+ /* Apply a scaled first-order filter compression */
+ p->buf[YDELAYB] = p->XfilterA - ((p->YfilterB * 31) >> 5);
+ p->buf[YADAPTCOEFFSB] = SIGN(p->buf[YDELAYB]);
+ p->YfilterB = p->XfilterA;
+
+ p->buf[YDELAYB-1] = p->buf[YDELAYB] - p->buf[YDELAYB-1];
+ p->buf[YADAPTCOEFFSB-1] = SIGN(p->buf[YDELAYB-1]);
+
+ predictionB = (p->buf[YDELAYB] * p->YcoeffsB[0]) +
+ (p->buf[YDELAYB-1] * p->YcoeffsB[1]) +
+ (p->buf[YDELAYB-2] * p->YcoeffsB[2]) +
+ (p->buf[YDELAYB-3] * p->YcoeffsB[3]) +
+ (p->buf[YDELAYB-4] * p->YcoeffsB[4]);
+
+ p->YlastA = *decoded0 + ((predictionA + (predictionB >> 1)) >> 10);
+ p->YfilterA = p->YlastA + ((p->YfilterA * 31) >> 5);
+
+ /* Predictor X */
+
+ p->buf[XDELAYA] = p->XlastA;
+ p->buf[XADAPTCOEFFSA] = SIGN(p->buf[XDELAYA]);
+ p->buf[XDELAYA-1] = p->buf[XDELAYA] - p->buf[XDELAYA-1];
+ p->buf[XADAPTCOEFFSA-1] = SIGN(p->buf[XDELAYA-1]);
+
+ predictionA = (p->buf[XDELAYA] * p->XcoeffsA[0]) +
+ (p->buf[XDELAYA-1] * p->XcoeffsA[1]) +
+ (p->buf[XDELAYA-2] * p->XcoeffsA[2]) +
+ (p->buf[XDELAYA-3] * p->XcoeffsA[3]);
+
+ /* Apply a scaled first-order filter compression */
+ p->buf[XDELAYB] = p->YfilterA - ((p->XfilterB * 31) >> 5);
+ p->buf[XADAPTCOEFFSB] = SIGN(p->buf[XDELAYB]);
+ p->XfilterB = p->YfilterA;
+ p->buf[XDELAYB-1] = p->buf[XDELAYB] - p->buf[XDELAYB-1];
+ p->buf[XADAPTCOEFFSB-1] = SIGN(p->buf[XDELAYB-1]);
+
+ predictionB = (p->buf[XDELAYB] * p->XcoeffsB[0]) +
+ (p->buf[XDELAYB-1] * p->XcoeffsB[1]) +
+ (p->buf[XDELAYB-2] * p->XcoeffsB[2]) +
+ (p->buf[XDELAYB-3] * p->XcoeffsB[3]) +
+ (p->buf[XDELAYB-4] * p->XcoeffsB[4]);
+
+ p->XlastA = *decoded1 + ((predictionA + (predictionB >> 1)) >> 10);
+ p->XfilterA = p->XlastA + ((p->XfilterA * 31) >> 5);
+
+ if (LIKELY(*decoded0 != 0))
+ {
+ if (*decoded0 > 0)
+ {
+ p->YcoeffsA[0] -= p->buf[YADAPTCOEFFSA];
+ p->YcoeffsA[1] -= p->buf[YADAPTCOEFFSA-1];
+ p->YcoeffsA[2] -= p->buf[YADAPTCOEFFSA-2];
+ p->YcoeffsA[3] -= p->buf[YADAPTCOEFFSA-3];
+
+ p->YcoeffsB[0] -= p->buf[YADAPTCOEFFSB];
+ p->YcoeffsB[1] -= p->buf[YADAPTCOEFFSB-1];
+ p->YcoeffsB[2] -= p->buf[YADAPTCOEFFSB-2];
+ p->YcoeffsB[3] -= p->buf[YADAPTCOEFFSB-3];
+ p->YcoeffsB[4] -= p->buf[YADAPTCOEFFSB-4];
+ }
+ else
+ {
+ p->YcoeffsA[0] += p->buf[YADAPTCOEFFSA];
+ p->YcoeffsA[1] += p->buf[YADAPTCOEFFSA-1];
+ p->YcoeffsA[2] += p->buf[YADAPTCOEFFSA-2];
+ p->YcoeffsA[3] += p->buf[YADAPTCOEFFSA-3];
+
+ p->YcoeffsB[0] += p->buf[YADAPTCOEFFSB];
+ p->YcoeffsB[1] += p->buf[YADAPTCOEFFSB-1];
+ p->YcoeffsB[2] += p->buf[YADAPTCOEFFSB-2];
+ p->YcoeffsB[3] += p->buf[YADAPTCOEFFSB-3];
+ p->YcoeffsB[4] += p->buf[YADAPTCOEFFSB-4];
+ }
+ }
+
+ *(decoded0++) = p->YfilterA;
+
+ if (LIKELY(*decoded1 != 0))
+ {
+ if (*decoded1 > 0)
+ {
+ p->XcoeffsA[0] -= p->buf[XADAPTCOEFFSA];
+ p->XcoeffsA[1] -= p->buf[XADAPTCOEFFSA-1];
+ p->XcoeffsA[2] -= p->buf[XADAPTCOEFFSA-2];
+ p->XcoeffsA[3] -= p->buf[XADAPTCOEFFSA-3];
+
+ p->XcoeffsB[0] -= p->buf[XADAPTCOEFFSB];
+ p->XcoeffsB[1] -= p->buf[XADAPTCOEFFSB-1];
+ p->XcoeffsB[2] -= p->buf[XADAPTCOEFFSB-2];
+ p->XcoeffsB[3] -= p->buf[XADAPTCOEFFSB-3];
+ p->XcoeffsB[4] -= p->buf[XADAPTCOEFFSB-4];
+ }
+ else
+ {
+ p->XcoeffsA[0] += p->buf[XADAPTCOEFFSA];
+ p->XcoeffsA[1] += p->buf[XADAPTCOEFFSA-1];
+ p->XcoeffsA[2] += p->buf[XADAPTCOEFFSA-2];
+ p->XcoeffsA[3] += p->buf[XADAPTCOEFFSA-3];
+
+ p->XcoeffsB[0] += p->buf[XADAPTCOEFFSB];
+ p->XcoeffsB[1] += p->buf[XADAPTCOEFFSB-1];
+ p->XcoeffsB[2] += p->buf[XADAPTCOEFFSB-2];
+ p->XcoeffsB[3] += p->buf[XADAPTCOEFFSB-3];
+ p->XcoeffsB[4] += p->buf[XADAPTCOEFFSB-4];
+ }
+ }
+
+ *(decoded1++) = p->XfilterA;
+
+ /* Combined */
+ p->buf++;
+
+ /* Have we filled the history buffer? */
+ if (UNLIKELY(p->buf == p->historybuffer + PREDICTOR_HISTORY_SIZE)) {
+ memmove(p->historybuffer, p->buf,
+ PREDICTOR_SIZE * sizeof(int32_t));
+ p->buf = p->historybuffer;
+ }
+ }
+}
+
+void ICODE_ATTR_DEMAC predictor_decode_mono(struct predictor_t* p,
+ int32_t* decoded0,
+ int count)
+{
+ int32_t predictionA, currentA, A;
+
+ currentA = p->YlastA;
+
+ while (LIKELY(count--))
+ {
+ A = *decoded0;
+
+ p->buf[YDELAYA] = currentA;
+ p->buf[YDELAYA-1] = p->buf[YDELAYA] - p->buf[YDELAYA-1];
+
+ predictionA = (p->buf[YDELAYA] * p->YcoeffsA[0]) +
+ (p->buf[YDELAYA-1] * p->YcoeffsA[1]) +
+ (p->buf[YDELAYA-2] * p->YcoeffsA[2]) +
+ (p->buf[YDELAYA-3] * p->YcoeffsA[3]);
+
+ currentA = A + (predictionA >> 10);
+
+ p->buf[YADAPTCOEFFSA] = SIGN(p->buf[YDELAYA]);
+ p->buf[YADAPTCOEFFSA-1] = SIGN(p->buf[YDELAYA-1]);
+
+ if (LIKELY(A != 0))
+ {
+ if (A > 0)
+ {
+ p->YcoeffsA[0] -= p->buf[YADAPTCOEFFSA];
+ p->YcoeffsA[1] -= p->buf[YADAPTCOEFFSA-1];
+ p->YcoeffsA[2] -= p->buf[YADAPTCOEFFSA-2];
+ p->YcoeffsA[3] -= p->buf[YADAPTCOEFFSA-3];
+ }
+ else
+ {
+ p->YcoeffsA[0] += p->buf[YADAPTCOEFFSA];
+ p->YcoeffsA[1] += p->buf[YADAPTCOEFFSA-1];
+ p->YcoeffsA[2] += p->buf[YADAPTCOEFFSA-2];
+ p->YcoeffsA[3] += p->buf[YADAPTCOEFFSA-3];
+ }
+ }
+
+ p->buf++;
+
+ /* Have we filled the history buffer? */
+ if (UNLIKELY(p->buf == p->historybuffer + PREDICTOR_HISTORY_SIZE)) {
+ memmove(p->historybuffer, p->buf,
+ PREDICTOR_SIZE * sizeof(int32_t));
+ p->buf = p->historybuffer;
+ }
+
+ p->YfilterA = currentA + ((p->YfilterA * 31) >> 5);
+ *(decoded0++) = p->YfilterA;
+ }
+
+ p->YlastA = currentA;
+}
+#endif
diff --git a/lib/rbcodec/codecs/demac/libdemac/predictor.h b/lib/rbcodec/codecs/demac/libdemac/predictor.h
new file mode 100644
index 0000000000..6a0a81983b
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/predictor.h
@@ -0,0 +1,38 @@
+/*
+
+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 predictor_t* p);
+void predictor_decode_stereo(struct predictor_t* p, int32_t* decoded0,
+ int32_t* decoded1, int count);
+void predictor_decode_mono(struct predictor_t* p, int32_t* decoded0,
+ int count);
+
+#endif
diff --git a/lib/rbcodec/codecs/demac/libdemac/udiv32_arm-pre.S b/lib/rbcodec/codecs/demac/libdemac/udiv32_arm-pre.S
new file mode 100644
index 0000000000..459cab8240
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/udiv32_arm-pre.S
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2010 by Andrew Mahone
+ *
+ * Wrapper for udiv32_arm.S to test available IRAM by pre-linking the codec.
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#define APE_PRE
+#include "udiv32_arm.S"
diff --git a/lib/rbcodec/codecs/demac/libdemac/udiv32_arm.S b/lib/rbcodec/codecs/demac/libdemac/udiv32_arm.S
new file mode 100644
index 0000000000..7b851659bd
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/udiv32_arm.S
@@ -0,0 +1,318 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2008 by Jens Arnold
+ * Copyright (C) 2009 by Andrew Mahone
+ *
+ * Optimised unsigned integer division for ARMv4
+ *
+ * Based on: libgcc routines for ARM cpu, additional algorithms from ARM System
+ * Developer's Guide
+ * Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
+ * Copyright 1995, 1996, 1998, 1999, 2000, 2003, 2004, 2005
+ * Free Software Foundation, Inc.
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "config.h"
+/* On targets with codec iram, a header file will be generated after an initial
+ link of the APE codec, stating the amount of IRAM remaining for use by the
+ reciprocal lookup table. */
+#if !defined(APE_PRE) && defined(USE_IRAM) && ARM_ARCH < 5
+#include "lib/rbcodec/codecs/ape_free_iram.h"
+#endif
+
+/* Codecs should not normally do this, but we need to check a macro, and
+ * codecs.h would confuse the assembler. */
+
+#ifdef USE_IRAM
+#define DIV_RECIP
+ .section .icode,"ax",%progbits
+#else
+ .text
+#endif
+ .align
+ .global udiv32_arm
+ .type udiv32_arm,%function
+
+#if ARM_ARCH < 5
+/* Adapted from an algorithm given in ARM System Developer's Guide (7.3.1.2)
+ for dividing a 30-bit value by a 15-bit value, with two operations per
+ iteration by storing quotient and remainder together and adding the previous
+ quotient bit during trial subtraction. Modified to work with any dividend
+ and divisor both less than 1 << 30, and skipping trials by calculating bits
+ in output. */
+.macro ARM_DIV_31_BODY dividend, divisor, result, bits, curbit, quotient, remainder
+
+ mov \bits, #1
+ /* Shift the divisor left until it aligns with the numerator. If it already
+ has the high bit set, this is fine, everything inside .rept will be
+ skipped, and the add before and adcs after will set the one-bit result
+ to zero. */
+ cmn \divisor, \dividend, lsr #16
+ movcs \divisor, \divisor, lsl #16
+ addcs \bits, \bits, #16
+ cmn \divisor, \dividend, lsr #8
+ movcs \divisor, \divisor, lsl #8
+ addcs \bits, \bits, #8
+ cmn \divisor, \dividend, lsr #4
+ movcs \divisor, \divisor, lsl #4
+ addcs \bits, \bits, #4
+ cmn \divisor, \dividend, lsr #2
+ movcs \divisor, \divisor, lsl #2
+ addcs \bits, \bits, #2
+ cmn \divisor, \dividend, lsr #1
+ movcs \divisor, \divisor, lsl #1
+ addcs \bits, \bits, #1
+ adds \result, \dividend, \divisor
+ subcc \result, \result, \divisor
+ rsb \curbit, \bits, #31
+ add pc, pc, \curbit, lsl #3
+ nop
+ .rept 30
+ adcs \result, \divisor, \result, lsl #1
+ /* Fix the remainder portion of the result. This must be done because the
+ handler for 32-bit numerators needs the remainder. */
+ subcc \result, \result, \divisor
+ .endr
+ /* Shift remainder/quotient left one, add final quotient bit */
+ adc \result, \result, \result
+ mov \remainder, \result, lsr \bits
+ eor \quotient, \result, \remainder, lsl \bits
+.endm
+
+#ifndef FREE_IRAM
+.set recip_max, 2
+#else
+/* Each table entry is one word. Since a compare is done against the maximum
+ entry as an immediate, the maximum entry must be a valid ARM immediate,
+ which means a byte shifted by an even number of places. */
+.set recip_max, 2 + FREE_IRAM / 4
+.set recip_max_tmp, recip_max >> 8
+.set recip_mask_shift, 0
+.set tmp_shift, 16
+.rept 5
+ .if recip_max_tmp >> tmp_shift
+ .set recip_max_tmp, recip_max_tmp >> tmp_shift
+ .set recip_mask_shift, recip_mask_shift + tmp_shift
+ .endif
+ .set tmp_shift, tmp_shift >> 1
+.endr
+.if recip_max_tmp
+ .set recip_mask_shift, recip_mask_shift + 1
+.endif
+.set recip_mask_shift, (recip_mask_shift + 1) & 62
+.set recip_max, recip_max & (255 << recip_mask_shift)
+//.set recip_max, 2
+#endif
+
+udiv32_arm:
+#ifdef DIV_RECIP
+ cmp r1, #3
+ bcc .L_udiv_tiny
+ cmp r1, #recip_max
+ bhi .L_udiv
+ adr r3, .L_udiv_recip_table-12
+ ldr r2, [r3, r1, lsl #2]
+ mov r3, r0
+ umull ip, r0, r2, r0
+ mul r2, r0, r1
+ cmp r3, r2
+ bxcs lr
+ sub r0, r0, #1
+ bx lr
+.L_udiv_tiny:
+ cmp r1, #1
+ movhi r0, r0, lsr #1
+ bxcs lr
+ b .L_div0
+#endif
+.L_udiv:
+ /* Invert divisor. ARM_DIV_31_BODY uses adc to both subtract the divisor
+ and add the next bit of the result. The correction code at .L_udiv32
+ does not need the divisor inverted, but can be modified to work with it,
+ and this allows the zero divisor test to be done early and without an
+ explicit comparison. */
+ rsbs r1, r1, #0
+#ifndef DIV_RECIP
+ beq .L_div0
+#endif
+ tst r0, r0
+ /* High bit must be unset, otherwise shift numerator right, calculate,
+ and correct results. As this case is very uncommon we want to avoid
+ any other delays on the main path in handling it, so the long divide
+ calls the short divide as a function. */
+ bmi .L_udiv32
+.L_udiv31:
+ ARM_DIV_31_BODY r0, r1, r2, r3, ip, r0, r1
+ bx lr
+.L_udiv32:
+ /* store original numerator and divisor, we'll need them to correct the
+ result, */
+ stmdb sp, { r0, r1, lr }
+ /* Call __div0 here if divisor is zero, otherwise it would report the wrong
+ address. */
+ mov r0, r0, lsr #1
+ bl .L_udiv31
+ ldmdb sp, { r2, r3, lr }
+ /* Move the low bit of the original numerator to the carry bit */
+ movs r2, r2, lsr #1
+ /* Shift the remainder left one and add in the carry bit */
+ adc r1, r1, r1
+ /* Subtract the original divisor from the remainder, setting carry if the
+ result is non-negative */
+ adds r1, r1, r3
+ /* Shift quotient left one and add carry bit */
+ adc r0, r0, r0
+ bx lr
+.L_div0:
+ /* __div0 expects the calling address on the top of the stack */
+ stmdb sp!, { lr }
+ mov r0, #0
+#if defined(__ARM_EABI__) || !defined(USE_IRAM)
+ bl __div0
+#else
+ ldr pc, [pc, #-4]
+ .word __div0
+#endif
+#ifdef DIV_RECIP
+.L_udiv_recip_table:
+ .set div, 3
+ .rept recip_max - 2
+ .if (div - 1) & div
+ .set q, 0x40000000 / div
+ .set r, (0x40000000 - (q * div))<<1
+ .set q, q << 1
+ .if r >= div
+ .set q, q + 1
+ .set r, r - div
+ .endif
+ .set r, r << 1
+ .set q, q << 1
+ .if r >= div
+ .set q, q + 1
+ .set r, r - div
+ .endif
+ .set q, q + 1
+ .else
+ .set q, 0x40000000 / div * 4
+ .endif
+ .word q
+ .set div, div+1
+ .endr
+#endif
+ .size udiv32_arm, . - udiv32_arm
+
+#else
+.macro ARMV5_UDIV32_BODY numerator, divisor, quotient, bits, inv, neg, div0label
+ cmp \numerator, \divisor
+ clz \bits, \divisor
+ bcc 30f
+ mov \inv, \divisor, lsl \bits
+ add \neg, pc, \inv, lsr #25
+ cmp \inv, #1<<31
+ ldrhib \inv, [\neg, #.L_udiv_est_table-.-64]
+ bls 20f
+ subs \bits, \bits, #7
+ rsb \neg, \divisor, #0
+ movpl \divisor, \inv, lsl \bits
+ bmi 10f
+ mul \inv, \divisor, \neg
+ smlawt \divisor, \divisor, \inv, \divisor
+ mul \inv, \divisor, \neg
+ /* This will save a cycle on ARMv6, but requires that the numerator sign
+ bit is not set (that of inv is guaranteed unset). The branch should
+ predict very well, making it typically 1 cycle, and thus both the branch
+ and test fill delay cycles for the multiplies. Based on logging of
+ numerator sizes in the APE codec, the branch is taken about 1/10^7 of
+ the time. */
+#if ARM_ARCH >= 6
+ tst \numerator, \numerator
+ smmla \divisor, \divisor, \inv, \divisor
+ bmi 40f
+ smmul \inv, \numerator, \divisor
+#else
+ mov \bits, #0
+ smlal \bits, \divisor, \inv, \divisor
+ umull \bits, \inv, \numerator, \divisor
+#endif
+ add \numerator, \numerator, \neg
+ mla \divisor, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \divisor, \neg
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+ bx lr
+10:
+ rsb \bits, \bits, #0
+ sub \inv, \inv, #4
+ mov \divisor, \inv, lsr \bits
+ umull \bits, \inv, \numerator, \divisor
+ mla \divisor, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \neg, \divisor, lsr #1
+ addcs \divisor, \divisor, \neg, lsl #1
+ addcs \quotient, \quotient, #2
+ cmn \neg, \divisor
+ addcs \quotient, \quotient, #1
+ bx lr
+20:
+.ifnc "", "\div0label"
+ rsb \bits, \bits, #31
+ bne \div0label
+.endif
+ mov \quotient, \numerator, lsr \bits
+ bx lr
+30:
+ mov \quotient, #0
+ bx lr
+#if ARM_ARCH >= 6
+40:
+ umull \bits, \inv, \numerator, \divisor
+ add \numerator, \numerator, \neg
+ mla \divisor, \inv, \neg, \numerator
+ mov \quotient, \inv
+ cmn \divisor, \neg
+ addcc \quotient, \quotient, #1
+ addpl \quotient, \quotient, #2
+ bx lr
+#endif
+.endm
+
+udiv32_arm:
+ ARMV5_UDIV32_BODY r0, r1, r0, r2, r3, ip, .L_div0
+.L_div0:
+ /* __div0 expects the calling address on the top of the stack */
+ stmdb sp!, { lr }
+ mov r0, #0
+#if defined(__ARM_EABI__) || !defined(USE_IRAM)
+ bl __div0
+#else
+ ldr pc, [pc, #-4]
+ .word __div0
+#endif
+.L_udiv_est_table:
+ .byte 0xff, 0xfc, 0xf8, 0xf4, 0xf0, 0xed, 0xea, 0xe6
+ .byte 0xe3, 0xe0, 0xdd, 0xda, 0xd7, 0xd4, 0xd2, 0xcf
+ .byte 0xcc, 0xca, 0xc7, 0xc5, 0xc3, 0xc0, 0xbe, 0xbc
+ .byte 0xba, 0xb8, 0xb6, 0xb4, 0xb2, 0xb0, 0xae, 0xac
+ .byte 0xaa, 0xa8, 0xa7, 0xa5, 0xa3, 0xa2, 0xa0, 0x9f
+ .byte 0x9d, 0x9c, 0x9a, 0x99, 0x97, 0x96, 0x94, 0x93
+ .byte 0x92, 0x90, 0x8f, 0x8e, 0x8d, 0x8c, 0x8a, 0x89
+ .byte 0x88, 0x87, 0x86, 0x85, 0x84, 0x83, 0x82, 0x81
+#endif
+ .size udiv32_arm, . - udiv32_arm
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv5te.h b/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv5te.h
new file mode 100644
index 0000000000..ae7427c137
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv5te.h
@@ -0,0 +1,404 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+ARMv5te vector math copyright (C) 2008 Jens Arnold
+
+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 FUSED_VECTOR_MATH
+
+#define REPEAT_3(x) x x x
+#if ORDER > 16
+#define REPEAT_MLA(x) x x x x x x x
+#else
+#define REPEAT_MLA(x) x x x
+#endif
+
+/* Calculate scalarproduct, then add a 2nd vector (fused for performance)
+ * This version fetches data as 32 bit words, and *requires* v1 to be
+ * 32 bit aligned. It also requires that f2 and s2 are either both 32 bit
+ * aligned or both unaligned. If either condition isn't met, it will either
+ * result in a data abort or incorrect results. */
+static inline int32_t vector_sp_add(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 16
+ int cnt = ORDER>>4;
+#endif
+
+#define ADDHALFREGS(sum, s1, s2) /* Adds register */ \
+ "mov " #s1 ", " #s1 ", ror #16 \n" /* halves straight */ \
+ "add " #sum ", " #s1 ", " #s2 ", lsl #16 \n" /* Clobbers 's1' */ \
+ "add " #s1 ", " #s1 ", " #s2 ", lsr #16 \n" \
+ "mov " #s1 ", " #s1 ", lsl #16 \n" \
+ "orr " #sum ", " #s1 ", " #sum ", lsr #16 \n"
+
+#define ADDHALFXREGS(sum, s1, s2) /* Adds register */ \
+ "add " #s1 ", " #s1 ", " #sum ", lsl #16 \n" /* halves across. */ \
+ "add " #sum ", " #s2 ", " #sum ", lsr #16 \n" /* Clobbers 's1'. */ \
+ "mov " #sum ", " #sum ", lsl #16 \n" \
+ "orr " #sum ", " #sum ", " #s1 ", lsr #16 \n"
+
+ asm volatile (
+#if ORDER > 16
+ "mov %[res], #0 \n"
+#endif
+ "tst %[f2], #2 \n"
+ "beq 20f \n"
+
+ "10: \n"
+ "ldrh r4, [%[s2]], #2 \n"
+ "mov r4, r4, lsl #16 \n"
+ "ldrh r3, [%[f2]], #2 \n"
+#if ORDER > 16
+ "mov r3, r3, lsl #16 \n"
+ "1: \n"
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+#else
+ "ldmia %[v1], {r0,r1} \n"
+ "smulbb %[res], r0, r3 \n"
+#endif
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r5} \n"
+ ADDHALFXREGS(r0, r4, r2)
+ ADDHALFXREGS(r1, r2, r5)
+ "stmia %[v1]!, {r0,r1} \n"
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r4} \n"
+ ADDHALFXREGS(r0, r5, r2)
+ ADDHALFXREGS(r1, r2, r4)
+ "stmia %[v1]!, {r0,r1} \n"
+
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r5} \n"
+ ADDHALFXREGS(r0, r4, r2)
+ ADDHALFXREGS(r1, r2, r5)
+ "stmia %[v1]!, {r0,r1} \n"
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r4} \n"
+ ADDHALFXREGS(r0, r5, r2)
+ ADDHALFXREGS(r1, r2, r4)
+ "stmia %[v1]!, {r0,r1} \n"
+#if ORDER > 16
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+ "b 99f \n"
+
+ "20: \n"
+ "1: \n"
+ "ldmia %[v1], {r1,r2} \n"
+ "ldmia %[f2]!, {r3,r4} \n"
+#if ORDER > 16
+ "smlabb %[res], r1, r3, %[res] \n"
+#else
+ "smulbb %[res], r1, r3 \n"
+#endif
+ "smlatt %[res], r1, r3, %[res] \n"
+ "smlabb %[res], r2, r4, %[res] \n"
+ "smlatt %[res], r2, r4, %[res] \n"
+ "ldmia %[s2]!, {r3,r4} \n"
+ ADDHALFREGS(r0, r1, r3)
+ ADDHALFREGS(r1, r2, r4)
+ "stmia %[v1]!, {r0,r1} \n"
+
+ REPEAT_3(
+ "ldmia %[v1], {r1,r2} \n"
+ "ldmia %[f2]!, {r3,r4} \n"
+ "smlabb %[res], r1, r3, %[res] \n"
+ "smlatt %[res], r1, r3, %[res] \n"
+ "smlabb %[res], r2, r4, %[res] \n"
+ "smlatt %[res], r2, r4, %[res] \n"
+ "ldmia %[s2]!, {r3,r4} \n"
+ ADDHALFREGS(r0, r1, r3)
+ ADDHALFREGS(r1, r2, r4)
+ "stmia %[v1]!, {r0,r1} \n"
+ )
+#if ORDER > 16
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+
+ "99: \n"
+ : /* outputs */
+#if ORDER > 16
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "r4", "r5", "cc", "memory"
+ );
+ return res;
+}
+
+/* Calculate scalarproduct, then subtract a 2nd vector (fused for performance)
+ * This version fetches data as 32 bit words, and *requires* v1 to be
+ * 32 bit aligned. It also requires that f2 and s2 are either both 32 bit
+ * aligned or both unaligned. If either condition isn't met, it will either
+ * result in a data abort or incorrect results. */
+static inline int32_t vector_sp_sub(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 16
+ int cnt = ORDER>>4;
+#endif
+
+#define SUBHALFREGS(dif, s1, s2) /* Subtracts reg. */ \
+ "mov " #s1 ", " #s1 ", ror #16 \n" /* halves straight */ \
+ "sub " #dif ", " #s1 ", " #s2 ", lsl #16 \n" /* Clobbers 's1' */ \
+ "sub " #s1 ", " #s1 ", " #s2 ", lsr #16 \n" \
+ "mov " #s1 ", " #s1 ", lsl #16 \n" \
+ "orr " #dif ", " #s1 ", " #dif ", lsr #16 \n"
+
+#define SUBHALFXREGS(dif, s1, s2, msk) /* Subtracts reg. */ \
+ "sub " #s1 ", " #dif ", " #s1 ", lsr #16 \n" /* halves across. */ \
+ "and " #s1 ", " #s1 ", " #msk " \n" /* Needs msk = */ \
+ "rsb " #dif ", " #s2 ", " #dif ", lsr #16 \n" /* 0x0000ffff, */ \
+ "orr " #dif ", " #s1 ", " #dif ", lsl #16 \n" /* clobbers 's1'. */
+
+ asm volatile (
+#if ORDER > 16
+ "mov %[res], #0 \n"
+#endif
+ "tst %[f2], #2 \n"
+ "beq 20f \n"
+
+ "10: \n"
+ "mov r6, #0xff \n"
+ "orr r6, r6, #0xff00 \n"
+ "ldrh r4, [%[s2]], #2 \n"
+ "mov r4, r4, lsl #16 \n"
+ "ldrh r3, [%[f2]], #2 \n"
+#if ORDER > 16
+ "mov r3, r3, lsl #16 \n"
+ "1: \n"
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+#else
+ "ldmia %[v1], {r0,r1} \n"
+ "smulbb %[res], r0, r3 \n"
+#endif
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r5} \n"
+ SUBHALFXREGS(r0, r4, r2, r6)
+ SUBHALFXREGS(r1, r2, r5, r6)
+ "stmia %[v1]!, {r0,r1} \n"
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r4} \n"
+ SUBHALFXREGS(r0, r5, r2, r6)
+ SUBHALFXREGS(r1, r2, r4, r6)
+ "stmia %[v1]!, {r0,r1} \n"
+
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r5} \n"
+ SUBHALFXREGS(r0, r4, r2, r6)
+ SUBHALFXREGS(r1, r2, r5, r6)
+ "stmia %[v1]!, {r0,r1} \n"
+ "ldmia %[v1], {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ "ldmia %[s2]!, {r2,r4} \n"
+ SUBHALFXREGS(r0, r5, r2, r6)
+ SUBHALFXREGS(r1, r2, r4, r6)
+ "stmia %[v1]!, {r0,r1} \n"
+#if ORDER > 16
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+ "b 99f \n"
+
+ "20: \n"
+ "1: \n"
+ "ldmia %[v1], {r1,r2} \n"
+ "ldmia %[f2]!, {r3,r4} \n"
+#if ORDER > 16
+ "smlabb %[res], r1, r3, %[res] \n"
+#else
+ "smulbb %[res], r1, r3 \n"
+#endif
+ "smlatt %[res], r1, r3, %[res] \n"
+ "smlabb %[res], r2, r4, %[res] \n"
+ "smlatt %[res], r2, r4, %[res] \n"
+ "ldmia %[s2]!, {r3,r4} \n"
+ SUBHALFREGS(r0, r1, r3)
+ SUBHALFREGS(r1, r2, r4)
+ "stmia %[v1]!, {r0,r1} \n"
+
+ REPEAT_3(
+ "ldmia %[v1], {r1,r2} \n"
+ "ldmia %[f2]!, {r3,r4} \n"
+ "smlabb %[res], r1, r3, %[res] \n"
+ "smlatt %[res], r1, r3, %[res] \n"
+ "smlabb %[res], r2, r4, %[res] \n"
+ "smlatt %[res], r2, r4, %[res] \n"
+ "ldmia %[s2]!, {r3,r4} \n"
+ SUBHALFREGS(r0, r1, r3)
+ SUBHALFREGS(r1, r2, r4)
+ "stmia %[v1]!, {r0,r1} \n"
+ )
+#if ORDER > 16
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+
+ "99: \n"
+ : /* outputs */
+#if ORDER > 16
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "r4", "r5", "r6", "cc", "memory"
+ );
+ return res;
+}
+
+/* This version fetches data as 32 bit words, and *requires* v1 to be
+ * 32 bit aligned, otherwise it will result either in a data abort, or
+ * incorrect results (if ARM aligncheck is disabled). */
+static inline int32_t scalarproduct(int16_t* v1, int16_t* v2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+#endif
+ "tst %[v2], #2 \n"
+ "beq 20f \n"
+
+ "10: \n"
+ "ldrh r3, [%[v2]], #2 \n"
+#if ORDER > 32
+ "mov r3, r3, lsl #16 \n"
+ "1: \n"
+ "ldmia %[v1]!, {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+#else
+ "ldmia %[v1]!, {r0,r1} \n"
+ "smulbb %[res], r0, r3 \n"
+#endif
+ "ldmia %[v2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+
+ REPEAT_MLA(
+ "ldmia %[v1]!, {r0,r1} \n"
+ "smlabt %[res], r0, r3, %[res] \n"
+ "ldmia %[v2]!, {r2,r3} \n"
+ "smlatb %[res], r0, r2, %[res] \n"
+ "smlabt %[res], r1, r2, %[res] \n"
+ "smlatb %[res], r1, r3, %[res] \n"
+ )
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+ "b 99f \n"
+
+ "20: \n"
+ "1: \n"
+ "ldmia %[v1]!, {r0,r1} \n"
+ "ldmia %[v2]!, {r2,r3} \n"
+#if ORDER > 32
+ "smlabb %[res], r0, r2, %[res] \n"
+#else
+ "smulbb %[res], r0, r2 \n"
+#endif
+ "smlatt %[res], r0, r2, %[res] \n"
+ "smlabb %[res], r1, r3, %[res] \n"
+ "smlatt %[res], r1, r3, %[res] \n"
+
+ REPEAT_MLA(
+ "ldmia %[v1]!, {r0,r1} \n"
+ "ldmia %[v2]!, {r2,r3} \n"
+ "smlabb %[res], r0, r2, %[res] \n"
+ "smlatt %[res], r0, r2, %[res] \n"
+ "smlabb %[res], r1, r3, %[res] \n"
+ "smlatt %[res], r1, r3, %[res] \n"
+ )
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+
+ "99: \n"
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [v2] "+r"(v2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "cc", "memory"
+ );
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv6.h b/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv6.h
new file mode 100644
index 0000000000..8d27331b62
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv6.h
@@ -0,0 +1,490 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+ARMv6 vector math copyright (C) 2008 Jens Arnold
+
+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 FUSED_VECTOR_MATH
+
+#if ORDER > 16
+#define REPEAT_BLOCK(x) x x x
+#else
+#define REPEAT_BLOCK(x) x
+#endif
+
+/* Calculate scalarproduct, then add a 2nd vector (fused for performance)
+ * This version fetches data as 32 bit words, and *requires* v1 to be
+ * 32 bit aligned. It also requires that f2 and s2 are either both 32 bit
+ * aligned or both unaligned. If either condition isn't met, it will either
+ * result in a data abort or incorrect results. */
+static inline int32_t vector_sp_add(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+#endif
+ "tst %[f2], #2 \n"
+ "beq 20f \n"
+
+ "10: \n"
+ "ldrh r3, [%[f2]], #2 \n"
+ "ldrh r6, [%[s2]], #2 \n"
+ "ldmia %[f2]!, {r2,r4} \n"
+ "mov r3, r3, lsl #16 \n"
+ "mov r6, r6, lsl #16 \n"
+
+ "1: \n"
+ "ldmia %[s2]!, {r5,r7} \n"
+ "pkhtb r3, r3, r2 \n"
+ "pkhtb r2, r2, r4 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r6, r5, r6, asr #16 \n"
+ "pkhbt r5, r5, r7, lsl #16 \n"
+#if ORDER > 32
+ "smladx %[res], r0, r3, %[res] \n"
+#else
+ "smuadx %[res], r0, r3 \n"
+#endif
+ "smladx %[res], r1, r2, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "sadd16 r0, r0, r6 \n"
+ "sadd16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+
+ REPEAT_BLOCK(
+ "ldmia %[s2]!, {r5,r6} \n"
+ "pkhtb r4, r4, r2 \n"
+ "pkhtb r2, r2, r3 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r7, r5, r7, asr #16 \n"
+ "pkhbt r5, r5, r6, lsl #16 \n"
+ "smladx %[res], r0, r4, %[res] \n"
+ "smladx %[res], r1, r2, %[res] \n"
+ "ldmia %[f2]!, {r2,r4} \n"
+ "sadd16 r0, r0, r7 \n"
+ "sadd16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+ "ldmia %[s2]!, {r5,r7} \n"
+ "pkhtb r3, r3, r2 \n"
+ "pkhtb r2, r2, r4 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r6, r5, r6, asr #16 \n"
+ "pkhbt r5, r5, r7, lsl #16 \n"
+ "smladx %[res], r0, r3, %[res] \n"
+ "smladx %[res], r1, r2, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "sadd16 r0, r0, r6 \n"
+ "sadd16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+ )
+
+ "ldmia %[s2]!, {r5,r6} \n"
+ "pkhtb r4, r4, r2 \n"
+ "pkhtb r2, r2, r3 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r7, r5, r7, asr #16 \n"
+ "pkhbt r5, r5, r6, lsl #16 \n"
+ "smladx %[res], r0, r4, %[res] \n"
+ "smladx %[res], r1, r2, %[res] \n"
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "ldmneia %[f2]!, {r2,r4} \n"
+ "sadd16 r0, r0, r7 \n"
+ "sadd16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+ "bne 1b \n"
+#else
+ "sadd16 r0, r0, r7 \n"
+ "sadd16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+#endif
+
+ "b 99f \n"
+
+ "20: \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r0, [%[v1]] \n"
+
+#if ORDER > 32
+ "1: \n"
+ "smlad %[res], r0, r4, %[res] \n"
+#else
+ "smuad %[res], r0, r4 \n"
+#endif
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r1, r5, %[res] \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r2, [%[v1], #8] \n"
+ "sadd16 r0, r0, r6 \n"
+ "sadd16 r1, r1, r7 \n"
+ "strd r0, [%[v1]], #8 \n"
+
+ REPEAT_BLOCK(
+ "smlad %[res], r2, r4, %[res] \n"
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r3, r5, %[res] \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r0, [%[v1], #8] \n"
+ "sadd16 r2, r2, r6 \n"
+ "sadd16 r3, r3, r7 \n"
+ "strd r2, [%[v1]], #8 \n"
+ "smlad %[res], r0, r4, %[res] \n"
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r1, r5, %[res] \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r2, [%[v1], #8] \n"
+ "sadd16 r0, r0, r6 \n"
+ "sadd16 r1, r1, r7 \n"
+ "strd r0, [%[v1]], #8 \n"
+ )
+
+ "smlad %[res], r2, r4, %[res] \n"
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r3, r5, %[res] \n"
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "ldrned r4, [%[f2]], #8 \n"
+ "ldrned r0, [%[v1], #8] \n"
+ "sadd16 r2, r2, r6 \n"
+ "sadd16 r3, r3, r7 \n"
+ "strd r2, [%[v1]], #8 \n"
+ "bne 1b \n"
+#else
+ "sadd16 r2, r2, r6 \n"
+ "sadd16 r3, r3, r7 \n"
+ "strd r2, [%[v1]], #8 \n"
+#endif
+
+ "99: \n"
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "r4",
+ "r5", "r6", "r7", "cc", "memory"
+ );
+ return res;
+}
+
+/* Calculate scalarproduct, then subtract a 2nd vector (fused for performance)
+ * This version fetches data as 32 bit words, and *requires* v1 to be
+ * 32 bit aligned. It also requires that f2 and s2 are either both 32 bit
+ * aligned or both unaligned. If either condition isn't met, it will either
+ * result in a data abort or incorrect results. */
+static inline int32_t vector_sp_sub(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+#endif
+ "tst %[f2], #2 \n"
+ "beq 20f \n"
+
+ "10: \n"
+ "ldrh r3, [%[f2]], #2 \n"
+ "ldrh r6, [%[s2]], #2 \n"
+ "ldmia %[f2]!, {r2,r4} \n"
+ "mov r3, r3, lsl #16 \n"
+ "mov r6, r6, lsl #16 \n"
+
+ "1: \n"
+ "ldmia %[s2]!, {r5,r7} \n"
+ "pkhtb r3, r3, r2 \n"
+ "pkhtb r2, r2, r4 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r6, r5, r6, asr #16 \n"
+ "pkhbt r5, r5, r7, lsl #16 \n"
+#if ORDER > 32
+ "smladx %[res], r0, r3, %[res] \n"
+#else
+ "smuadx %[res], r0, r3 \n"
+#endif
+ "smladx %[res], r1, r2, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "ssub16 r0, r0, r6 \n"
+ "ssub16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+
+ REPEAT_BLOCK(
+ "ldmia %[s2]!, {r5,r6} \n"
+ "pkhtb r4, r4, r2 \n"
+ "pkhtb r2, r2, r3 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r7, r5, r7, asr #16 \n"
+ "pkhbt r5, r5, r6, lsl #16 \n"
+ "smladx %[res], r0, r4, %[res] \n"
+ "smladx %[res], r1, r2, %[res] \n"
+ "ldmia %[f2]!, {r2,r4} \n"
+ "ssub16 r0, r0, r7 \n"
+ "ssub16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+ "ldmia %[s2]!, {r5,r7} \n"
+ "pkhtb r3, r3, r2 \n"
+ "pkhtb r2, r2, r4 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r6, r5, r6, asr #16 \n"
+ "pkhbt r5, r5, r7, lsl #16 \n"
+ "smladx %[res], r0, r3, %[res] \n"
+ "smladx %[res], r1, r2, %[res] \n"
+ "ldmia %[f2]!, {r2,r3} \n"
+ "ssub16 r0, r0, r6 \n"
+ "ssub16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+ )
+
+ "ldmia %[s2]!, {r5,r6} \n"
+ "pkhtb r4, r4, r2 \n"
+ "pkhtb r2, r2, r3 \n"
+ "ldrd r0, [%[v1]] \n"
+ "mov r5, r5, ror #16 \n"
+ "pkhtb r7, r5, r7, asr #16 \n"
+ "pkhbt r5, r5, r6, lsl #16 \n"
+ "smladx %[res], r0, r4, %[res] \n"
+ "smladx %[res], r1, r2, %[res] \n"
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "ldmneia %[f2]!, {r2,r4} \n"
+ "ssub16 r0, r0, r7 \n"
+ "ssub16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+ "bne 1b \n"
+#else
+ "ssub16 r0, r0, r7 \n"
+ "ssub16 r1, r1, r5 \n"
+ "strd r0, [%[v1]], #8 \n"
+#endif
+
+ "b 99f \n"
+
+ "20: \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r0, [%[v1]] \n"
+
+#if ORDER > 32
+ "1: \n"
+ "smlad %[res], r0, r4, %[res] \n"
+#else
+ "smuad %[res], r0, r4 \n"
+#endif
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r1, r5, %[res] \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r2, [%[v1], #8] \n"
+ "ssub16 r0, r0, r6 \n"
+ "ssub16 r1, r1, r7 \n"
+ "strd r0, [%[v1]], #8 \n"
+
+ REPEAT_BLOCK(
+ "smlad %[res], r2, r4, %[res] \n"
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r3, r5, %[res] \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r0, [%[v1], #8] \n"
+ "ssub16 r2, r2, r6 \n"
+ "ssub16 r3, r3, r7 \n"
+ "strd r2, [%[v1]], #8 \n"
+ "smlad %[res], r0, r4, %[res] \n"
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r1, r5, %[res] \n"
+ "ldrd r4, [%[f2]], #8 \n"
+ "ldrd r2, [%[v1], #8] \n"
+ "ssub16 r0, r0, r6 \n"
+ "ssub16 r1, r1, r7 \n"
+ "strd r0, [%[v1]], #8 \n"
+ )
+
+ "smlad %[res], r2, r4, %[res] \n"
+ "ldrd r6, [%[s2]], #8 \n"
+ "smlad %[res], r3, r5, %[res] \n"
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "ldrned r4, [%[f2]], #8 \n"
+ "ldrned r0, [%[v1], #8] \n"
+ "ssub16 r2, r2, r6 \n"
+ "ssub16 r3, r3, r7 \n"
+ "strd r2, [%[v1]], #8 \n"
+ "bne 1b \n"
+#else
+ "ssub16 r2, r2, r6 \n"
+ "ssub16 r3, r3, r7 \n"
+ "strd r2, [%[v1]], #8 \n"
+#endif
+
+ "99: \n"
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "r4",
+ "r5", "r6", "r7", "cc", "memory"
+ );
+ return res;
+}
+
+/* This version fetches data as 32 bit words, and *requires* v1 to be
+ * 32 bit aligned, otherwise it will result either in a data abort, or
+ * incorrect results (if ARM aligncheck is disabled). */
+static inline int32_t scalarproduct(int16_t* v1, int16_t* v2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+#endif
+ "tst %[v2], #2 \n"
+ "beq 20f \n"
+
+ "10: \n"
+ "bic %[v2], %[v2], #2 \n"
+ "ldmia %[v2]!, {r5-r7} \n"
+ "ldrd r0, [%[v1]], #8 \n"
+
+ "1: \n"
+ "pkhtb r3, r5, r6 \n"
+ "ldrd r4, [%[v2]], #8 \n"
+#if ORDER > 32
+ "smladx %[res], r0, r3, %[res] \n"
+#else
+ "smuadx %[res], r0, r3 \n"
+#endif
+ REPEAT_BLOCK(
+ "pkhtb r0, r6, r7 \n"
+ "ldrd r2, [%[v1]], #8 \n"
+ "smladx %[res], r1, r0, %[res] \n"
+ "pkhtb r1, r7, r4 \n"
+ "ldrd r6, [%[v2]], #8 \n"
+ "smladx %[res], r2, r1, %[res] \n"
+ "pkhtb r2, r4, r5 \n"
+ "ldrd r0, [%[v1]], #8 \n"
+ "smladx %[res], r3, r2, %[res] \n"
+ "pkhtb r3, r5, r6 \n"
+ "ldrd r4, [%[v2]], #8 \n"
+ "smladx %[res], r0, r3, %[res] \n"
+ )
+
+ "pkhtb r0, r6, r7 \n"
+ "ldrd r2, [%[v1]], #8 \n"
+ "smladx %[res], r1, r0, %[res] \n"
+ "pkhtb r1, r7, r4 \n"
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "ldrned r6, [%[v2]], #8 \n"
+ "smladx %[res], r2, r1, %[res] \n"
+ "pkhtb r2, r4, r5 \n"
+ "ldrned r0, [%[v1]], #8 \n"
+ "smladx %[res], r3, r2, %[res] \n"
+ "bne 1b \n"
+#else
+ "pkhtb r4, r4, r5 \n"
+ "smladx %[res], r2, r1, %[res] \n"
+ "smladx %[res], r3, r4, %[res] \n"
+#endif
+
+ "b 99f \n"
+
+ "20: \n"
+ "ldrd r0, [%[v1]], #8 \n"
+ "ldmia %[v2]!, {r5-r7} \n"
+
+ "1: \n"
+ "ldrd r2, [%[v1]], #8 \n"
+#if ORDER > 32
+ "smlad %[res], r0, r5, %[res] \n"
+#else
+ "smuad %[res], r0, r5 \n"
+#endif
+ REPEAT_BLOCK(
+ "ldrd r4, [%[v2]], #8 \n"
+ "smlad %[res], r1, r6, %[res] \n"
+ "ldrd r0, [%[v1]], #8 \n"
+ "smlad %[res], r2, r7, %[res] \n"
+ "ldrd r6, [%[v2]], #8 \n"
+ "smlad %[res], r3, r4, %[res] \n"
+ "ldrd r2, [%[v1]], #8 \n"
+ "smlad %[res], r0, r5, %[res] \n"
+ )
+
+#if ORDER > 32
+ "ldrd r4, [%[v2]], #8 \n"
+ "smlad %[res], r1, r6, %[res] \n"
+ "subs %[cnt], %[cnt], #1 \n"
+ "ldrned r0, [%[v1]], #8 \n"
+ "smlad %[res], r2, r7, %[res] \n"
+ "ldrned r6, [%[v2]], #8 \n"
+ "smlad %[res], r3, r4, %[res] \n"
+ "bne 1b \n"
+#else
+ "ldr r4, [%[v2]], #4 \n"
+ "smlad %[res], r1, r6, %[res] \n"
+ "smlad %[res], r2, r7, %[res] \n"
+ "smlad %[res], r3, r4, %[res] \n"
+#endif
+
+ "99: \n"
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [v2] "+r"(v2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3",
+ "r4", "r5", "r6", "r7", "cc", "memory"
+ );
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv7.h b/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv7.h
new file mode 100644
index 0000000000..84afda3e5d
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math16_armv7.h
@@ -0,0 +1,214 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+ARMv7 neon vector math copyright (C) 2010 Jens Arnold
+
+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 FUSED_VECTOR_MATH
+
+#if ORDER > 32
+#define REPEAT_BLOCK(x) x x x
+#elif ORDER > 16
+#define REPEAT_BLOCK(x) x
+#else
+#define REPEAT_BLOCK(x)
+#endif
+
+/* Calculate scalarproduct, then add a 2nd vector (fused for performance) */
+static inline int32_t vector_sp_add(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 64
+ int cnt = ORDER>>6;
+#endif
+
+ asm volatile (
+#if ORDER > 64
+ "vmov.i16 q0, #0 \n"
+ "1: \n"
+ "subs %[cnt], %[cnt], #1 \n"
+#endif
+ "vld1.16 {d6-d9}, [%[f2]]! \n"
+ "vld1.16 {d2-d5}, [%[v1]] \n"
+ "vld1.16 {d10-d13}, [%[s2]]! \n"
+#if ORDER > 64
+ "vmlal.s16 q0, d2, d6 \n"
+#else
+ "vmull.s16 q0, d2, d6 \n"
+#endif
+ "vmlal.s16 q0, d3, d7 \n"
+ "vmlal.s16 q0, d4, d8 \n"
+ "vmlal.s16 q0, d5, d9 \n"
+ "vadd.i16 q1, q1, q5 \n"
+ "vadd.i16 q2, q2, q6 \n"
+ "vst1.16 {d2-d5}, [%[v1]]! \n"
+
+ REPEAT_BLOCK(
+ "vld1.16 {d6-d9}, [%[f2]]! \n"
+ "vld1.16 {d2-d5}, [%[v1]] \n"
+ "vld1.16 {d10-d13}, [%[s2]]! \n"
+ "vmlal.s16 q0, d2, d6 \n"
+ "vmlal.s16 q0, d3, d7 \n"
+ "vmlal.s16 q0, d4, d8 \n"
+ "vmlal.s16 q0, d5, d9 \n"
+ "vadd.i16 q1, q1, q5 \n"
+ "vadd.i16 q2, q2, q6 \n"
+ "vst1.16 {d2-d5}, [%[v1]]! \n"
+ )
+#if ORDER > 64
+ "bne 1b \n"
+#endif
+ "vpadd.i32 d0, d0, d1 \n"
+ "vpaddl.s32 d0, d0 \n"
+ "vmov.32 %[res], d0[0] \n"
+ : /* outputs */
+#if ORDER > 64
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "d10", "d11", "d12", "d13", "memory"
+ );
+ return res;
+}
+
+/* Calculate scalarproduct, then subtract a 2nd vector (fused for performance) */
+static inline int32_t vector_sp_sub(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 64
+ int cnt = ORDER>>6;
+#endif
+
+ asm volatile (
+#if ORDER > 64
+ "vmov.i16 q0, #0 \n"
+ "1: \n"
+ "subs %[cnt], %[cnt], #1 \n"
+#endif
+ "vld1.16 {d6-d9}, [%[f2]]! \n"
+ "vld1.16 {d2-d5}, [%[v1]] \n"
+ "vld1.16 {d10-d13}, [%[s2]]! \n"
+#if ORDER > 64
+ "vmlal.s16 q0, d2, d6 \n"
+#else
+ "vmull.s16 q0, d2, d6 \n"
+#endif
+ "vmlal.s16 q0, d3, d7 \n"
+ "vmlal.s16 q0, d4, d8 \n"
+ "vmlal.s16 q0, d5, d9 \n"
+ "vsub.i16 q1, q1, q5 \n"
+ "vsub.i16 q2, q2, q6 \n"
+ "vst1.16 {d2-d5}, [%[v1]]! \n"
+
+ REPEAT_BLOCK(
+ "vld1.16 {d6-d9}, [%[f2]]! \n"
+ "vld1.16 {d2-d5}, [%[v1]] \n"
+ "vld1.16 {d10-d13}, [%[s2]]! \n"
+ "vmlal.s16 q0, d2, d6 \n"
+ "vmlal.s16 q0, d3, d7 \n"
+ "vmlal.s16 q0, d4, d8 \n"
+ "vmlal.s16 q0, d5, d9 \n"
+ "vsub.i16 q1, q1, q5 \n"
+ "vsub.i16 q2, q2, q6 \n"
+ "vst1.16 {d2-d5}, [%[v1]]! \n"
+ )
+#if ORDER > 64
+ "bne 1b \n"
+#endif
+ "vpadd.i32 d0, d0, d1 \n"
+ "vpaddl.s32 d0, d0 \n"
+ "vmov.32 %[res], d0[0] \n"
+ : /* outputs */
+#if ORDER > 64
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
+ "d8", "d9", "d10", "d11", "d12", "d13", "memory"
+ );
+ return res;
+}
+
+static inline int32_t scalarproduct(int16_t* v1, int16_t* v2)
+{
+ int res;
+#if ORDER > 64
+ int cnt = ORDER>>6;
+#endif
+
+ asm volatile (
+#if ORDER > 64
+ "vmov.i16 q0, #0 \n"
+ "1: \n"
+ "subs %[cnt], %[cnt], #1 \n"
+#endif
+ "vld1.16 {d2-d5}, [%[v1]]! \n"
+ "vld1.16 {d6-d9}, [%[v2]]! \n"
+#if ORDER > 64
+ "vmlal.s16 q0, d2, d6 \n"
+#else
+ "vmull.s16 q0, d2, d6 \n"
+#endif
+ "vmlal.s16 q0, d3, d7 \n"
+ "vmlal.s16 q0, d4, d8 \n"
+ "vmlal.s16 q0, d5, d9 \n"
+
+ REPEAT_BLOCK(
+ "vld1.16 {d2-d5}, [%[v1]]! \n"
+ "vld1.16 {d6-d9}, [%[v2]]! \n"
+ "vmlal.s16 q0, d2, d6 \n"
+ "vmlal.s16 q0, d3, d7 \n"
+ "vmlal.s16 q0, d4, d8 \n"
+ "vmlal.s16 q0, d5, d9 \n"
+ )
+#if ORDER > 64
+ "bne 1b \n"
+#endif
+ "vpadd.i32 d0, d0, d1 \n"
+ "vpaddl.s32 d0, d0 \n"
+ "vmov.32 %[res], d0[0] \n"
+ : /* outputs */
+#if ORDER > 64
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [v2] "+r"(v2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "d0", "d1", "d2", "d3", "d4",
+ "d5", "d6", "d7", "d8", "d9"
+ );
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math16_cf.h b/lib/rbcodec/codecs/demac/libdemac/vector_math16_cf.h
new file mode 100644
index 0000000000..4d77d3be31
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math16_cf.h
@@ -0,0 +1,364 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+Coldfire vector math copyright (C) 2007 Jens Arnold
+
+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 FUSED_VECTOR_MATH
+
+#define PREPARE_SCALARPRODUCT coldfire_set_macsr(0); /* signed integer mode */
+
+#define REPEAT_2(x) x x
+#define REPEAT_3(x) x x x
+#define REPEAT_7(x) x x x x x x x
+
+/* Calculate scalarproduct, then add a 2nd vector (fused for performance)
+ * This version fetches data as 32 bit words, and *recommends* v1 to be
+ * 32 bit aligned. It also assumes that f2 and s2 are either both 32 bit
+ * aligned or both unaligned. Performance will suffer if either condition
+ * isn't met. It also needs EMAC in signed integer mode. */
+static inline int32_t vector_sp_add(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 16
+ int cnt = ORDER>>4;
+#endif
+
+#define ADDHALFREGS(s1, s2, sum) /* Add register halves straight. */ \
+ "move.l " #s1 ", " #sum "\n" /* 's1' and 's2' can be A or D */ \
+ "add.l " #s2 ", " #s1 "\n" /* regs, 'sum' must be a D reg. */ \
+ "clr.w " #sum " \n" /* 's1' is clobbered! */ \
+ "add.l " #s2 ", " #sum "\n" \
+ "move.w " #s1 ", " #sum "\n"
+
+#define ADDHALFXREGS(s1, s2, sum) /* Add register halves across. */ \
+ "clr.w " #sum " \n" /* Needs 'sum' pre-swapped, swaps */ \
+ "add.l " #s1 ", " #sum "\n" /* 's2', and clobbers 's1'. */ \
+ "swap " #s2 " \n" /* 's1' can be an A or D reg. */ \
+ "add.l " #s2 ", " #s1 "\n" /* 'sum' and 's2' must be D regs. */ \
+ "move.w " #s1 ", " #sum "\n"
+
+ asm volatile (
+ "move.l %[f2], %%d0 \n"
+ "and.l #2, %%d0 \n"
+ "jeq 20f \n"
+
+ "10: \n"
+ "move.w (%[f2])+, %%d0 \n"
+ "move.w (%[s2])+, %%d1 \n"
+ "swap %%d1 \n"
+ "1: \n"
+ REPEAT_2(
+ "movem.l (%[v1]), %%d6-%%d7/%%a0-%%a1 \n"
+ "mac.w %%d0l, %%d6u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%d6l, (%[s2])+, %%d2, %%acc0\n"
+ ADDHALFXREGS(%%d6, %%d2, %%d1)
+ "mac.w %%d0l, %%d7u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%d7l, (%[s2])+, %%d6, %%acc0\n"
+ "move.l %%d1, (%[v1])+ \n"
+ ADDHALFXREGS(%%d7, %%d6, %%d2)
+ "mac.w %%d0l, %%a0u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%a0l, (%[s2])+, %%d7, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFXREGS(%%a0, %%d7, %%d6)
+ "mac.w %%d0l, %%a1u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%a1l, (%[s2])+, %%d1, %%acc0\n"
+ "move.l %%d6, (%[v1])+ \n"
+ ADDHALFXREGS(%%a1, %%d1, %%d7)
+ "move.l %%d7, (%[v1])+ \n"
+ )
+
+#if ORDER > 16
+ "subq.l #1, %[res] \n"
+ "bne.w 1b \n"
+#endif
+ "jra 99f \n"
+
+ "20: \n"
+ "move.l (%[f2])+, %%d0 \n"
+ "1: \n"
+ "movem.l (%[v1]), %%d6-%%d7/%%a0-%%a1 \n"
+ "mac.w %%d0u, %%d6u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d6l, (%[f2])+, %%d0, %%acc0\n"
+ ADDHALFREGS(%%d6, %%d1, %%d2)
+ "mac.w %%d0u, %%d7u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d7l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFREGS(%%d7, %%d1, %%d2)
+ "mac.w %%d0u, %%a0u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%a0l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFREGS(%%a0, %%d1, %%d2)
+ "mac.w %%d0u, %%a1u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%a1l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFREGS(%%a1, %%d1, %%d2)
+ "move.l %%d2, (%[v1])+ \n"
+
+ "movem.l (%[v1]), %%d6-%%d7/%%a0-%%a1 \n"
+ "mac.w %%d0u, %%d6u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d6l, (%[f2])+, %%d0, %%acc0\n"
+ ADDHALFREGS(%%d6, %%d1, %%d2)
+ "mac.w %%d0u, %%d7u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d7l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFREGS(%%d7, %%d1, %%d2)
+ "mac.w %%d0u, %%a0u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%a0l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFREGS(%%a0, %%d1, %%d2)
+ "mac.w %%d0u, %%a1u, (%[s2])+, %%d1, %%acc0\n"
+#if ORDER > 16
+ "mac.w %%d0l, %%a1l, (%[f2])+, %%d0, %%acc0\n"
+#else
+ "mac.w %%d0l, %%a1l, %%acc0 \n"
+#endif
+ "move.l %%d2, (%[v1])+ \n"
+ ADDHALFREGS(%%a1, %%d1, %%d2)
+ "move.l %%d2, (%[v1])+ \n"
+#if ORDER > 16
+ "subq.l #1, %[res] \n"
+ "bne.w 1b \n"
+#endif
+
+ "99: \n"
+ "movclr.l %%acc0, %[res] \n"
+ : /* outputs */
+ [v1]"+a"(v1),
+ [f2]"+a"(f2),
+ [s2]"+a"(s2),
+ [res]"=d"(res)
+ : /* inputs */
+#if ORDER > 16
+ [cnt]"[res]"(cnt)
+#endif
+ : /* clobbers */
+ "d0", "d1", "d2", "d6", "d7",
+ "a0", "a1", "memory"
+
+ );
+ return res;
+}
+
+/* Calculate scalarproduct, then subtract a 2nd vector (fused for performance)
+ * This version fetches data as 32 bit words, and *recommends* v1 to be
+ * 32 bit aligned. It also assumes that f2 and s2 are either both 32 bit
+ * aligned or both unaligned. Performance will suffer if either condition
+ * isn't met. It also needs EMAC in signed integer mode. */
+static inline int32_t vector_sp_sub(int16_t* v1, int16_t* f2, int16_t* s2)
+{
+ int res;
+#if ORDER > 16
+ int cnt = ORDER>>4;
+#endif
+
+#define SUBHALFREGS(min, sub, dif) /* Subtract register halves straight. */ \
+ "move.l " #min ", " #dif "\n" /* 'min' can be an A or D reg */ \
+ "sub.l " #sub ", " #min "\n" /* 'sub' and 'dif' must be D regs */ \
+ "clr.w " #sub "\n" /* 'min' and 'sub' are clobbered! */ \
+ "sub.l " #sub ", " #dif "\n" \
+ "move.w " #min ", " #dif "\n"
+
+#define SUBHALFXREGS(min, s2, s1d) /* Subtract register halves across. */ \
+ "clr.w " #s1d "\n" /* Needs 's1d' pre-swapped, swaps */ \
+ "sub.l " #s1d ", " #min "\n" /* 's2' and clobbers 'min'. */ \
+ "move.l " #min ", " #s1d "\n" /* 'min' can be an A or D reg, */ \
+ "swap " #s2 "\n" /* 's2' and 's1d' must be D regs. */ \
+ "sub.l " #s2 ", " #min "\n" \
+ "move.w " #min ", " #s1d "\n"
+
+ asm volatile (
+ "move.l %[f2], %%d0 \n"
+ "and.l #2, %%d0 \n"
+ "jeq 20f \n"
+
+ "10: \n"
+ "move.w (%[f2])+, %%d0 \n"
+ "move.w (%[s2])+, %%d1 \n"
+ "swap %%d1 \n"
+ "1: \n"
+ REPEAT_2(
+ "movem.l (%[v1]), %%d6-%%d7/%%a0-%%a1 \n"
+ "mac.w %%d0l, %%d6u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%d6l, (%[s2])+, %%d2, %%acc0\n"
+ SUBHALFXREGS(%%d6, %%d2, %%d1)
+ "mac.w %%d0l, %%d7u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%d7l, (%[s2])+, %%d6, %%acc0\n"
+ "move.l %%d1, (%[v1])+ \n"
+ SUBHALFXREGS(%%d7, %%d6, %%d2)
+ "mac.w %%d0l, %%a0u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%a0l, (%[s2])+, %%d7, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFXREGS(%%a0, %%d7, %%d6)
+ "mac.w %%d0l, %%a1u, (%[f2])+, %%d0, %%acc0\n"
+ "mac.w %%d0u, %%a1l, (%[s2])+, %%d1, %%acc0\n"
+ "move.l %%d6, (%[v1])+ \n"
+ SUBHALFXREGS(%%a1, %%d1, %%d7)
+ "move.l %%d7, (%[v1])+ \n"
+ )
+
+#if ORDER > 16
+ "subq.l #1, %[res] \n"
+ "bne.w 1b \n"
+#endif
+
+ "jra 99f \n"
+
+ "20: \n"
+ "move.l (%[f2])+, %%d0 \n"
+ "1: \n"
+ "movem.l (%[v1]), %%d6-%%d7/%%a0-%%a1 \n"
+ "mac.w %%d0u, %%d6u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d6l, (%[f2])+, %%d0, %%acc0\n"
+ SUBHALFREGS(%%d6, %%d1, %%d2)
+ "mac.w %%d0u, %%d7u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d7l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFREGS(%%d7, %%d1, %%d2)
+ "mac.w %%d0u, %%a0u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%a0l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFREGS(%%a0, %%d1, %%d2)
+ "mac.w %%d0u, %%a1u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%a1l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFREGS(%%a1, %%d1, %%d2)
+ "move.l %%d2, (%[v1])+ \n"
+
+ "movem.l (%[v1]), %%d6-%%d7/%%a0-%%a1 \n"
+ "mac.w %%d0u, %%d6u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d6l, (%[f2])+, %%d0, %%acc0\n"
+ SUBHALFREGS(%%d6, %%d1, %%d2)
+ "mac.w %%d0u, %%d7u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d7l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFREGS(%%d7, %%d1, %%d2)
+ "mac.w %%d0u, %%a0u, (%[s2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%a0l, (%[f2])+, %%d0, %%acc0\n"
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFREGS(%%a0, %%d1, %%d2)
+ "mac.w %%d0u, %%a1u, (%[s2])+, %%d1, %%acc0\n"
+#if ORDER > 16
+ "mac.w %%d0l, %%a1l, (%[f2])+, %%d0, %%acc0\n"
+#else
+ "mac.w %%d0l, %%a1l, %%acc0 \n"
+#endif
+ "move.l %%d2, (%[v1])+ \n"
+ SUBHALFREGS(%%a1, %%d1, %%d2)
+ "move.l %%d2, (%[v1])+ \n"
+#if ORDER > 16
+ "subq.l #1, %[res] \n"
+ "bne.w 1b \n"
+#endif
+
+ "99: \n"
+ "movclr.l %%acc0, %[res] \n"
+ : /* outputs */
+ [v1]"+a"(v1),
+ [f2]"+a"(f2),
+ [s2]"+a"(s2),
+ [res]"=d"(res)
+ : /* inputs */
+#if ORDER > 16
+ [cnt]"[res]"(cnt)
+#endif
+ : /* clobbers */
+ "d0", "d1", "d2", "d6", "d7",
+ "a0", "a1", "memory"
+
+ );
+ return res;
+}
+
+/* This version fetches data as 32 bit words, and *recommends* v1 to be
+ * 32 bit aligned, otherwise performance will suffer. It also needs EMAC
+ * in signed integer mode. */
+static inline int32_t scalarproduct(int16_t* v1, int16_t* v2)
+{
+ int res;
+#if ORDER > 16
+ int cnt = ORDER>>4;
+#endif
+
+ asm volatile (
+ "move.l %[v2], %%d0 \n"
+ "and.l #2, %%d0 \n"
+ "jeq 20f \n"
+
+ "10: \n"
+ "move.l (%[v1])+, %%d0 \n"
+ "move.w (%[v2])+, %%d1 \n"
+ "1: \n"
+ REPEAT_7(
+ "mac.w %%d0u, %%d1l, (%[v2])+, %%d1, %%acc0\n"
+ "mac.w %%d0l, %%d1u, (%[v1])+, %%d0, %%acc0\n"
+ )
+
+ "mac.w %%d0u, %%d1l, (%[v2])+, %%d1, %%acc0\n"
+#if ORDER > 16
+ "mac.w %%d0l, %%d1u, (%[v1])+, %%d0, %%acc0\n"
+ "subq.l #1, %[res] \n"
+ "bne.b 1b \n"
+#else
+ "mac.w %%d0l, %%d1u, %%acc0 \n"
+#endif
+ "jra 99f \n"
+
+ "20: \n"
+ "move.l (%[v1])+, %%d0 \n"
+ "move.l (%[v2])+, %%d1 \n"
+ "1: \n"
+ REPEAT_3(
+ "mac.w %%d0u, %%d1u, (%[v1])+, %%d2, %%acc0\n"
+ "mac.w %%d0l, %%d1l, (%[v2])+, %%d1, %%acc0\n"
+ "mac.w %%d2u, %%d1u, (%[v1])+, %%d0, %%acc0\n"
+ "mac.w %%d2l, %%d1l, (%[v2])+, %%d1, %%acc0\n"
+ )
+
+ "mac.w %%d0u, %%d1u, (%[v1])+, %%d2, %%acc0\n"
+ "mac.w %%d0l, %%d1l, (%[v2])+, %%d1, %%acc0\n"
+#if ORDER > 16
+ "mac.w %%d2u, %%d1u, (%[v1])+, %%d0, %%acc0\n"
+ "mac.w %%d2l, %%d1l, (%[v2])+, %%d1, %%acc0\n"
+ "subq.l #1, %[res] \n"
+ "bne.b 1b \n"
+#else
+ "mac.w %%d2u, %%d1u, %%acc0 \n"
+ "mac.w %%d2l, %%d1l, %%acc0 \n"
+#endif
+
+ "99: \n"
+ "movclr.l %%acc0, %[res] \n"
+ : /* outputs */
+ [v1]"+a"(v1),
+ [v2]"+a"(v2),
+ [res]"=d"(res)
+ : /* inputs */
+#if ORDER > 16
+ [cnt]"[res]"(cnt)
+#endif
+ : /* clobbers */
+ "d0", "d1", "d2"
+ );
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math16_mmx.h b/lib/rbcodec/codecs/demac/libdemac/vector_math16_mmx.h
new file mode 100644
index 0000000000..2177fe88ea
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math16_mmx.h
@@ -0,0 +1,234 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+MMX vector math copyright (C) 2010 Jens Arnold
+
+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 FUSED_VECTOR_MATH
+
+#define REPEAT_MB3(x, n) x(n) x(n+8) x(n+16)
+#define REPEAT_MB7(x, n) x(n) x(n+8) x(n+16) x(n+24) x(n+32) x(n+40) x(n+48)
+#define REPEAT_MB8(x, n) REPEAT_MB7(x, n) x(n+56)
+
+#if ORDER == 16 /* 3 times */
+#define REPEAT_MB(x) REPEAT_MB3(x, 8)
+#elif ORDER == 32 /* 7 times */
+#define REPEAT_MB(x) REPEAT_MB7(x, 8)
+#elif ORDER == 64 /* 5*3 == 15 times */
+#define REPEAT_MB(x) REPEAT_MB3(x, 8) REPEAT_MB3(x, 32) REPEAT_MB3(x, 56) \
+ REPEAT_MB3(x, 80) REPEAT_MB3(x, 104)
+#elif ORDER == 256 /* 9*7 == 63 times */
+#define REPEAT_MB(x) REPEAT_MB7(x, 8) REPEAT_MB7(x, 64) REPEAT_MB7(x, 120) \
+ REPEAT_MB7(x, 176) REPEAT_MB7(x, 232) REPEAT_MB7(x, 288) \
+ REPEAT_MB7(x, 344) REPEAT_MB7(x, 400) REPEAT_MB7(x, 456)
+#elif ORDER == 1280 /* 8*8 == 64 times */
+#define REPEAT_MB(x) REPEAT_MB8(x, 0) REPEAT_MB8(x, 64) REPEAT_MB8(x, 128) \
+ REPEAT_MB8(x, 192) REPEAT_MB8(x, 256) REPEAT_MB8(x, 320) \
+ REPEAT_MB8(x, 384) REPEAT_MB8(x, 448)
+#else
+#error unsupported order
+#endif
+
+
+static inline int32_t vector_sp_add(int16_t* v1, int16_t* f2, int16_t *s2)
+{
+ int res, t;
+#if ORDER > 256
+ int cnt = ORDER>>8;
+#endif
+
+ asm volatile (
+#if ORDER > 256
+ "pxor %%mm2, %%mm2 \n"
+ "1: \n"
+#else
+ "movq (%[v1]), %%mm2 \n"
+ "movq %%mm2, %%mm0 \n"
+ "pmaddwd (%[f2]), %%mm2 \n"
+ "paddw (%[s2]), %%mm0 \n"
+ "movq %%mm0, (%[v1]) \n"
+#endif
+
+#define SP_ADD_BLOCK(n) \
+ "movq " #n "(%[v1]), %%mm1 \n" \
+ "movq %%mm1, %%mm0 \n" \
+ "pmaddwd " #n "(%[f2]), %%mm1 \n" \
+ "paddw " #n "(%[s2]), %%mm0 \n" \
+ "movq %%mm0, " #n "(%[v1]) \n" \
+ "paddd %%mm1, %%mm2 \n"
+
+REPEAT_MB(SP_ADD_BLOCK)
+
+#if ORDER > 256
+ "add $512, %[v1] \n"
+ "add $512, %[s2] \n"
+ "add $512, %[f2] \n"
+ "dec %[cnt] \n"
+ "jne 1b \n"
+#endif
+
+ "movd %%mm2, %[t] \n"
+ "psrlq $32, %%mm2 \n"
+ "movd %%mm2, %[res] \n"
+ "add %[t], %[res] \n"
+ : /* outputs */
+#if ORDER > 256
+ [cnt]"+r"(cnt),
+ [s2] "+r"(s2),
+ [res]"=r"(res),
+ [t] "=r"(t)
+ : /* inputs */
+ [v1]"2"(v1),
+ [f2]"3"(f2)
+#else
+ [res]"=r"(res),
+ [t] "=r"(t)
+ : /* inputs */
+ [v1]"r"(v1),
+ [f2]"r"(f2),
+ [s2]"r"(s2)
+#endif
+ : /* clobbers */
+ "mm0", "mm1", "mm2"
+ );
+ return res;
+}
+
+static inline int32_t vector_sp_sub(int16_t* v1, int16_t* f2, int16_t *s2)
+{
+ int res, t;
+#if ORDER > 256
+ int cnt = ORDER>>8;
+#endif
+
+ asm volatile (
+#if ORDER > 256
+ "pxor %%mm2, %%mm2 \n"
+ "1: \n"
+#else
+ "movq (%[v1]), %%mm2 \n"
+ "movq %%mm2, %%mm0 \n"
+ "pmaddwd (%[f2]), %%mm2 \n"
+ "psubw (%[s2]), %%mm0 \n"
+ "movq %%mm0, (%[v1]) \n"
+#endif
+
+#define SP_SUB_BLOCK(n) \
+ "movq " #n "(%[v1]), %%mm1 \n" \
+ "movq %%mm1, %%mm0 \n" \
+ "pmaddwd " #n "(%[f2]), %%mm1 \n" \
+ "psubw " #n "(%[s2]), %%mm0 \n" \
+ "movq %%mm0, " #n "(%[v1]) \n" \
+ "paddd %%mm1, %%mm2 \n"
+
+REPEAT_MB(SP_SUB_BLOCK)
+
+#if ORDER > 256
+ "add $512, %[v1] \n"
+ "add $512, %[s2] \n"
+ "add $512, %[f2] \n"
+ "dec %[cnt] \n"
+ "jne 1b \n"
+#endif
+
+ "movd %%mm2, %[t] \n"
+ "psrlq $32, %%mm2 \n"
+ "movd %%mm2, %[res] \n"
+ "add %[t], %[res] \n"
+ : /* outputs */
+#if ORDER > 256
+ [cnt]"+r"(cnt),
+ [s2] "+r"(s2),
+ [res]"=r"(res),
+ [t] "=r"(t)
+ : /* inputs */
+ [v1]"2"(v1),
+ [f2]"3"(f2)
+#else
+ [res]"=r"(res),
+ [t] "=r"(t)
+ : /* inputs */
+ [v1]"r"(v1),
+ [f2]"r"(f2),
+ [s2]"r"(s2)
+#endif
+ : /* clobbers */
+ "mm0", "mm1", "mm2"
+ );
+ return res;
+}
+
+static inline int32_t scalarproduct(int16_t* v1, int16_t* v2)
+{
+ int res, t;
+#if ORDER > 256
+ int cnt = ORDER>>8;
+#endif
+
+ asm volatile (
+#if ORDER > 256
+ "pxor %%mm1, %%mm1 \n"
+ "1: \n"
+#else
+ "movq (%[v1]), %%mm1 \n"
+ "pmaddwd (%[v2]), %%mm1 \n"
+#endif
+
+#define SP_BLOCK(n) \
+ "movq " #n "(%[v1]), %%mm0 \n" \
+ "pmaddwd " #n "(%[v2]), %%mm0 \n" \
+ "paddd %%mm0, %%mm1 \n"
+
+REPEAT_MB(SP_BLOCK)
+
+#if ORDER > 256
+ "add $512, %[v1] \n"
+ "add $512, %[v2] \n"
+ "dec %[cnt] \n"
+ "jne 1b \n"
+#endif
+
+ "movd %%mm1, %[t] \n"
+ "psrlq $32, %%mm1 \n"
+ "movd %%mm1, %[res] \n"
+ "add %[t], %[res] \n"
+ : /* outputs */
+#if ORDER > 256
+ [cnt]"+r"(cnt),
+ [res]"=r"(res),
+ [t] "=r"(t)
+ : /* inputs */
+ [v1]"1"(v1),
+ [v2]"2"(v2)
+#else
+ [res]"=r"(res),
+ [t] "=r"(t)
+ : /* inputs */
+ [v1]"r"(v1),
+ [v2]"r"(v2)
+#endif
+ : /* clobbers */
+ "mm0", "mm1"
+ );
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math32_armv4.h b/lib/rbcodec/codecs/demac/libdemac/vector_math32_armv4.h
new file mode 100644
index 0000000000..d6bb9b0d9c
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math32_armv4.h
@@ -0,0 +1,201 @@
+/*
+
+libdemac - A Monkey's Audio decoder
+
+$Id$
+
+Copyright (C) Dave Chapman 2007
+
+ARMv4 vector math copyright (C) 2008 Jens Arnold
+
+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 FUSED_VECTOR_MATH
+
+#if ORDER > 32
+#define REPEAT_BLOCK(x) x x x x x x x x
+#elif ORDER > 16
+#define REPEAT_BLOCK(x) x x x x x x x
+#else
+#define REPEAT_BLOCK(x) x x x
+#endif
+
+/* Calculate scalarproduct, then add a 2nd vector (fused for performance) */
+static inline int32_t vector_sp_add(int32_t* v1, int32_t* f2, int32_t* s2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+ "1: \n"
+#else
+ "ldmia %[v1], {r0-r3} \n"
+ "ldmia %[f2]!, {r4-r7} \n"
+ "mul %[res], r4, r0 \n"
+ "mla %[res], r5, r1, %[res] \n"
+ "mla %[res], r6, r2, %[res] \n"
+ "mla %[res], r7, r3, %[res] \n"
+ "ldmia %[s2]!, {r4-r7} \n"
+ "add r0, r0, r4 \n"
+ "add r1, r1, r5 \n"
+ "add r2, r2, r6 \n"
+ "add r3, r3, r7 \n"
+ "stmia %[v1]!, {r0-r3} \n"
+#endif
+ REPEAT_BLOCK(
+ "ldmia %[v1], {r0-r3} \n"
+ "ldmia %[f2]!, {r4-r7} \n"
+ "mla %[res], r4, r0, %[res] \n"
+ "mla %[res], r5, r1, %[res] \n"
+ "mla %[res], r6, r2, %[res] \n"
+ "mla %[res], r7, r3, %[res] \n"
+ "ldmia %[s2]!, {r4-r7} \n"
+ "add r0, r0, r4 \n"
+ "add r1, r1, r5 \n"
+ "add r2, r2, r6 \n"
+ "add r3, r3, r7 \n"
+ "stmia %[v1]!, {r0-r3} \n"
+ )
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "r4",
+ "r5", "r6", "r7", "cc", "memory"
+ );
+ return res;
+}
+
+/* Calculate scalarproduct, then subtract a 2nd vector (fused for performance) */
+static inline int32_t vector_sp_sub(int32_t* v1, int32_t* f2, int32_t* s2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+ "1: \n"
+#else
+ "ldmia %[v1], {r0-r3} \n"
+ "ldmia %[f2]!, {r4-r7} \n"
+ "mul %[res], r4, r0 \n"
+ "mla %[res], r5, r1, %[res] \n"
+ "mla %[res], r6, r2, %[res] \n"
+ "mla %[res], r7, r3, %[res] \n"
+ "ldmia %[s2]!, {r4-r7} \n"
+ "sub r0, r0, r4 \n"
+ "sub r1, r1, r5 \n"
+ "sub r2, r2, r6 \n"
+ "sub r3, r3, r7 \n"
+ "stmia %[v1]!, {r0-r3} \n"
+#endif
+ REPEAT_BLOCK(
+ "ldmia %[v1], {r0-r3} \n"
+ "ldmia %[f2]!, {r4-r7} \n"
+ "mla %[res], r4, r0, %[res] \n"
+ "mla %[res], r5, r1, %[res] \n"
+ "mla %[res], r6, r2, %[res] \n"
+ "mla %[res], r7, r3, %[res] \n"
+ "ldmia %[s2]!, {r4-r7} \n"
+ "sub r0, r0, r4 \n"
+ "sub r1, r1, r5 \n"
+ "sub r2, r2, r6 \n"
+ "sub r3, r3, r7 \n"
+ "stmia %[v1]!, {r0-r3} \n"
+ )
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [f2] "+r"(f2),
+ [s2] "+r"(s2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3", "r4",
+ "r5", "r6", "r7", "cc", "memory"
+ );
+ return res;
+}
+
+static inline int32_t scalarproduct(int32_t* v1, int32_t* v2)
+{
+ int res;
+#if ORDER > 32
+ int cnt = ORDER>>5;
+#endif
+
+ asm volatile (
+#if ORDER > 32
+ "mov %[res], #0 \n"
+ "1: \n"
+#else
+ "ldmia %[v1]!, {r0-r3} \n"
+ "ldmia %[v2]!, {r4-r7} \n"
+ "mul %[res], r4, r0 \n"
+ "mla %[res], r5, r1, %[res] \n"
+ "mla %[res], r6, r2, %[res] \n"
+ "mla %[res], r7, r3, %[res] \n"
+#endif
+ REPEAT_BLOCK(
+ "ldmia %[v1]!, {r0-r3} \n"
+ "ldmia %[v2]!, {r4-r7} \n"
+ "mla %[res], r4, r0, %[res] \n"
+ "mla %[res], r5, r1, %[res] \n"
+ "mla %[res], r6, r2, %[res] \n"
+ "mla %[res], r7, r3, %[res] \n"
+ )
+#if ORDER > 32
+ "subs %[cnt], %[cnt], #1 \n"
+ "bne 1b \n"
+#endif
+ : /* outputs */
+#if ORDER > 32
+ [cnt]"+r"(cnt),
+#endif
+ [v1] "+r"(v1),
+ [v2] "+r"(v2),
+ [res]"=r"(res)
+ : /* inputs */
+ : /* clobbers */
+ "r0", "r1", "r2", "r3",
+ "r4", "r5", "r6", "r7", "cc", "memory"
+ );
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/libdemac/vector_math_generic.h b/lib/rbcodec/codecs/demac/libdemac/vector_math_generic.h
new file mode 100644
index 0000000000..00bf07a007
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/libdemac/vector_math_generic.h
@@ -0,0 +1,160 @@
+/*
+
+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 "demac_config.h"
+
+static inline void vector_add(filter_int* v1, filter_int* 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(filter_int* v1, filter_int* 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(filter_int* v1, filter_int* v2)
+{
+ int res = 0;
+
+#if ORDER > 32
+ int order = (ORDER >> 5);
+ 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++;
+#if ORDER > 16
+ 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++;
+#endif
+ }
+ return res;
+}
diff --git a/lib/rbcodec/codecs/demac/wavwrite.c b/lib/rbcodec/codecs/demac/wavwrite.c
new file mode 100644
index 0000000000..71d2b7bb97
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/wavwrite.c
@@ -0,0 +1,110 @@
+/*
+
+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 "inttypes.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include "parser.h"
+
+#ifndef __WIN32__
+#define O_BINARY 0
+#endif
+
+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=open(filename, O_CREAT|O_WRONLY|O_TRUNC|O_BINARY, 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;
+}
diff --git a/lib/rbcodec/codecs/demac/wavwrite.h b/lib/rbcodec/codecs/demac/wavwrite.h
new file mode 100644
index 0000000000..a124353229
--- /dev/null
+++ b/lib/rbcodec/codecs/demac/wavwrite.h
@@ -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
diff --git a/lib/rbcodec/codecs/flac.c b/lib/rbcodec/codecs/flac.c
new file mode 100644
index 0000000000..e10403819c
--- /dev/null
+++ b/lib/rbcodec/codecs/flac.c
@@ -0,0 +1,536 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2005 Dave Chapman
+ *
+ * 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 software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#include "codeclib.h"
+#include <codecs/libffmpegFLAC/decoder.h>
+
+CODEC_HEADER
+
+static FLACContext fc IBSS_ATTR_FLAC;
+
+/* The output buffers containing the decoded samples (channels 0 and 1) */
+static int32_t decoded0[MAX_BLOCKSIZE] IBSS_ATTR_FLAC;
+static int32_t decoded1[MAX_BLOCKSIZE] IBSS_ATTR_FLAC;
+static int32_t decoded2[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_LARGE_IRAM;
+static int32_t decoded3[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_LARGE_IRAM;
+static int32_t decoded4[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_XLARGE_IRAM;
+static int32_t decoded5[MAX_BLOCKSIZE] IBSS_ATTR_FLAC_XLARGE_IRAM;
+
+#define MAX_SUPPORTED_SEEKTABLE_SIZE 5000
+
+/* Notes about seeking:
+
+ The full seek table consists of:
+ uint64_t sample (only 36 bits are used)
+ uint64_t offset
+ uint32_t blocksize
+
+ We also limit the sample and offset values to 32-bits - Rockbox doesn't
+ support files bigger than 2GB on FAT32 filesystems.
+
+ The reference FLAC encoder produces a seek table with points every
+ 10 seconds, but this can be overridden by the user when encoding a file.
+
+ With the default settings, a typical 4 minute track will contain
+ 24 seek points.
+
+ Taking the extreme case of a Rockbox supported file to be a 2GB (compressed)
+ 16-bit/44.1KHz mono stream with a likely uncompressed size of 4GB:
+ Total duration is: 48694 seconds (about 810 minutes - 13.5 hours)
+ Total number of seek points: 4869
+
+ Therefore we limit the number of seek points to 5000. This is a
+ very extreme case, and requires 5000*8=40000 bytes of storage.
+
+ If we come across a FLAC file with more than this number of seekpoints, we
+ just use the first 5000.
+
+*/
+
+struct FLACseekpoints {
+ uint32_t sample;
+ uint32_t offset;
+ uint16_t blocksize;
+};
+
+static struct FLACseekpoints seekpoints[MAX_SUPPORTED_SEEKTABLE_SIZE];
+static int nseekpoints;
+
+static int8_t *bit_buffer;
+static size_t buff_size;
+
+static bool flac_init(FLACContext* fc, int first_frame_offset)
+{
+ unsigned char buf[255];
+ bool found_streaminfo=false;
+ uint32_t seekpoint_hi,seekpoint_lo;
+ uint32_t offset_hi,offset_lo;
+ uint16_t blocksize;
+ int endofmetadata=0;
+ uint32_t blocklength;
+
+ ci->memset(fc,0,sizeof(FLACContext));
+ nseekpoints=0;
+
+ fc->sample_skip = 0;
+
+ /* Reset sample buffers */
+ memset(decoded0, 0, sizeof(decoded0));
+ memset(decoded1, 0, sizeof(decoded1));
+ memset(decoded2, 0, sizeof(decoded2));
+ memset(decoded3, 0, sizeof(decoded3));
+ memset(decoded4, 0, sizeof(decoded4));
+ memset(decoded5, 0, sizeof(decoded5));
+
+ /* Set sample buffers in decoder structure */
+ fc->decoded[0] = decoded0;
+ fc->decoded[1] = decoded1;
+ fc->decoded[2] = decoded2;
+ fc->decoded[3] = decoded3;
+ fc->decoded[4] = decoded4;
+ fc->decoded[5] = decoded5;
+
+
+ /* Skip any foreign tags at start of file */
+ ci->seek_buffer(first_frame_offset);
+
+ fc->metadatalength = first_frame_offset;
+
+ if (ci->read_filebuf(buf, 4) < 4)
+ {
+ return false;
+ }
+
+ if (ci->memcmp(buf,"fLaC",4) != 0)
+ {
+ return false;
+ }
+ fc->metadatalength += 4;
+
+ while (!endofmetadata) {
+ if (ci->read_filebuf(buf, 4) < 4)
+ {
+ return false;
+ }
+
+ endofmetadata=(buf[0]&0x80);
+ blocklength = (buf[1] << 16) | (buf[2] << 8) | buf[3];
+ fc->metadatalength+=blocklength+4;
+
+ if ((buf[0] & 0x7f) == 0) /* 0 is the STREAMINFO block */
+ {
+ if (ci->read_filebuf(buf, blocklength) < blocklength) return false;
+
+ fc->filesize = ci->filesize;
+ fc->min_blocksize = (buf[0] << 8) | buf[1];
+ int max_blocksize = (buf[2] << 8) | buf[3];
+ if (max_blocksize > MAX_BLOCKSIZE)
+ {
+ LOGF("FLAC: Maximum blocksize is too large (%d > %d)\n",
+ max_blocksize, MAX_BLOCKSIZE);
+ return false;
+ }
+ fc->max_blocksize = max_blocksize;
+ fc->min_framesize = (buf[4] << 16) | (buf[5] << 8) | buf[6];
+ fc->max_framesize = (buf[7] << 16) | (buf[8] << 8) | buf[9];
+ fc->samplerate = (buf[10] << 12) | (buf[11] << 4)
+ | ((buf[12] & 0xf0) >> 4);
+ fc->channels = ((buf[12]&0x0e)>>1) + 1;
+ fc->bps = (((buf[12]&0x01) << 4) | ((buf[13]&0xf0)>>4) ) + 1;
+
+ /* totalsamples is a 36-bit field, but we assume <= 32 bits are
+ used */
+ fc->totalsamples = (buf[14] << 24) | (buf[15] << 16)
+ | (buf[16] << 8) | buf[17];
+
+ /* Calculate track length (in ms) and estimate the bitrate
+ (in kbit/s) */
+ fc->length = ((int64_t) fc->totalsamples * 1000) / fc->samplerate;
+
+ found_streaminfo=true;
+ } else if ((buf[0] & 0x7f) == 3) { /* 3 is the SEEKTABLE block */
+ while ((nseekpoints < MAX_SUPPORTED_SEEKTABLE_SIZE) &&
+ (blocklength >= 18)) {
+ if (ci->read_filebuf(buf,18) < 18) return false;
+ blocklength-=18;
+
+ seekpoint_hi=(buf[0] << 24) | (buf[1] << 16) |
+ (buf[2] << 8) | buf[3];
+ seekpoint_lo=(buf[4] << 24) | (buf[5] << 16) |
+ (buf[6] << 8) | buf[7];
+ offset_hi=(buf[8] << 24) | (buf[9] << 16) |
+ (buf[10] << 8) | buf[11];
+ offset_lo=(buf[12] << 24) | (buf[13] << 16) |
+ (buf[14] << 8) | buf[15];
+
+ blocksize=(buf[16] << 8) | buf[17];
+
+ /* Only store seekpoints where the high 32 bits are zero */
+ if ((seekpoint_hi == 0) && (seekpoint_lo != 0xffffffff) &&
+ (offset_hi == 0)) {
+ seekpoints[nseekpoints].sample=seekpoint_lo;
+ seekpoints[nseekpoints].offset=offset_lo;
+ seekpoints[nseekpoints].blocksize=blocksize;
+ nseekpoints++;
+ }
+ }
+ /* Skip any unread seekpoints */
+ if (blocklength > 0)
+ ci->advance_buffer(blocklength);
+ } else {
+ /* Skip to next metadata block */
+ ci->advance_buffer(blocklength);
+ }
+ }
+
+ if (found_streaminfo) {
+ fc->bitrate = ((int64_t) (fc->filesize-fc->metadatalength) * 8)
+ / fc->length;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/* Synchronize to next frame in stream - adapted from libFLAC 1.1.3b2 */
+static bool frame_sync(FLACContext* fc) {
+ unsigned int x = 0;
+ bool cached = false;
+
+ /* Make sure we're byte aligned. */
+ align_get_bits(&fc->gb);
+
+ while(1) {
+ if(fc->gb.size_in_bits - get_bits_count(&fc->gb) < 8) {
+ /* Error, end of bitstream, a valid stream should never reach here
+ * since the buffer should contain at least one frame header.
+ */
+ return false;
+ }
+
+ if(cached)
+ cached = false;
+ else
+ x = get_bits(&fc->gb, 8);
+
+ if(x == 0xff) { /* MAGIC NUMBER for first 8 frame sync bits. */
+ x = get_bits(&fc->gb, 8);
+ /* We have to check if we just read two 0xff's in a row; the second
+ * may actually be the beginning of the sync code.
+ */
+ if(x == 0xff) { /* MAGIC NUMBER for first 8 frame sync bits. */
+ cached = true;
+ }
+ else if(x >> 2 == 0x3e) { /* MAGIC NUMBER for last 6 sync bits. */
+ /* Succesfully synced. */
+ break;
+ }
+ }
+ }
+
+ /* Advance and init bit buffer to the new frame. */
+ ci->advance_buffer((get_bits_count(&fc->gb)-16)>>3); /* consumed bytes */
+ bit_buffer = ci->request_buffer(&buff_size, MAX_FRAMESIZE+16);
+ init_get_bits(&fc->gb, bit_buffer, buff_size*8);
+
+ /* Decode the frame to verify the frame crc and
+ * fill fc with its metadata.
+ */
+ if(flac_decode_frame(fc,
+ bit_buffer, buff_size, ci->yield) < 0) {
+ return false;
+ }
+
+ return true;
+}
+
+/* Seek to sample - adapted from libFLAC 1.1.3b2+ */
+static bool flac_seek(FLACContext* fc, uint32_t target_sample) {
+ off_t orig_pos = ci->curpos;
+ off_t pos = -1;
+ unsigned long lower_bound, upper_bound;
+ unsigned long lower_bound_sample, upper_bound_sample;
+ int i;
+ unsigned approx_bytes_per_frame;
+ uint32_t this_frame_sample = fc->samplenumber;
+ unsigned this_block_size = fc->blocksize;
+ bool needs_seek = true, first_seek = true;
+
+ /* We are just guessing here. */
+ if(fc->max_framesize > 0)
+ approx_bytes_per_frame = (fc->max_framesize + fc->min_framesize)/2 + 1;
+ /* Check if it's a known fixed-blocksize stream. */
+ else if(fc->min_blocksize == fc->max_blocksize && fc->min_blocksize > 0)
+ approx_bytes_per_frame = fc->min_blocksize*fc->channels*fc->bps/8 + 64;
+ else
+ approx_bytes_per_frame = 4608 * fc->channels * fc->bps/8 + 64;
+
+ /* Set an upper and lower bound on where in the stream we will search. */
+ lower_bound = fc->metadatalength;
+ lower_bound_sample = 0;
+ upper_bound = fc->filesize;
+ upper_bound_sample = fc->totalsamples>0 ? fc->totalsamples : target_sample;
+
+ /* Refine the bounds if we have a seektable with suitable points. */
+ if(nseekpoints > 0) {
+ /* Find the closest seek point <= target_sample, if it exists. */
+ for(i = nseekpoints-1; i >= 0; i--) {
+ if(seekpoints[i].sample <= target_sample)
+ break;
+ }
+ if(i >= 0) { /* i.e. we found a suitable seek point... */
+ lower_bound = fc->metadatalength + seekpoints[i].offset;
+ lower_bound_sample = seekpoints[i].sample;
+ }
+
+ /* Find the closest seek point > target_sample, if it exists. */
+ for(i = 0; i < nseekpoints; i++) {
+ if(seekpoints[i].sample > target_sample)
+ break;
+ }
+ if(i < nseekpoints) { /* i.e. we found a suitable seek point... */
+ upper_bound = fc->metadatalength + seekpoints[i].offset;
+ upper_bound_sample = seekpoints[i].sample;
+ }
+ }
+
+ while(1) {
+ /* Check if bounds are still ok. */
+ if(lower_bound_sample >= upper_bound_sample ||
+ lower_bound > upper_bound) {
+ return false;
+ }
+
+ /* Calculate new seek position */
+ if(needs_seek) {
+ pos = (off_t)(lower_bound +
+ (((target_sample - lower_bound_sample) *
+ (int64_t)(upper_bound - lower_bound)) /
+ (upper_bound_sample - lower_bound_sample)) -
+ approx_bytes_per_frame);
+
+ if(pos >= (off_t)upper_bound)
+ pos = (off_t)upper_bound-1;
+ if(pos < (off_t)lower_bound)
+ pos = (off_t)lower_bound;
+ }
+
+ if(!ci->seek_buffer(pos))
+ return false;
+
+ bit_buffer = ci->request_buffer(&buff_size, MAX_FRAMESIZE+16);
+ init_get_bits(&fc->gb, bit_buffer, buff_size*8);
+
+ /* Now we need to get a frame. It is possible for our seek
+ * to land in the middle of audio data that looks exactly like
+ * a frame header from a future version of an encoder. When
+ * that happens, frame_sync() will return false.
+ * But there is a remote possibility that it is properly
+ * synced at such a "future-codec frame", so to make sure,
+ * we wait to see several "unparseable" errors in a row before
+ * bailing out.
+ */
+ {
+ unsigned unparseable_count;
+ bool got_a_frame = false;
+ for(unparseable_count = 0; !got_a_frame
+ && unparseable_count < 10; unparseable_count++) {
+ if(frame_sync(fc))
+ got_a_frame = true;
+ }
+ if(!got_a_frame) {
+ ci->seek_buffer(orig_pos);
+ return false;
+ }
+ }
+
+ this_frame_sample = fc->samplenumber;
+ this_block_size = fc->blocksize;
+
+ if(target_sample >= this_frame_sample
+ && target_sample < this_frame_sample+this_block_size) {
+ /* Found the frame containing the target sample. */
+ fc->sample_skip = target_sample - this_frame_sample;
+ break;
+ }
+
+ if(this_frame_sample + this_block_size >= upper_bound_sample &&
+ !first_seek) {
+ if(pos == (off_t)lower_bound || !needs_seek) {
+ ci->seek_buffer(orig_pos);
+ return false;
+ }
+ /* Our last move backwards wasn't big enough, try again. */
+ approx_bytes_per_frame *= 2;
+ continue;
+ }
+ /* Allow one seek over upper bound,
+ * required for streams with unknown total samples.
+ */
+ first_seek = false;
+
+ /* Make sure we are not seeking in a corrupted stream */
+ if(this_frame_sample < lower_bound_sample) {
+ ci->seek_buffer(orig_pos);
+ return false;
+ }
+
+ approx_bytes_per_frame = this_block_size*fc->channels*fc->bps/8 + 64;
+
+ /* We need to narrow the search. */
+ if(target_sample < this_frame_sample) {
+ upper_bound_sample = this_frame_sample;
+ upper_bound = ci->curpos;
+ }
+ else { /* Target is beyond this frame. */
+ /* We are close, continue in decoding next frames. */
+ if(target_sample < this_frame_sample + 4*this_block_size) {
+ pos = ci->curpos + fc->framesize;
+ needs_seek = false;
+ }
+
+ lower_bound_sample = this_frame_sample + this_block_size;
+ lower_bound = ci->curpos + fc->framesize;
+ }
+ }
+
+ return true;
+}
+
+/* Seek to file offset */
+static bool flac_seek_offset(FLACContext* fc, uint32_t offset) {
+ unsigned unparseable_count;
+ bool got_a_frame = false;
+
+ if(!ci->seek_buffer(offset))
+ return false;
+
+ bit_buffer = ci->request_buffer(&buff_size, MAX_FRAMESIZE);
+ init_get_bits(&fc->gb, bit_buffer, buff_size*8);
+
+ for(unparseable_count = 0; !got_a_frame
+ && unparseable_count < 10; unparseable_count++) {
+ if(frame_sync(fc))
+ got_a_frame = true;
+ }
+
+ if(!got_a_frame) {
+ ci->seek_buffer(fc->metadatalength);
+ return false;
+ }
+
+ return true;
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* Generic codec initialisation */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, FLAC_OUTPUT_DEPTH-1);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ int8_t *buf;
+ uint32_t samplesdone;
+ uint32_t elapsedtime;
+ size_t bytesleft;
+ int consumed;
+ int res;
+ int frame;
+ intptr_t param;
+
+ if (codec_init()) {
+ LOGF("FLAC: Error initialising codec\n");
+ return CODEC_ERROR;
+ }
+
+ /* Need to save offset for later use (cleared indirectly by flac_init) */
+ samplesdone = ci->id3->offset;
+
+ if (!flac_init(&fc,ci->id3->first_frame_offset)) {
+ LOGF("FLAC: Error initialising codec\n");
+ return CODEC_ERROR;
+ }
+
+ ci->configure(DSP_SWITCH_FREQUENCY, ci->id3->frequency);
+ ci->configure(DSP_SET_STEREO_MODE, fc.channels == 1 ?
+ STEREO_MONO : STEREO_NONINTERLEAVED);
+ codec_set_replaygain(ci->id3);
+
+ flac_seek_offset(&fc, samplesdone);
+ samplesdone=fc.samplenumber+fc.blocksize;
+ elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
+ ci->set_elapsed(elapsedtime);
+
+ /* The main decoding loop */
+ frame=0;
+ buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
+ while (bytesleft) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ /* Deal with any pending seek requests */
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ if (flac_seek(&fc,(uint32_t)(((uint64_t)param
+ *ci->id3->frequency)/1000))) {
+ /* Refill the input buffer */
+ buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
+ }
+
+ ci->set_elapsed(param);
+ ci->seek_complete();
+ }
+
+ if((res=flac_decode_frame(&fc,buf,
+ bytesleft,ci->yield)) < 0) {
+ LOGF("FLAC: Frame %d, error %d\n",frame,res);
+ return CODEC_ERROR;
+ }
+ consumed=fc.gb.index/8;
+ frame++;
+
+ ci->yield();
+ ci->pcmbuf_insert(&fc.decoded[0][fc.sample_skip], &fc.decoded[1][fc.sample_skip],
+ fc.blocksize - fc.sample_skip);
+
+ fc.sample_skip = 0;
+
+ /* Update the elapsed-time indicator */
+ samplesdone=fc.samplenumber+fc.blocksize;
+ elapsedtime=(samplesdone*10)/(ci->id3->frequency/100);
+ ci->set_elapsed(elapsedtime);
+
+ ci->advance_buffer(consumed);
+
+ buf = ci->request_buffer(&bytesleft, MAX_FRAMESIZE);
+ }
+
+ LOGF("FLAC: Decoded %lu samples\n",(unsigned long)samplesdone);
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/gbs.c b/lib/rbcodec/codecs/gbs.c
new file mode 100644
index 0000000000..def05ed351
--- /dev/null
+++ b/lib/rbcodec/codecs/gbs.c
@@ -0,0 +1,108 @@
+
+/* Ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
+
+#include <codecs/lib/codeclib.h>
+#include "libgme/gbs_emu.h"
+
+CODEC_HEADER
+
+/* Maximum number of bytes to process in one iteration */
+#define CHUNK_SIZE (1024*2)
+
+static int16_t samples[CHUNK_SIZE] IBSS_ATTR;
+static struct Gbs_Emu gbs_emu;
+
+/****************** rockbox interface ******************/
+
+static void set_codec_track(int t) {
+ Gbs_start_track(&gbs_emu, t);
+
+ /* for loop mode we disable track limits */
+ if (!ci->loop_track()) {
+ Track_set_fade(&gbs_emu, Track_get_length( &gbs_emu, t ), 4000);
+ }
+ ci->set_elapsed(t*1000); /* t is track no to display */
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* we only render 16 bits */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
+
+ /* 44 Khz, Interleaved stereo */
+ ci->configure(DSP_SET_FREQUENCY, 44100);
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+
+ Gbs_init(&gbs_emu);
+ Gbs_set_sample_rate(&gbs_emu, 44100);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ blargg_err_t err;
+ uint8_t *buf;
+ size_t n;
+ intptr_t param;
+ int track = 0;
+
+ DEBUGF("GBS: next_track\n");
+ if (codec_init()) {
+ return CODEC_ERROR;
+ }
+
+ codec_set_replaygain(ci->id3);
+
+ /* Read the entire file */
+ DEBUGF("GBS: request file\n");
+ ci->seek_buffer(0);
+ buf = ci->request_buffer(&n, ci->filesize);
+ if (!buf || n < (size_t)ci->filesize) {
+ DEBUGF("GBS: file load failed\n");
+ return CODEC_ERROR;
+ }
+
+ if ((err = Gbs_load_mem(&gbs_emu, buf, ci->filesize))) {
+ DEBUGF("GBS: Gbs_load_mem failed (%s)\n", err);
+ return CODEC_ERROR;
+ }
+
+ /* Update internal track count */
+ if (gbs_emu.m3u.size > 0)
+ gbs_emu.track_count = gbs_emu.m3u.size;
+
+next_track:
+ set_codec_track(track);
+
+ /* The main decoder loop */
+ while (1) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)
+ break;
+
+ if (action == CODEC_ACTION_SEEK_TIME) {
+ track = param/1000;
+ ci->seek_complete();
+ if (track >= gbs_emu.track_count) break;
+ goto next_track;
+ }
+
+ /* Generate audio buffer */
+ err = Gbs_play(&gbs_emu, CHUNK_SIZE, samples);
+ if (err || Track_ended(&gbs_emu)) {
+ track++;
+ if (track >= gbs_emu.track_count) break;
+ goto next_track;
+ }
+
+ ci->pcmbuf_insert(samples, NULL, CHUNK_SIZE >> 1);
+ }
+
+ return CODEC_OK;
+}
diff --git a/lib/rbcodec/codecs/hes.c b/lib/rbcodec/codecs/hes.c
new file mode 100644
index 0000000000..849fd88f12
--- /dev/null
+++ b/lib/rbcodec/codecs/hes.c
@@ -0,0 +1,108 @@
+/* Ripped off from Game_Music_Emu 0.5.2. http://www.slack.net/~ant/ */
+
+#include <string.h>
+#include "codeclib.h"
+#include "libgme/hes_emu.h"
+
+CODEC_HEADER
+
+/* Maximum number of bytes to process in one iteration */
+#define CHUNK_SIZE (1024*2)
+
+static int16_t samples[CHUNK_SIZE] IBSS_ATTR;
+static struct Hes_Emu hes_emu;
+
+/****************** rockbox interface ******************/
+
+static void set_codec_track(int t) {
+ Hes_start_track(&hes_emu, t);
+
+ /* for loop mode we disable track limits */
+ if (!ci->loop_track()) {
+ Track_set_fade(&hes_emu, Track_get_length( &hes_emu, t ), 4000);
+ }
+ ci->set_elapsed(t*1000); /* t is track no to display */
+}
+
+/* this is the codec entry point */
+enum codec_status codec_main(enum codec_entry_call_reason reason)
+{
+ if (reason == CODEC_LOAD) {
+ /* we only render 16 bits */
+ ci->configure(DSP_SET_SAMPLE_DEPTH, 16);
+
+ /* 44 Khz, Interleaved stereo */
+ ci->configure(DSP_SET_FREQUENCY, 44100);
+ ci->configure(DSP_SET_STEREO_MODE, STEREO_INTERLEAVED);
+
+ Hes_init(&hes_emu);
+ Hes_set_sample_rate(&hes_emu, 44100);
+ }
+
+ return CODEC_OK;
+}
+
+/* this is called for each file to process */
+enum codec_status codec_run(void)
+{
+ blargg_err_t err;
+ uint8_t *buf;
+ size_t n;
+ intptr_t param;
+ int track = 0;
+
+ DEBUGF("HES: next_track\n");
+ if (codec_init()) {
+ return CODEC_ERROR;
+ }
+
+ codec_set_replaygain(ci->id3);
+
+ /* Read the entire file */
+ DEBUGF("HES: request file\n");
+ ci->seek_buffer(0);
+ buf = ci->request_buffer(&n, ci->filesize);
+ if (!buf || n < (size_t)ci->filesize) {
+ DEBUGF("HES: file load failed\n");
+ return CODEC_ERROR;
+ }
+
+ if ((err = Hes_load_mem(&hes_emu, buf, ci->filesize))) {
+ DEBUGF("HES: Hes_load_mem failed (%s)\n", err);
+ return CODEC_ERROR;
+ }
+
+ /* Update internal track count */
+ if (hes_emu.m3u.size > 0)
+ hes_emu.track_count = hes_emu.m3u.size;
+
+next_track:
+ set_codec_track(track);
+
+ /* The main decoder loop */
+ while ( 1 ) {
+ enum codec_command_action action = ci->get_command(&param);
+
+ if (action == CODEC_ACTION_HALT)</