1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 David Bryant
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
18 ****************************************************************************/
27 #include "metadata_common.h"
28 #include "metadata_parsers.h"
31 #define ID_UNIQUE 0x3f
33 #define ID_SAMPLE_RATE 0x27
38 static const long wavpack_sample_rates
[] =
40 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000,
41 32000, 44100, 48000, 64000, 88200, 96000, 192000
44 /* A simple parser to read basic information from a WavPack file. This
45 * now works with self-extrating WavPack files and also will scan the
46 * metadata for non-standard sampling rates. This no longer fails on
47 * WavPack files containing floating-point audio data because these are
48 * now converted to standard Rockbox format in the decoder.
51 bool get_wavpack_metadata(int fd
, struct mp3entry
* id3
)
53 /* Use the trackname part of the id3 structure as a temporary buffer */
54 unsigned char* buf
= (unsigned char *)id3
->path
;
55 uint32_t totalsamples
, blocksamples
, flags
;
58 for (i
= 0; i
< 256; ++i
) {
60 /* at every 256 bytes into file, try to read a WavPack header */
62 if ((lseek(fd
, i
* 256, SEEK_SET
) < 0) || (read(fd
, buf
, 32) < 32))
65 /* if valid WavPack 4 header version, break */
67 if (memcmp (buf
, "wvpk", 4) == 0 && buf
[9] == 4 &&
68 (buf
[8] >= 2 && buf
[8] <= 0x10))
73 logf ("Not a WavPack file");
77 id3
->vbr
= true; /* All WavPack files are VBR */
78 id3
->filesize
= filesize (fd
);
79 totalsamples
= get_long_le(&buf
[12]);
80 blocksamples
= get_long_le(&buf
[20]);
81 flags
= get_long_le(&buf
[24]);
84 int srindx
= ((buf
[26] >> 7) & 1) + ((buf
[27] << 1) & 14);
87 uint32_t meta_bytes
= buf
[4] + (buf
[5] << 8) + (buf
[6] << 16) - 24;
90 id3
->frequency
= 44100;
92 while (meta_bytes
>= 6) {
93 if (read(fd
, buf
, 2) < 2)
96 if (buf
[0] & ID_LARGE
) {
97 if (read(fd
, buf
+ 2, 2) < 2)
100 meta_size
= (buf
[1] << 1) + (buf
[2] << 9) + (buf
[3] << 17);
101 meta_bytes
-= meta_size
+ 4;
104 meta_size
= buf
[1] << 1;
105 meta_bytes
-= meta_size
+ 2;
107 if ((buf
[0] & ID_UNIQUE
) == ID_SAMPLE_RATE
) {
108 if (meta_size
== 4 && read(fd
, buf
+ 2, 4) == 4)
109 id3
->frequency
= buf
[2] + (buf
[3] << 8) + (buf
[4] << 16);
115 if (meta_size
> 0 && lseek(fd
, meta_size
, SEEK_CUR
) < 0)
120 id3
->frequency
= wavpack_sample_rates
[srindx
];
122 /* if the total number of samples is unknown, make a guess on the high side (for now) */
124 if (totalsamples
== (uint32_t) -1) {
125 totalsamples
= filesize (fd
) * 3;
127 if (!(flags
& HYBRID_FLAG
))
130 if (!(flags
& MONO_FLAG
))
134 id3
->length
= ((int64_t) totalsamples
* 1000) / id3
->frequency
;
135 id3
->bitrate
= filesize (fd
) / (id3
->length
/ 8);