diff options
author | Yoshihisa Uchida <uchida@rockbox.org> | 2010-02-20 10:15:36 +0000 |
---|---|---|
committer | Yoshihisa Uchida <uchida@rockbox.org> | 2010-02-20 10:15:36 +0000 |
commit | 9f63f4f2fcb5400a2c043504799228e79c424cab (patch) | |
tree | 4781560a69f642f44c8c1ab95d7ad1c1a042bdfc /apps/codecs/libpcm | |
parent | bc8cefd1a472072e575a81ca10d548d7e83209a6 (diff) |
libpcm: linear pcm decode logic separates according to each bitspersample, endian, and signess.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@24785 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'apps/codecs/libpcm')
-rw-r--r-- | apps/codecs/libpcm/linear_pcm.c | 216 |
1 files changed, 160 insertions, 56 deletions
diff --git a/apps/codecs/libpcm/linear_pcm.c b/apps/codecs/libpcm/linear_pcm.c index 5360d79901..451154cc9b 100644 --- a/apps/codecs/libpcm/linear_pcm.c +++ b/apps/codecs/libpcm/linear_pcm.c @@ -59,7 +59,7 @@ static struct pcm_pos *get_seek_pos(long seek_time, { static struct pcm_pos newpos; uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) - / (1000LL * fmt->samplesperblock); + / (1000LL * fmt->samplesperblock); (void)read_buffer; newpos.pos = newblock * fmt->blockalign; @@ -67,86 +67,190 @@ static struct pcm_pos *get_seek_pos(long seek_time, return &newpos; } -static int decode(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf, int *outbufsize) +/* 8bit decode functions */ +static inline void decode_s8(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) { - uint32_t i; + size_t i = 0; + for ( ; i < inbufsize; i++) + outbuf[i] = SE(inbuf[i])<<21; +} + +static inline void decode_u8(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i++) + outbuf[i] = SFT(inbuf[i])<<21; +} + +/* 16bit decode functions */ +static inline void decode_s16le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 2) + outbuf[i/2] = (inbuf[i]<<13)|(SE(inbuf[i+1])<<21); +} + +static inline void decode_u16le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 2) + outbuf[i/2] = (inbuf[i]<<13)|(SFT(inbuf[i+1])<<21); +} + +static inline void decode_s16be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 2) + outbuf[i/2] = (inbuf[i+1]<<13)|(SE(inbuf[i])<<21); +} + +static inline void decode_u16be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 2) + outbuf[i/2] = (inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); +} + +/* 24bit decode functions */ +static inline void decode_s24le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 3) + outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i+2])<<21); +} + +static inline void decode_u24le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 3) + outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i+2])<<21); +} + +static inline void decode_s24be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 3) + outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); +} + +static inline void decode_u24be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 3) + outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); +} + +/* 32bit decode functions */ +static inline void decode_s32le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 4) + outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SE(inbuf[i+3])<<21); +} + +static inline void decode_u32le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 4) + outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SFT(inbuf[i+3])<<21); +} + +static inline void decode_s32be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 4) + outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); +} + +static inline void decode_u32be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) +{ + size_t i = 0; + + for ( ; i < inbufsize; i += 4) + outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); +} + +static int decode(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf, int *outbufcount) +{ if (fmt->bitspersample > 24) { - for (i = 0; i < inbufsize; i += 4) + if (fmt->is_little_endian) { - if (fmt->is_little_endian) - { - if (fmt->is_signed) - outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SE(inbuf[i+3])<<21); - else - outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SFT(inbuf[i+3])<<21); - } + if (fmt->is_signed) + decode_s32le(inbuf, inbufsize, outbuf); else - { - if (fmt->is_signed) - outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); - else - outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); - } + decode_u32le(inbuf, inbufsize, outbuf); } - *outbufsize = inbufsize >> 2; + else + { + if (fmt->is_signed) + decode_s32be(inbuf, inbufsize, outbuf); + else + decode_u32be(inbuf, inbufsize, outbuf); + } + *outbufcount = inbufsize >> 2; } else if (fmt->bitspersample > 16) { - for (i = 0; i < inbufsize; i += 3) + if (fmt->is_little_endian) { - if (fmt->is_little_endian) - { - if (fmt->is_signed) - outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i+2])<<21); - else - outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i+2])<<21); - } + if (fmt->is_signed) + decode_s24le(inbuf, inbufsize, outbuf); + else + decode_u24le(inbuf, inbufsize, outbuf); + } + else + { + if (fmt->is_signed) + decode_s24be(inbuf, inbufsize, outbuf); else - { - if (fmt->is_signed) - outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); - else - outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); - } + decode_u24be(inbuf, inbufsize, outbuf); } - *outbufsize = inbufsize/3; + *outbufcount = inbufsize / 3; } else if (fmt->bitspersample > 8) { - for (i = 0; i < inbufsize; i += 2) + if (fmt->is_little_endian) { - if (fmt->is_little_endian) - { - if (fmt->is_signed) - outbuf[i/2] = (inbuf[i]<<13)|(SE(inbuf[i+1])<<21); - else - outbuf[i/2] = (inbuf[i]<<13)|(SFT(inbuf[i+1])<<21); - } + if (fmt->is_signed) + decode_s16le(inbuf, inbufsize, outbuf); else - { - if (fmt->is_signed) - outbuf[i/2] = (inbuf[i+1]<<13)|(SE(inbuf[i])<<21); - else - outbuf[i/2] = (inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); - } + decode_u16le(inbuf, inbufsize, outbuf); } - *outbufsize = inbufsize >> 1; - } - else - { - for (i = 0; i < inbufsize; i++) { + else + { if (fmt->is_signed) - outbuf[i] = SE(inbuf[i])<<21; + decode_s16be(inbuf, inbufsize, outbuf); else - outbuf[i] = SFT(inbuf[i])<<21; + decode_u16be(inbuf, inbufsize, outbuf); } - *outbufsize = inbufsize; + *outbufcount = inbufsize >> 1; + } + else + { + if (fmt->is_signed) + decode_s8(inbuf, inbufsize, outbuf); + else + decode_u8(inbuf, inbufsize, outbuf); + + *outbufcount = inbufsize; } if (fmt->channels == 2) - *outbufsize >>= 1; + *outbufcount >>= 1; return CODEC_OK; } |