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 | |
parent | bc8cefd1a472072e575a81ca10d548d7e83209a6 (diff) | |
download | rockbox-9f63f4f2fcb5400a2c043504799228e79c424cab.tar.gz rockbox-9f63f4f2fcb5400a2c043504799228e79c424cab.zip |
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')
-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, | |||
59 | { | 59 | { |
60 | static struct pcm_pos newpos; | 60 | static struct pcm_pos newpos; |
61 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) | 61 | uint32_t newblock = ((uint64_t)seek_time * ci->id3->frequency) |
62 | / (1000LL * fmt->samplesperblock); | 62 | / (1000LL * fmt->samplesperblock); |
63 | 63 | ||
64 | (void)read_buffer; | 64 | (void)read_buffer; |
65 | newpos.pos = newblock * fmt->blockalign; | 65 | newpos.pos = newblock * fmt->blockalign; |
@@ -67,86 +67,190 @@ static struct pcm_pos *get_seek_pos(long seek_time, | |||
67 | return &newpos; | 67 | return &newpos; |
68 | } | 68 | } |
69 | 69 | ||
70 | static int decode(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf, int *outbufsize) | 70 | /* 8bit decode functions */ |
71 | static inline void decode_s8(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
71 | { | 72 | { |
72 | uint32_t i; | 73 | size_t i = 0; |
73 | 74 | ||
75 | for ( ; i < inbufsize; i++) | ||
76 | outbuf[i] = SE(inbuf[i])<<21; | ||
77 | } | ||
78 | |||
79 | static inline void decode_u8(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
80 | { | ||
81 | size_t i = 0; | ||
82 | |||
83 | for ( ; i < inbufsize; i++) | ||
84 | outbuf[i] = SFT(inbuf[i])<<21; | ||
85 | } | ||
86 | |||
87 | /* 16bit decode functions */ | ||
88 | static inline void decode_s16le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
89 | { | ||
90 | size_t i = 0; | ||
91 | |||
92 | for ( ; i < inbufsize; i += 2) | ||
93 | outbuf[i/2] = (inbuf[i]<<13)|(SE(inbuf[i+1])<<21); | ||
94 | } | ||
95 | |||
96 | static inline void decode_u16le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
97 | { | ||
98 | size_t i = 0; | ||
99 | |||
100 | for ( ; i < inbufsize; i += 2) | ||
101 | outbuf[i/2] = (inbuf[i]<<13)|(SFT(inbuf[i+1])<<21); | ||
102 | } | ||
103 | |||
104 | static inline void decode_s16be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
105 | { | ||
106 | size_t i = 0; | ||
107 | |||
108 | for ( ; i < inbufsize; i += 2) | ||
109 | outbuf[i/2] = (inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
110 | } | ||
111 | |||
112 | static inline void decode_u16be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
113 | { | ||
114 | size_t i = 0; | ||
115 | |||
116 | for ( ; i < inbufsize; i += 2) | ||
117 | outbuf[i/2] = (inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
118 | } | ||
119 | |||
120 | /* 24bit decode functions */ | ||
121 | static inline void decode_s24le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
122 | { | ||
123 | size_t i = 0; | ||
124 | |||
125 | for ( ; i < inbufsize; i += 3) | ||
126 | outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i+2])<<21); | ||
127 | } | ||
128 | |||
129 | static inline void decode_u24le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
130 | { | ||
131 | size_t i = 0; | ||
132 | |||
133 | for ( ; i < inbufsize; i += 3) | ||
134 | outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i+2])<<21); | ||
135 | } | ||
136 | |||
137 | static inline void decode_s24be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
138 | { | ||
139 | size_t i = 0; | ||
140 | |||
141 | for ( ; i < inbufsize; i += 3) | ||
142 | outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
143 | } | ||
144 | |||
145 | static inline void decode_u24be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
146 | { | ||
147 | size_t i = 0; | ||
148 | |||
149 | for ( ; i < inbufsize; i += 3) | ||
150 | outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
151 | } | ||
152 | |||
153 | /* 32bit decode functions */ | ||
154 | static inline void decode_s32le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
155 | { | ||
156 | size_t i = 0; | ||
157 | |||
158 | for ( ; i < inbufsize; i += 4) | ||
159 | outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SE(inbuf[i+3])<<21); | ||
160 | } | ||
161 | |||
162 | static inline void decode_u32le(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
163 | { | ||
164 | size_t i = 0; | ||
165 | |||
166 | for ( ; i < inbufsize; i += 4) | ||
167 | outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SFT(inbuf[i+3])<<21); | ||
168 | } | ||
169 | |||
170 | static inline void decode_s32be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
171 | { | ||
172 | size_t i = 0; | ||
173 | |||
174 | for ( ; i < inbufsize; i += 4) | ||
175 | outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
176 | } | ||
177 | |||
178 | static inline void decode_u32be(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf) | ||
179 | { | ||
180 | size_t i = 0; | ||
181 | |||
182 | for ( ; i < inbufsize; i += 4) | ||
183 | outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
184 | } | ||
185 | |||
186 | static int decode(const uint8_t *inbuf, size_t inbufsize, int32_t *outbuf, int *outbufcount) | ||
187 | { | ||
74 | if (fmt->bitspersample > 24) | 188 | if (fmt->bitspersample > 24) |
75 | { | 189 | { |
76 | for (i = 0; i < inbufsize; i += 4) | 190 | if (fmt->is_little_endian) |
77 | { | 191 | { |
78 | if (fmt->is_little_endian) | 192 | if (fmt->is_signed) |
79 | { | 193 | decode_s32le(inbuf, inbufsize, outbuf); |
80 | if (fmt->is_signed) | ||
81 | outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SE(inbuf[i+3])<<21); | ||
82 | else | ||
83 | outbuf[i/4] = (inbuf[i]>>3)|(inbuf[i+1]<<5)|(inbuf[i+2]<<13)|(SFT(inbuf[i+3])<<21); | ||
84 | } | ||
85 | else | 194 | else |
86 | { | 195 | decode_u32le(inbuf, inbufsize, outbuf); |
87 | if (fmt->is_signed) | ||
88 | outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
89 | else | ||
90 | outbuf[i/4] = (inbuf[i+3]>>3)|(inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
91 | } | ||
92 | } | 196 | } |
93 | *outbufsize = inbufsize >> 2; | 197 | else |
198 | { | ||
199 | if (fmt->is_signed) | ||
200 | decode_s32be(inbuf, inbufsize, outbuf); | ||
201 | else | ||
202 | decode_u32be(inbuf, inbufsize, outbuf); | ||
203 | } | ||
204 | *outbufcount = inbufsize >> 2; | ||
94 | } | 205 | } |
95 | else if (fmt->bitspersample > 16) | 206 | else if (fmt->bitspersample > 16) |
96 | { | 207 | { |
97 | for (i = 0; i < inbufsize; i += 3) | 208 | if (fmt->is_little_endian) |
98 | { | 209 | { |
99 | if (fmt->is_little_endian) | 210 | if (fmt->is_signed) |
100 | { | 211 | decode_s24le(inbuf, inbufsize, outbuf); |
101 | if (fmt->is_signed) | 212 | else |
102 | outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i+2])<<21); | 213 | decode_u24le(inbuf, inbufsize, outbuf); |
103 | else | 214 | } |
104 | outbuf[i/3] = (inbuf[i]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i+2])<<21); | 215 | else |
105 | } | 216 | { |
217 | if (fmt->is_signed) | ||
218 | decode_s24be(inbuf, inbufsize, outbuf); | ||
106 | else | 219 | else |
107 | { | 220 | decode_u24be(inbuf, inbufsize, outbuf); |
108 | if (fmt->is_signed) | ||
109 | outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
110 | else | ||
111 | outbuf[i/3] = (inbuf[i+2]<<5)|(inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
112 | } | ||
113 | } | 221 | } |
114 | *outbufsize = inbufsize/3; | 222 | *outbufcount = inbufsize / 3; |
115 | } | 223 | } |
116 | else if (fmt->bitspersample > 8) | 224 | else if (fmt->bitspersample > 8) |
117 | { | 225 | { |
118 | for (i = 0; i < inbufsize; i += 2) | 226 | if (fmt->is_little_endian) |
119 | { | 227 | { |
120 | if (fmt->is_little_endian) | 228 | if (fmt->is_signed) |
121 | { | 229 | decode_s16le(inbuf, inbufsize, outbuf); |
122 | if (fmt->is_signed) | ||
123 | outbuf[i/2] = (inbuf[i]<<13)|(SE(inbuf[i+1])<<21); | ||
124 | else | ||
125 | outbuf[i/2] = (inbuf[i]<<13)|(SFT(inbuf[i+1])<<21); | ||
126 | } | ||
127 | else | 230 | else |
128 | { | 231 | decode_u16le(inbuf, inbufsize, outbuf); |
129 | if (fmt->is_signed) | ||
130 | outbuf[i/2] = (inbuf[i+1]<<13)|(SE(inbuf[i])<<21); | ||
131 | else | ||
132 | outbuf[i/2] = (inbuf[i+1]<<13)|(SFT(inbuf[i])<<21); | ||
133 | } | ||
134 | } | 232 | } |
135 | *outbufsize = inbufsize >> 1; | 233 | else |
136 | } | 234 | { |
137 | else | ||
138 | { | ||
139 | for (i = 0; i < inbufsize; i++) { | ||
140 | if (fmt->is_signed) | 235 | if (fmt->is_signed) |
141 | outbuf[i] = SE(inbuf[i])<<21; | 236 | decode_s16be(inbuf, inbufsize, outbuf); |
142 | else | 237 | else |
143 | outbuf[i] = SFT(inbuf[i])<<21; | 238 | decode_u16be(inbuf, inbufsize, outbuf); |
144 | } | 239 | } |
145 | *outbufsize = inbufsize; | 240 | *outbufcount = inbufsize >> 1; |
241 | } | ||
242 | else | ||
243 | { | ||
244 | if (fmt->is_signed) | ||
245 | decode_s8(inbuf, inbufsize, outbuf); | ||
246 | else | ||
247 | decode_u8(inbuf, inbufsize, outbuf); | ||
248 | |||
249 | *outbufcount = inbufsize; | ||
146 | } | 250 | } |
147 | 251 | ||
148 | if (fmt->channels == 2) | 252 | if (fmt->channels == 2) |
149 | *outbufsize >>= 1; | 253 | *outbufcount >>= 1; |
150 | 254 | ||
151 | return CODEC_OK; | 255 | return CODEC_OK; |
152 | } | 256 | } |