summaryrefslogtreecommitdiff
path: root/apps/codecs/libpcm
diff options
context:
space:
mode:
authorYoshihisa Uchida <uchida@rockbox.org>2010-02-20 10:15:36 +0000
committerYoshihisa Uchida <uchida@rockbox.org>2010-02-20 10:15:36 +0000
commit9f63f4f2fcb5400a2c043504799228e79c424cab (patch)
tree4781560a69f642f44c8c1ab95d7ad1c1a042bdfc /apps/codecs/libpcm
parentbc8cefd1a472072e575a81ca10d548d7e83209a6 (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.c216
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;
}