diff options
Diffstat (limited to 'apps/metadata/wavpack.c')
-rw-r--r-- | apps/metadata/wavpack.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/apps/metadata/wavpack.c b/apps/metadata/wavpack.c new file mode 100644 index 0000000000..5d33c0dffd --- /dev/null +++ b/apps/metadata/wavpack.c | |||
@@ -0,0 +1,122 @@ | |||
1 | /*************************************************************************** | ||
2 | * __________ __ ___. | ||
3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ | ||
4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / | ||
5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < | ||
6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ | ||
7 | * \/ \/ \/ \/ \/ | ||
8 | * $Id:$ | ||
9 | * | ||
10 | * Copyright (C) 2007 David Bryant | ||
11 | * | ||
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. | ||
14 | * | ||
15 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY | ||
16 | * KIND, either express or implied. | ||
17 | * | ||
18 | ****************************************************************************/ | ||
19 | #include <stdio.h> | ||
20 | #include <string.h> | ||
21 | #include <stdlib.h> | ||
22 | #include <ctype.h> | ||
23 | #include <inttypes.h> | ||
24 | |||
25 | #include "system.h" | ||
26 | #include "id3.h" | ||
27 | #include "metadata_common.h" | ||
28 | #include "logf.h" | ||
29 | |||
30 | #define ID_UNIQUE 0x3f | ||
31 | #define ID_LARGE 0x80 | ||
32 | #define ID_SAMPLE_RATE 0x27 | ||
33 | |||
34 | static const long wavpack_sample_rates [] = | ||
35 | { | ||
36 | 6000, 8000, 9600, 11025, 12000, 16000, 22050, 24000, | ||
37 | 32000, 44100, 48000, 64000, 88200, 96000, 192000 | ||
38 | }; | ||
39 | |||
40 | /* A simple parser to read basic information from a WavPack file. This | ||
41 | * now works with self-extrating WavPack files and also will scan the | ||
42 | * metadata for non-standard sampling rates. This no longer fails on | ||
43 | * WavPack files containing floating-point audio data because these are | ||
44 | * now converted to standard Rockbox format in the decoder. | ||
45 | */ | ||
46 | |||
47 | bool get_wavpack_metadata(int fd, struct mp3entry* id3) | ||
48 | { | ||
49 | /* Use the trackname part of the id3 structure as a temporary buffer */ | ||
50 | unsigned char* buf = (unsigned char *)id3->path; | ||
51 | uint32_t totalsamples, blocksamples; | ||
52 | int i; | ||
53 | |||
54 | for (i = 0; i < 256; ++i) { | ||
55 | |||
56 | /* at every 256 bytes into file, try to read a WavPack header */ | ||
57 | |||
58 | if ((lseek(fd, i * 256, SEEK_SET) < 0) || (read(fd, buf, 32) < 32)) | ||
59 | return false; | ||
60 | |||
61 | /* if valid WavPack 4 header version, break */ | ||
62 | |||
63 | if (memcmp (buf, "wvpk", 4) == 0 && buf [9] == 4 && | ||
64 | (buf [8] >= 2 && buf [8] <= 0x10)) | ||
65 | break; | ||
66 | } | ||
67 | |||
68 | if (i == 256) { | ||
69 | logf ("Not a WavPack file"); | ||
70 | return false; | ||
71 | } | ||
72 | |||
73 | id3->vbr = true; /* All WavPack files are VBR */ | ||
74 | id3->filesize = filesize (fd); | ||
75 | totalsamples = get_long_le(&buf[12]); | ||
76 | blocksamples = get_long_le(&buf[20]); | ||
77 | |||
78 | if (blocksamples && totalsamples != (uint32_t) -1) { | ||
79 | int srindx = ((buf [26] >> 7) & 1) + ((buf [27] << 1) & 14); | ||
80 | |||
81 | if (srindx == 15) { | ||
82 | uint32_t meta_bytes = buf [4] + (buf [5] << 8) + (buf [6] << 16) - 24; | ||
83 | uint32_t meta_size; | ||
84 | |||
85 | id3->frequency = 44100; | ||
86 | |||
87 | while (meta_bytes >= 6) { | ||
88 | if (read(fd, buf, 2) < 2) | ||
89 | break; | ||
90 | |||
91 | if (buf [0] & ID_LARGE) { | ||
92 | if (read(fd, buf + 2, 2) < 2) | ||
93 | break; | ||
94 | |||
95 | meta_size = (buf [1] << 1) + (buf [2] << 9) + (buf [3] << 17); | ||
96 | meta_bytes -= meta_size + 4; | ||
97 | } | ||
98 | else { | ||
99 | meta_size = buf [1] << 1; | ||
100 | meta_bytes -= meta_size + 2; | ||
101 | |||
102 | if ((buf [0] & ID_UNIQUE) == ID_SAMPLE_RATE) { | ||
103 | if (meta_size == 4 && read(fd, buf + 2, 4) == 4) | ||
104 | id3->frequency = buf [2] + (buf [3] << 8) + (buf [4] << 16); | ||
105 | |||
106 | break; | ||
107 | } | ||
108 | } | ||
109 | |||
110 | if (meta_size > 0 && lseek(fd, meta_size, SEEK_CUR) < 0) | ||
111 | break; | ||
112 | } | ||
113 | } | ||
114 | else | ||
115 | id3->frequency = wavpack_sample_rates[srindx]; | ||
116 | |||
117 | id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; | ||
118 | id3->bitrate = filesize (fd) / (id3->length / 8); | ||
119 | } | ||
120 | |||
121 | return true; | ||
122 | } | ||