3 libdemac - A Monkey's Audio decoder
7 Copyright (C) Dave Chapman 2007
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.
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.
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
30 #include <sys/types.h>
41 #define APE_MAX(a,b) ((a)>(b)?(a):(b))
44 static inline int16_t get_int16(unsigned char* buf
)
46 return(buf
[0] | (buf
[1] << 8));
49 static inline uint16_t get_uint16(unsigned char* buf
)
51 return(buf
[0] | (buf
[1] << 8));
54 static inline uint32_t get_uint32(unsigned char* buf
)
56 return(buf
[0] | (buf
[1] << 8) | (buf
[2] << 16) | (buf
[3] << 24));
60 int ape_parseheaderbuf(unsigned char* buf
, struct ape_ctx_t
* ape_ctx
)
62 unsigned char* header
;
64 memset(ape_ctx
,0,sizeof(struct ape_ctx_t
));
65 /* TODO: Skip any leading junk such as id3v2 tags */
66 ape_ctx
->junklength
= 0;
68 memcpy(ape_ctx
->magic
, buf
, 4);
69 if (memcmp(ape_ctx
->magic
,"MAC ",4)!=0)
74 ape_ctx
->fileversion
= get_int16(buf
+ 4);
76 if (ape_ctx
->fileversion
>= 3980)
78 ape_ctx
->padding1
= get_int16(buf
+ 6);
79 ape_ctx
->descriptorlength
= get_uint32(buf
+ 8);
80 ape_ctx
->headerlength
= get_uint32(buf
+ 12);
81 ape_ctx
->seektablelength
= get_uint32(buf
+ 16);
82 ape_ctx
->wavheaderlength
= get_uint32(buf
+ 20);
83 ape_ctx
->audiodatalength
= get_uint32(buf
+ 24);
84 ape_ctx
->audiodatalength_high
= get_uint32(buf
+ 28);
85 ape_ctx
->wavtaillength
= get_uint32(buf
+ 32);
86 memcpy(ape_ctx
->md5
, buf
+ 36, 16);
88 header
= buf
+ ape_ctx
->descriptorlength
;
90 /* Read header data */
91 ape_ctx
->compressiontype
= get_uint16(header
+ 0);
92 ape_ctx
->formatflags
= get_uint16(header
+ 2);
93 ape_ctx
->blocksperframe
= get_uint32(header
+ 4);
94 ape_ctx
->finalframeblocks
= get_uint32(header
+ 8);
95 ape_ctx
->totalframes
= get_uint32(header
+ 12);
96 ape_ctx
->bps
= get_uint16(header
+ 16);
97 ape_ctx
->channels
= get_uint16(header
+ 18);
98 ape_ctx
->samplerate
= get_uint32(header
+ 20);
100 ape_ctx
->seektablefilepos
= ape_ctx
->junklength
+
101 ape_ctx
->descriptorlength
+
102 ape_ctx
->headerlength
;
104 ape_ctx
->firstframe
= ape_ctx
->junklength
+ ape_ctx
->descriptorlength
+
105 ape_ctx
->headerlength
+ ape_ctx
->seektablelength
+
106 ape_ctx
->wavheaderlength
;
108 ape_ctx
->headerlength
= 32;
109 ape_ctx
->compressiontype
= get_uint16(buf
+ 6);
110 ape_ctx
->formatflags
= get_uint16(buf
+ 8);
111 ape_ctx
->channels
= get_uint16(buf
+ 10);
112 ape_ctx
->samplerate
= get_uint32(buf
+ 12);
113 ape_ctx
->wavheaderlength
= get_uint32(buf
+ 16);
114 ape_ctx
->totalframes
= get_uint32(buf
+ 24);
115 ape_ctx
->finalframeblocks
= get_uint32(buf
+ 28);
117 if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_HAS_PEAK_LEVEL
)
119 ape_ctx
->headerlength
+= 4;
122 if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS
)
124 ape_ctx
->seektablelength
= get_uint32(buf
+ ape_ctx
->headerlength
);
125 ape_ctx
->seektablelength
*= sizeof(int32_t);
126 ape_ctx
->headerlength
+= 4;
128 ape_ctx
->seektablelength
= ape_ctx
->totalframes
* sizeof(int32_t);
131 if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_8_BIT
)
133 else if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_24_BIT
)
138 if (ape_ctx
->fileversion
>= 3950)
139 ape_ctx
->blocksperframe
= 73728 * 4;
140 else if ((ape_ctx
->fileversion
>= 3900) || (ape_ctx
->fileversion
>= 3800 && ape_ctx
->compressiontype
>= 4000))
141 ape_ctx
->blocksperframe
= 73728;
143 ape_ctx
->blocksperframe
= 9216;
145 ape_ctx
->seektablefilepos
= ape_ctx
->junklength
+ ape_ctx
->headerlength
+
146 ape_ctx
->wavheaderlength
;
148 ape_ctx
->firstframe
= ape_ctx
->junklength
+ ape_ctx
->headerlength
+
149 ape_ctx
->wavheaderlength
+ ape_ctx
->seektablelength
;
152 ape_ctx
->totalsamples
= ape_ctx
->finalframeblocks
;
153 if (ape_ctx
->totalframes
> 1)
154 ape_ctx
->totalsamples
+= ape_ctx
->blocksperframe
* (ape_ctx
->totalframes
-1);
156 ape_ctx
->numseekpoints
= APE_MAX(ape_ctx
->maxseekpoints
,
157 ape_ctx
->seektablelength
/ sizeof(int32_t));
164 /* Helper functions */
166 static int read_uint16(int fd
, uint16_t* x
)
168 unsigned char tmp
[2];
176 *x
= tmp
[0] | (tmp
[1] << 8);
181 static int read_int16(int fd
, int16_t* x
)
183 return read_uint16(fd
, (uint16_t*)x
);
186 static int read_uint32(int fd
, uint32_t* x
)
188 unsigned char tmp
[4];
196 *x
= tmp
[0] | (tmp
[1] << 8) | (tmp
[2] << 16) | (tmp
[3] << 24);
201 int ape_parseheader(int fd
, struct ape_ctx_t
* ape_ctx
)
205 /* TODO: Skip any leading junk such as id3v2 tags */
206 ape_ctx
->junklength
= 0;
208 lseek(fd
,ape_ctx
->junklength
,SEEK_SET
);
210 n
= read(fd
,&ape_ctx
->magic
,4);
211 if (n
!= 4) return -1;
213 if (memcmp(ape_ctx
->magic
,"MAC ",4)!=0)
218 if (read_int16(fd
,&ape_ctx
->fileversion
) < 0)
221 if (ape_ctx
->fileversion
>= 3980)
223 if (read_int16(fd
,&ape_ctx
->padding1
) < 0)
225 if (read_uint32(fd
,&ape_ctx
->descriptorlength
) < 0)
227 if (read_uint32(fd
,&ape_ctx
->headerlength
) < 0)
229 if (read_uint32(fd
,&ape_ctx
->seektablelength
) < 0)
231 if (read_uint32(fd
,&ape_ctx
->wavheaderlength
) < 0)
233 if (read_uint32(fd
,&ape_ctx
->audiodatalength
) < 0)
235 if (read_uint32(fd
,&ape_ctx
->audiodatalength_high
) < 0)
237 if (read_uint32(fd
,&ape_ctx
->wavtaillength
) < 0)
239 if (read(fd
,&ape_ctx
->md5
,16) != 16)
242 /* Skip any unknown bytes at the end of the descriptor. This is for future
244 if (ape_ctx
->descriptorlength
> 52)
245 lseek(fd
,ape_ctx
->descriptorlength
- 52, SEEK_CUR
);
247 /* Read header data */
248 if (read_uint16(fd
,&ape_ctx
->compressiontype
) < 0)
250 if (read_uint16(fd
,&ape_ctx
->formatflags
) < 0)
252 if (read_uint32(fd
,&ape_ctx
->blocksperframe
) < 0)
254 if (read_uint32(fd
,&ape_ctx
->finalframeblocks
) < 0)
256 if (read_uint32(fd
,&ape_ctx
->totalframes
) < 0)
258 if (read_uint16(fd
,&ape_ctx
->bps
) < 0)
260 if (read_uint16(fd
,&ape_ctx
->channels
) < 0)
262 if (read_uint32(fd
,&ape_ctx
->samplerate
) < 0)
265 ape_ctx
->descriptorlength
= 0;
266 ape_ctx
->headerlength
= 32;
268 if (read_uint16(fd
,&ape_ctx
->compressiontype
) < 0)
270 if (read_uint16(fd
,&ape_ctx
->formatflags
) < 0)
272 if (read_uint16(fd
,&ape_ctx
->channels
) < 0)
274 if (read_uint32(fd
,&ape_ctx
->samplerate
) < 0)
276 if (read_uint32(fd
,&ape_ctx
->wavheaderlength
) < 0)
278 if (read_uint32(fd
,&ape_ctx
->wavtaillength
) < 0)
280 if (read_uint32(fd
,&ape_ctx
->totalframes
) < 0)
282 if (read_uint32(fd
,&ape_ctx
->finalframeblocks
) < 0)
285 if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_HAS_PEAK_LEVEL
)
287 lseek(fd
, 4, SEEK_CUR
); /* Skip the peak level */
288 ape_ctx
->headerlength
+= 4;
291 if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_HAS_SEEK_ELEMENTS
)
293 if (read_uint32(fd
,&ape_ctx
->seektablelength
) < 0)
295 ape_ctx
->headerlength
+= 4;
296 ape_ctx
->seektablelength
*= sizeof(int32_t);
298 ape_ctx
->seektablelength
= ape_ctx
->totalframes
* sizeof(int32_t);
301 if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_8_BIT
)
303 else if (ape_ctx
->formatflags
& MAC_FORMAT_FLAG_24_BIT
)
308 if (ape_ctx
->fileversion
>= 3950)
309 ape_ctx
->blocksperframe
= 73728 * 4;
310 else if ((ape_ctx
->fileversion
>= 3900) || (ape_ctx
->fileversion
>= 3800 && ape_ctx
->compressiontype
>= 4000))
311 ape_ctx
->blocksperframe
= 73728;
313 ape_ctx
->blocksperframe
= 9216;
315 /* Skip any stored wav header */
316 if (!(ape_ctx
->formatflags
& MAC_FORMAT_FLAG_CREATE_WAV_HEADER
))
318 lseek(fd
, ape_ctx
->wavheaderlength
, SEEK_CUR
);
322 ape_ctx
->totalsamples
= ape_ctx
->finalframeblocks
;
323 if (ape_ctx
->totalframes
> 1)
324 ape_ctx
->totalsamples
+= ape_ctx
->blocksperframe
* (ape_ctx
->totalframes
-1);
326 if (ape_ctx
->seektablelength
> 0)
328 ape_ctx
->seektable
= malloc(ape_ctx
->seektablelength
);
329 if (ape_ctx
->seektable
== NULL
)
331 for (i
=0; i
< ape_ctx
->seektablelength
/ sizeof(uint32_t); i
++)
333 if (read_uint32(fd
,&ape_ctx
->seektable
[i
]) < 0)
335 free(ape_ctx
->seektable
);
341 ape_ctx
->firstframe
= ape_ctx
->junklength
+ ape_ctx
->descriptorlength
+
342 ape_ctx
->headerlength
+ ape_ctx
->seektablelength
+
343 ape_ctx
->wavheaderlength
;
348 void ape_dumpinfo(struct ape_ctx_t
* ape_ctx
)
352 printf("Descriptor Block:\n\n");
353 printf("magic = \"%c%c%c%c\"\n",
354 ape_ctx
->magic
[0],ape_ctx
->magic
[1],
355 ape_ctx
->magic
[2],ape_ctx
->magic
[3]);
356 printf("fileversion = %d\n",ape_ctx
->fileversion
);
357 printf("descriptorlength = %d\n",ape_ctx
->descriptorlength
);
358 printf("headerlength = %d\n",ape_ctx
->headerlength
);
359 printf("seektablelength = %d\n",ape_ctx
->seektablelength
);
360 printf("wavheaderlength = %d\n",ape_ctx
->wavheaderlength
);
361 printf("audiodatalength = %d\n",ape_ctx
->audiodatalength
);
362 printf("audiodatalength_high = %d\n",ape_ctx
->audiodatalength_high
);
363 printf("wavtaillength = %d\n",ape_ctx
->wavtaillength
);
365 for (i
= 0; i
< 16; i
++)
366 printf("%02x",ape_ctx
->md5
[i
]);
369 printf("\nHeader Block:\n\n");
371 printf("compressiontype = %d\n",ape_ctx
->compressiontype
);
372 printf("formatflags = %d\n",ape_ctx
->formatflags
);
373 printf("blocksperframe = %d\n",ape_ctx
->blocksperframe
);
374 printf("finalframeblocks = %d\n",ape_ctx
->finalframeblocks
);
375 printf("totalframes = %d\n",ape_ctx
->totalframes
);
376 printf("bps = %d\n",ape_ctx
->bps
);
377 printf("channels = %d\n",ape_ctx
->channels
);
378 printf("samplerate = %d\n",ape_ctx
->samplerate
);
380 printf("\nSeektable\n\n");
381 if ((ape_ctx
->seektablelength
/ sizeof(uint32_t)) != ape_ctx
->totalframes
)
383 printf("No seektable\n");
387 for ( i
= 0; i
< ape_ctx
->seektablelength
/ sizeof(uint32_t) ; i
++)
389 if (i
< ape_ctx
->totalframes
-1) {
390 printf("%8d %d (%d bytes)\n",i
,ape_ctx
->seektable
[i
],ape_ctx
->seektable
[i
+1]-ape_ctx
->seektable
[i
]);
392 printf("%8d %d\n",i
,ape_ctx
->seektable
[i
]);
396 printf("\nCalculated information:\n\n");
397 printf("junklength = %d\n",ape_ctx
->junklength
);
398 printf("firstframe = %d\n",ape_ctx
->firstframe
);
399 printf("totalsamples = %d\n",ape_ctx
->totalsamples
);
402 #endif /* !ROCKBOX */