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/demac/demac.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/demac/demac.c')
-rw-r--r-- | lib/rbcodec/codecs/demac/demac.c | 281 |
1 files changed, 281 insertions, 0 deletions
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 @@ | |||
1 | /* | ||
2 | |||
3 | demac - A Monkey's Audio decoder | ||
4 | |||
5 | $Id$ | ||
6 | |||
7 | Copyright (C) Dave Chapman 2007 | ||
8 | |||
9 | This program is free software; you can redistribute it and/or modify | ||
10 | it under the terms of the GNU General Public License as published by | ||
11 | the Free Software Foundation; either version 2 of the License, or | ||
12 | (at your option) any later version. | ||
13 | |||
14 | This program is distributed in the hope that it will be useful, | ||
15 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
17 | GNU General Public License for more details. | ||
18 | |||
19 | You should have received a copy of the GNU General Public License | ||
20 | along with this program; if not, write to the Free Software | ||
21 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110, USA | ||
22 | |||
23 | */ | ||
24 | |||
25 | /* | ||
26 | |||
27 | This example is intended to demonstrate how the decoder can be used in | ||
28 | embedded devices - there is no usage of dynamic memory (i.e. no | ||
29 | malloc/free) and small buffer sizes are chosen to minimise both the | ||
30 | memory usage and decoding latency. | ||
31 | |||
32 | This implementation requires the following memory and supports decoding of all APE files up to 24-bit Stereo. | ||
33 | |||
34 | 32768 - data from the input stream to be presented to the decoder in one contiguous chunk. | ||
35 | 18432 - decoding buffer (left channel) | ||
36 | 18432 - decoding buffer (right channel) | ||
37 | |||
38 | 17408+5120+2240 - buffers used for filter histories (compression levels 2000-5000) | ||
39 | |||
40 | In addition, this example uses a static 27648 byte buffer as temporary | ||
41 | storage for outputting the data to a WAV file but that could be | ||
42 | avoided by writing the decoded data one sample at a time. | ||
43 | |||
44 | */ | ||
45 | |||
46 | #include <stdio.h> | ||
47 | #include <inttypes.h> | ||
48 | #include <stdlib.h> | ||
49 | #include <sys/stat.h> | ||
50 | #include <fcntl.h> | ||
51 | #include <unistd.h> | ||
52 | #include <string.h> | ||
53 | |||
54 | #include "demac.h" | ||
55 | #include "wavwrite.h" | ||
56 | |||
57 | #ifndef __WIN32__ | ||
58 | #define O_BINARY 0 | ||
59 | #endif | ||
60 | |||
61 | #define CALC_CRC 1 | ||
62 | |||
63 | #define BLOCKS_PER_LOOP 4608 | ||
64 | #define MAX_CHANNELS 2 | ||
65 | #define MAX_BYTESPERSAMPLE 3 | ||
66 | |||
67 | #define INPUT_CHUNKSIZE (32*1024) | ||
68 | |||
69 | #ifndef MIN | ||
70 | #define MIN(a,b) ((a) < (b) ? (a) : (b)) | ||
71 | #endif | ||
72 | |||
73 | |||
74 | /* 4608*2*3 = 27648 bytes */ | ||
75 | static unsigned char wavbuffer[BLOCKS_PER_LOOP*MAX_CHANNELS*MAX_BYTESPERSAMPLE]; | ||
76 | |||
77 | /* 4608*4 = 18432 bytes per channel */ | ||
78 | static int32_t decoded0[BLOCKS_PER_LOOP]; | ||
79 | static int32_t decoded1[BLOCKS_PER_LOOP]; | ||
80 | |||
81 | /* We assume that 32KB of compressed data is enough to extract up to | ||
82 | 27648 bytes of decompressed data. */ | ||
83 | |||
84 | static unsigned char inbuffer[INPUT_CHUNKSIZE]; | ||
85 | |||
86 | int ape_decode(char* infile, char* outfile) | ||
87 | { | ||
88 | int fd; | ||
89 | int fdwav; | ||
90 | int currentframe; | ||
91 | int nblocks; | ||
92 | int bytesconsumed; | ||
93 | struct ape_ctx_t ape_ctx; | ||
94 | int i, n; | ||
95 | unsigned char* p; | ||
96 | int bytesinbuffer; | ||
97 | int blockstodecode; | ||
98 | int res; | ||
99 | int firstbyte; | ||
100 | int16_t sample16; | ||
101 | int32_t sample32; | ||
102 | uint32_t frame_crc; | ||
103 | int crc_errors = 0; | ||
104 | |||
105 | fd = open(infile,O_RDONLY|O_BINARY); | ||
106 | if (fd < 0) return -1; | ||
107 | |||
108 | /* Read the file headers to populate the ape_ctx struct */ | ||
109 | if (ape_parseheader(fd,&ape_ctx) < 0) { | ||
110 | printf("Cannot read header\n"); | ||
111 | close(fd); | ||
112 | return -1; | ||
113 | } | ||
114 | |||
115 | if ((ape_ctx.fileversion < APE_MIN_VERSION) || (ape_ctx.fileversion > APE_MAX_VERSION)) { | ||
116 | printf("Unsupported file version - %.2f\n", ape_ctx.fileversion/1000.0); | ||
117 | close(fd); | ||
118 | return -2; | ||
119 | } | ||
120 | |||
121 | //ape_dumpinfo(&ape_ctx); | ||
122 | |||
123 | printf("Decoding file - v%.2f, compression level %d\n",ape_ctx.fileversion/1000.0,ape_ctx.compressiontype); | ||
124 | |||
125 | /* Open the WAV file and write a canonical 44-byte WAV header | ||
126 | based on the audio format information in the ape_ctx struct. | ||
127 | |||
128 | NOTE: This example doesn't write the original WAV header and | ||
129 | tail data which are (optionally) stored in the APE file. | ||
130 | */ | ||
131 | fdwav = open_wav(&ape_ctx,outfile); | ||
132 | |||
133 | currentframe = 0; | ||
134 | |||
135 | /* Initialise the buffer */ | ||
136 | lseek(fd, ape_ctx.firstframe, SEEK_SET); | ||
137 | bytesinbuffer = read(fd, inbuffer, INPUT_CHUNKSIZE); | ||
138 | firstbyte = 3; /* Take account of the little-endian 32-bit byte ordering */ | ||
139 | |||
140 | /* The main decoding loop - we decode the frames a small chunk at a time */ | ||
141 | while (currentframe < ape_ctx.totalframes) | ||
142 | { | ||
143 | /* Calculate how many blocks there are in this frame */ | ||
144 | if (currentframe == (ape_ctx.totalframes - 1)) | ||
145 | nblocks = ape_ctx.finalframeblocks; | ||
146 | else | ||
147 | nblocks = ape_ctx.blocksperframe; | ||
148 | |||
149 | ape_ctx.currentframeblocks = nblocks; | ||
150 | |||
151 | /* Initialise the frame decoder */ | ||
152 | init_frame_decoder(&ape_ctx, inbuffer, &firstbyte, &bytesconsumed); | ||
153 | |||
154 | /* Update buffer */ | ||
155 | memmove(inbuffer,inbuffer + bytesconsumed, bytesinbuffer - bytesconsumed); | ||
156 | bytesinbuffer -= bytesconsumed; | ||
157 | |||
158 | n = read(fd, inbuffer + bytesinbuffer, INPUT_CHUNKSIZE - bytesinbuffer); | ||
159 | bytesinbuffer += n; | ||
160 | |||
161 | #if CALC_CRC | ||
162 | frame_crc = ape_initcrc(); | ||
163 | #endif | ||
164 | |||
165 | /* Decode the frame a chunk at a time */ | ||
166 | while (nblocks > 0) | ||
167 | { | ||
168 | blockstodecode = MIN(BLOCKS_PER_LOOP, nblocks); | ||
169 | |||
170 | if ((res = decode_chunk(&ape_ctx, inbuffer, &firstbyte, | ||
171 | &bytesconsumed, | ||
172 | decoded0, decoded1, | ||
173 | blockstodecode)) < 0) | ||
174 | { | ||
175 | /* Frame decoding error, abort */ | ||
176 | close(fd); | ||
177 | return res; | ||
178 | } | ||
179 | |||
180 | /* Convert the output samples to WAV format and write to output file */ | ||
181 | p = wavbuffer; | ||
182 | if (ape_ctx.bps == 8) { | ||
183 | for (i = 0 ; i < blockstodecode ; i++) | ||
184 | { | ||
185 | /* 8 bit WAV uses unsigned samples */ | ||
186 | *(p++) = (decoded0[i] + 0x80) & 0xff; | ||
187 | |||
188 | if (ape_ctx.channels == 2) { | ||
189 | *(p++) = (decoded1[i] + 0x80) & 0xff; | ||
190 | } | ||
191 | } | ||
192 | } else if (ape_ctx.bps == 16) { | ||
193 | for (i = 0 ; i < blockstodecode ; i++) | ||
194 | { | ||
195 | sample16 = decoded0[i]; | ||
196 | *(p++) = sample16 & 0xff; | ||
197 | *(p++) = (sample16 >> 8) & 0xff; | ||
198 | |||
199 | if (ape_ctx.channels == 2) { | ||
200 | sample16 = decoded1[i]; | ||
201 | *(p++) = sample16 & 0xff; | ||
202 | *(p++) = (sample16 >> 8) & 0xff; | ||
203 | } | ||
204 | } | ||
205 | } else if (ape_ctx.bps == 24) { | ||
206 | for (i = 0 ; i < blockstodecode ; i++) | ||
207 | { | ||
208 | sample32 = decoded0[i]; | ||
209 | *(p++) = sample32 & 0xff; | ||
210 | *(p++) = (sample32 >> 8) & 0xff; | ||
211 | *(p++) = (sample32 >> 16) & 0xff; | ||
212 | |||
213 | if (ape_ctx.channels == 2) { | ||
214 | sample32 = decoded1[i]; | ||
215 | *(p++) = sample32 & 0xff; | ||
216 | *(p++) = (sample32 >> 8) & 0xff; | ||
217 | *(p++) = (sample32 >> 16) & 0xff; | ||
218 | } | ||
219 | } | ||
220 | } | ||
221 | |||
222 | #if CALC_CRC | ||
223 | frame_crc = ape_updatecrc(wavbuffer, p - wavbuffer, frame_crc); | ||
224 | #endif | ||
225 | write(fdwav,wavbuffer,p - wavbuffer); | ||
226 | |||
227 | /* Update the buffer */ | ||
228 | memmove(inbuffer,inbuffer + bytesconsumed, bytesinbuffer - bytesconsumed); | ||
229 | bytesinbuffer -= bytesconsumed; | ||
230 | |||
231 | n = read(fd, inbuffer + bytesinbuffer, INPUT_CHUNKSIZE - bytesinbuffer); | ||
232 | bytesinbuffer += n; | ||
233 | |||
234 | /* Decrement the block count */ | ||
235 | nblocks -= blockstodecode; | ||
236 | } | ||
237 | |||
238 | #if CALC_CRC | ||
239 | frame_crc = ape_finishcrc(frame_crc); | ||
240 | |||
241 | if (ape_ctx.CRC != frame_crc) | ||
242 | { | ||
243 | fprintf(stderr,"CRC error in frame %d\n",currentframe); | ||
244 | crc_errors++; | ||
245 | } | ||
246 | #endif | ||
247 | |||
248 | currentframe++; | ||
249 | } | ||
250 | |||
251 | close(fd); | ||
252 | close(fdwav); | ||
253 | |||
254 | if (crc_errors > 0) | ||
255 | return -1; | ||
256 | else | ||
257 | return 0; | ||
258 | } | ||
259 | |||
260 | int main(int argc, char* argv[]) | ||
261 | { | ||
262 | int res; | ||
263 | |||
264 | if (argc != 3) { | ||
265 | fprintf(stderr,"Usage: demac infile.ape outfile.wav\n"); | ||
266 | return 0; | ||
267 | } | ||
268 | |||
269 | res = ape_decode(argv[1], argv[2]); | ||
270 | |||
271 | if (res < 0) | ||
272 | { | ||
273 | fprintf(stderr,"DECODING ERROR %d, ABORTING\n", res); | ||
274 | } | ||
275 | else | ||
276 | { | ||
277 | fprintf(stderr,"DECODED OK - NO CRC ERRORS.\n"); | ||
278 | } | ||
279 | |||
280 | return 0; | ||
281 | } | ||