diff options
author | Sean Bartell <wingedtachikoma@gmail.com> | 2011-06-25 21:32:25 -0400 |
---|---|---|
committer | Nils Wallménius <nils@rockbox.org> | 2012-04-25 22:13:20 +0200 |
commit | f40bfc9267b13b54e6379dfe7539447662879d24 (patch) | |
tree | 9b20069d5e62809ff434061ad730096836f916f2 /lib/rbcodec/codecs/libpcm/ieee_float.c | |
parent | a0009907de7a0107d49040d8a180f140e2eff299 (diff) | |
download | rockbox-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/libpcm/ieee_float.c')
-rw-r--r-- | lib/rbcodec/codecs/libpcm/ieee_float.c | 165 |
1 files changed, 165 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libpcm/ieee_float.c b/lib/rbcodec/codecs/libpcm/ieee_float.c new file mode 100644 index 0000000000..639390bcd5 --- /dev/null +++ b/lib/rbcodec/codecs/libpcm/ieee_float.c | |||
@@ -0,0 +1,165 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id$ | ||
9 | * | ||
10 | * Copyright (C) 2009 Yoshihisa Uchida | ||
11 | * | ||
12 | * This program is free software; you can redistribute it and/or | ||
13 | * modify it under the terms of the GNU General Public License | ||
14 | * as published by the Free Software Foundation; either version 2 | ||
15 | * of the License, or (at your option) any later version. | ||
16 | * | ||
17 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
18 | * KIND, either express or implied. | ||
19 | * | ||
20 | ****************************************************************************/ | ||
21 | #include "codeclib.h" | ||
22 | #include "pcm_common.h" | ||
23 | #include "support_formats.h" | ||
24 | |||
25 | /* | ||
26 | * IEEE float | ||
27 | */ | ||
28 | |||
29 | static struct pcm_format *fmt; | ||
30 | |||
31 | static bool set_format(struct pcm_format *format) | ||
32 | { | ||
33 | fmt = format; | ||
34 | |||
35 | if (fmt->channels == 0) | ||
36 | { | ||
37 | DEBUGF("CODEC_ERROR: channels is 0\n"); | ||
38 | return false; | ||
39 | } | ||
40 | |||
41 | if (fmt->bitspersample != 32 && fmt->bitspersample != 64) | ||
42 | { | ||
43 | DEBUGF("CODEC_ERROR: ieee float must be 32 or 64 bitspersample: %d\n", | ||
44 | fmt->bitspersample); | ||
45 | return false; | ||
46 | } | ||
47 | |||
48 | fmt->bytespersample = fmt->bitspersample >> 3; | ||
49 | |||
50 | if (fmt->blockalign == 0) | ||
51 | fmt->blockalign = fmt->bytespersample * fmt->channels; | ||
52 | |||
53 | fmt->samplesperblock = fmt->blockalign / (fmt->bytespersample * fmt->channels); | ||
54 | |||
55 | /* chunksize = about 1/50[sec] data */ | ||
56 | fmt->chunksize = (ci->id3->frequency / (50 * fmt->samplesperblock)) | ||
57 | * fmt->blockalign; | ||
58 | |||
59 | return true; | ||
60 | } | ||
61 | |||
62 | static struct pcm_pos *get_seek_pos(uint32_t seek_val, int seek_mode, | ||
63 | uint8_t *(*read_buffer)(size_t *realsize)) | ||
64 | { | ||
65 | static struct pcm_pos newpos; | ||
66 | uint32_t newblock = (seek_mode == PCM_SEEK_TIME) ? | ||
67 | ((uint64_t)seek_val * ci->id3->frequency / 1000LL) | ||
68 | / fmt->samplesperblock : | ||
69 | seek_val / fmt->blockalign; | ||
70 | |||
71 | (void)read_buffer; | ||
72 | newpos.pos = newblock * fmt->blockalign; | ||
73 | newpos.samples = newblock * fmt->samplesperblock; | ||
74 | return &newpos; | ||
75 | } | ||
76 | |||
77 | static int decode(const uint8_t *inbuf, size_t inbufsize, | ||
78 | int32_t *outbuf, int *outbufsize) | ||
79 | { | ||
80 | uint32_t i; | ||
81 | int32_t pcm; | ||
82 | int16_t exp; | ||
83 | int sgn; | ||
84 | |||
85 | if (fmt->bitspersample == 32) | ||
86 | { | ||
87 | for (i = 0; i < inbufsize; i += 4) | ||
88 | { | ||
89 | if (fmt->is_little_endian) | ||
90 | { | ||
91 | pcm = (inbuf[0]<<5)|(inbuf[1]<<13)|((inbuf[2]|0x80)<<21); | ||
92 | exp = ((inbuf[2]>>7)|((inbuf[3]&0x7f)<<1)) - 127; | ||
93 | sgn = inbuf[3] & 0x80; | ||
94 | } | ||
95 | else | ||
96 | { | ||
97 | pcm = (inbuf[3]<<5)|(inbuf[2]<<13)|((inbuf[1]|0x80)<<21); | ||
98 | exp = ((inbuf[1]>>7)|((inbuf[0]&0x7f)<<1)) - 127; | ||
99 | sgn = inbuf[0] & 0x80; | ||
100 | } | ||
101 | if (exp > -29 && exp < 0) | ||
102 | { | ||
103 | pcm >>= -exp; | ||
104 | if (sgn) | ||
105 | pcm = -pcm; | ||
106 | } | ||
107 | else if (exp < -28) | ||
108 | pcm = 0; | ||
109 | else | ||
110 | pcm = (sgn)?-(1<<28):(1<<28)-1; | ||
111 | |||
112 | outbuf[i/4] = pcm; | ||
113 | inbuf += 4; | ||
114 | } | ||
115 | *outbufsize = inbufsize >> 2; | ||
116 | } | ||
117 | else | ||
118 | { | ||
119 | for (i = 0; i < inbufsize; i += 8) | ||
120 | { | ||
121 | if (fmt->is_little_endian) | ||
122 | { | ||
123 | pcm = inbuf[3]|(inbuf[4]<<8)|(inbuf[5]<<16)|(((inbuf[6]&0x0f)|0x10)<<24); | ||
124 | exp = (((inbuf[6]&0xf0)>>4)|((inbuf[7]&0x7f)<<4)) - 1023; | ||
125 | sgn = inbuf[7] & 0x80; | ||
126 | } | ||
127 | else | ||
128 | { | ||
129 | pcm = inbuf[4]|(inbuf[3]<<8)|(inbuf[2]<<16)|(((inbuf[1]&0x0f)|0x10)<<24); | ||
130 | exp = (((inbuf[1]&0xf0)>>4)|((inbuf[0]&0x7f)<<4)) - 1023; | ||
131 | sgn = inbuf[0] & 0x80; | ||
132 | } | ||
133 | if (exp > -29 && exp < 0) | ||
134 | { | ||
135 | pcm >>= -exp; | ||
136 | if (sgn) | ||
137 | pcm = -pcm; | ||
138 | } | ||
139 | else if (exp < -28) | ||
140 | pcm = 0; | ||
141 | else | ||
142 | pcm = (sgn)?-(1<<28):(1<<28)-1; | ||
143 | |||
144 | outbuf[i/8] = pcm; | ||
145 | inbuf += 8; | ||
146 | } | ||
147 | *outbufsize = inbufsize >> 3; | ||
148 | } | ||
149 | |||
150 | if (fmt->channels == 2) | ||
151 | *outbufsize >>= 1; | ||
152 | |||
153 | return CODEC_OK; | ||
154 | } | ||
155 | |||
156 | static const struct pcm_codec codec = { | ||
157 | set_format, | ||
158 | get_seek_pos, | ||
159 | decode, | ||
160 | }; | ||
161 | |||
162 | const struct pcm_codec *get_ieee_float_codec(void) | ||
163 | { | ||
164 | return &codec; | ||
165 | } | ||