1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 David Bryant
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
29 #include "metadata_common.h"
30 #include "metadata_parsers.h"
33 #define ID_UNIQUE 0x3f
35 #define ID_SAMPLE_RATE 0x27
40 static const long wavpack_sample_rates
[] =
42 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
43 32000, 44100, 48000, 64000, 88200, 96000, 192000
46 /* A simple parser to read basic information from a WavPack file. This
47 * now works with self-extrating WavPack files and also will scan the
48 * metadata for non-standard sampling rates. This no longer fails on
49 * WavPack files containing floating-point audio data because these are
50 * now converted to standard Rockbox format in the decoder.
53 bool get_wavpack_metadata(int fd
, struct mp3entry
* id3
)
55 /* Use the trackname part of the id3 structure as a temporary buffer */
56 unsigned char* buf
= (unsigned char *)id3
->path
;
57 uint32_t totalsamples
, blocksamples
, flags
;
60 for (i
= 0; i
< 256; ++i
) {
62 /* at every 256 bytes into file, try to read a WavPack header */
64 if ((lseek(fd
, i
* 256, SEEK_SET
) < 0) || (read(fd
, buf
, 32) < 32))
67 /* if valid WavPack 4 header version, break */
69 if (memcmp (buf
, "wvpk", 4) == 0 && buf
[9] == 4 &&
70 (buf
[8] >= 2 && buf
[8] <= 0x10))
75 logf ("Not a WavPack file");
79 id3
->vbr
= true; /* All WavPack files are VBR */
80 id3
->filesize
= filesize (fd
);
81 totalsamples
= get_long_le(&buf
[12]);
82 blocksamples
= get_long_le(&buf
[20]);
83 flags
= get_long_le(&buf
[24]);
86 int srindx
= ((buf
[26] >> 7) & 1) + ((buf
[27] << 1) & 14);
89 uint32_t meta_bytes
= buf
[4] + (buf
[5] << 8) + (buf
[6] << 16) - 24;
92 id3
->frequency
= 44100;
94 while (meta_bytes
>= 6) {
95 if (read(fd
, buf
, 2) < 2)
98 if (buf
[0] & ID_LARGE
) {
99 if (read(fd
, buf
+ 2, 2) < 2)
102 meta_size
= (buf
[1] << 1) + (buf
[2] << 9) + (buf
[3] << 17);
103 meta_bytes
-= meta_size
+ 4;
106 meta_size
= buf
[1] << 1;
107 meta_bytes
-= meta_size
+ 2;
109 if ((buf
[0] & ID_UNIQUE
) == ID_SAMPLE_RATE
) {
110 if (meta_size
== 4 && read(fd
, buf
+ 2, 4) == 4)
111 id3
->frequency
= buf
[2] + (buf
[3] << 8) + (buf
[4] << 16);
117 if (meta_size
> 0 && lseek(fd
, meta_size
, SEEK_CUR
) < 0)
122 id3
->frequency
= wavpack_sample_rates
[srindx
];
124 /* if the total number of samples is unknown, make a guess on the high side (for now) */
126 if (totalsamples
== (uint32_t) -1) {
127 totalsamples
= filesize (fd
) * 3;
129 if (!(flags
& HYBRID_FLAG
))
132 if (!(flags
& MONO_FLAG
))
136 id3
->length
= ((int64_t) totalsamples
* 1000) / id3
->frequency
;
137 id3
->bitrate
= filesize (fd
) / (id3
->length
/ 8);