diff options
Diffstat (limited to 'apps/metadata/wavpack.c')
-rw-r--r-- | apps/metadata/wavpack.c | 108 |
1 files changed, 65 insertions, 43 deletions
diff --git a/apps/metadata/wavpack.c b/apps/metadata/wavpack.c index bb181b8d3f..7d19435543 100644 --- a/apps/metadata/wavpack.c +++ b/apps/metadata/wavpack.c | |||
@@ -47,14 +47,16 @@ static const long wavpack_sample_rates [] = | |||
47 | * now works with self-extrating WavPack files and also will scan the | 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 | 48 | * metadata for non-standard sampling rates. This no longer fails on |
49 | * WavPack files containing floating-point audio data because these are | 49 | * WavPack files containing floating-point audio data because these are |
50 | * now converted to standard Rockbox format in the decoder. | 50 | * now converted to standard Rockbox format in the decoder, and also |
51 | * handles the case where up to 15 non-audio blocks might occur at the | ||
52 | * beginning of the file. | ||
51 | */ | 53 | */ |
52 | 54 | ||
53 | bool get_wavpack_metadata(int fd, struct mp3entry* id3) | 55 | bool get_wavpack_metadata(int fd, struct mp3entry* id3) |
54 | { | 56 | { |
55 | /* Use the trackname part of the id3 structure as a temporary buffer */ | 57 | /* Use the trackname part of the id3 structure as a temporary buffer */ |
56 | unsigned char* buf = (unsigned char *)id3->path; | 58 | unsigned char* buf = (unsigned char *)id3->path; |
57 | uint32_t totalsamples, blocksamples, flags; | 59 | uint32_t totalsamples = (uint32_t) -1; |
58 | int i; | 60 | int i; |
59 | 61 | ||
60 | for (i = 0; i < 256; ++i) { | 62 | for (i = 0; i < 256; ++i) { |
@@ -78,66 +80,86 @@ bool get_wavpack_metadata(int fd, struct mp3entry* id3) | |||
78 | 80 | ||
79 | id3->vbr = true; /* All WavPack files are VBR */ | 81 | id3->vbr = true; /* All WavPack files are VBR */ |
80 | id3->filesize = filesize (fd); | 82 | 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]); | ||
84 | 83 | ||
85 | if (blocksamples) { | 84 | /* check up to 16 headers before we give up finding one with audio */ |
86 | int srindx = ((buf [26] >> 7) & 1) + ((buf [27] << 1) & 14); | ||
87 | 85 | ||
88 | if (srindx == 15) { | 86 | for (i = 0; i < 16; ++i) { |
89 | uint32_t meta_bytes = buf [4] + (buf [5] << 8) + (buf [6] << 16) - 24; | 87 | uint32_t trial_totalsamples = get_long_le(&buf[12]); |
90 | uint32_t meta_size; | 88 | uint32_t blockindex = get_long_le(&buf[16]); |
89 | uint32_t blocksamples = get_long_le(&buf[20]); | ||
90 | uint32_t flags = get_long_le(&buf[24]); | ||
91 | 91 | ||
92 | id3->frequency = 44100; | 92 | if (totalsamples == (uint32_t) -1 && trial_totalsamples != (uint32_t) -1 && blockindex == 0) |
93 | totalsamples = trial_totalsamples; | ||
93 | 94 | ||
94 | while (meta_bytes >= 6) { | 95 | if (blocksamples) { |
95 | if (read(fd, buf, 2) < 2) | 96 | int srindx = ((buf [26] >> 7) & 1) + ((buf [27] << 1) & 14); |
96 | break; | 97 | |
98 | if (srindx == 15) { | ||
99 | uint32_t meta_bytes = buf [4] + (buf [5] << 8) + (buf [6] << 16) - 24; | ||
100 | uint32_t meta_size; | ||
97 | 101 | ||
98 | if (buf [0] & ID_LARGE) { | 102 | id3->frequency = 44100; |
99 | if (read(fd, buf + 2, 2) < 2) | 103 | |
104 | while (meta_bytes >= 6) { | ||
105 | if (read(fd, buf, 2) < 2) | ||
100 | break; | 106 | break; |
101 | 107 | ||
102 | meta_size = (buf [1] << 1) + (buf [2] << 9) + (buf [3] << 17); | 108 | if (buf [0] & ID_LARGE) { |
103 | meta_bytes -= meta_size + 4; | 109 | if (read(fd, buf + 2, 2) < 2) |
104 | } | 110 | break; |
105 | else { | ||
106 | meta_size = buf [1] << 1; | ||
107 | meta_bytes -= meta_size + 2; | ||
108 | 111 | ||
109 | if ((buf [0] & ID_UNIQUE) == ID_SAMPLE_RATE) { | 112 | meta_size = (buf [1] << 1) + (buf [2] << 9) + (buf [3] << 17); |
110 | if (meta_size == 4 && read(fd, buf + 2, 4) == 4) | 113 | meta_bytes -= meta_size + 4; |
111 | id3->frequency = buf [2] + (buf [3] << 8) + (buf [4] << 16); | 114 | } |
115 | else { | ||
116 | meta_size = buf [1] << 1; | ||
117 | meta_bytes -= meta_size + 2; | ||
112 | 118 | ||
113 | break; | 119 | if ((buf [0] & ID_UNIQUE) == ID_SAMPLE_RATE) { |
120 | if (meta_size == 4 && read(fd, buf + 2, 4) == 4) | ||
121 | id3->frequency = buf [2] + (buf [3] << 8) + (buf [4] << 16); | ||
122 | |||
123 | break; | ||
124 | } | ||
114 | } | 125 | } |
115 | } | ||
116 | 126 | ||
117 | if (meta_size > 0 && lseek(fd, meta_size, SEEK_CUR) < 0) | 127 | if (meta_size > 0 && lseek(fd, meta_size, SEEK_CUR) < 0) |
118 | break; | 128 | break; |
129 | } | ||
119 | } | 130 | } |
120 | } | 131 | else |
121 | else | 132 | id3->frequency = wavpack_sample_rates[srindx]; |
122 | id3->frequency = wavpack_sample_rates[srindx]; | 133 | |
134 | /* if the total number of samples is still unknown, make a guess on the high side (for now) */ | ||
135 | |||
136 | if (totalsamples == (uint32_t) -1) { | ||
137 | totalsamples = filesize (fd) * 3; | ||
123 | 138 | ||
124 | /* if the total number of samples is unknown, make a guess on the high side (for now) */ | 139 | if (!(flags & HYBRID_FLAG)) |
140 | totalsamples /= 2; | ||
125 | 141 | ||
126 | if (totalsamples == (uint32_t) -1) { | 142 | if (!(flags & MONO_FLAG)) |
127 | totalsamples = filesize (fd) * 3; | 143 | totalsamples /= 2; |
144 | } | ||
128 | 145 | ||
129 | if (!(flags & HYBRID_FLAG)) | 146 | id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; |
130 | totalsamples /= 2; | 147 | id3->bitrate = filesize (fd) / (id3->length / 8); |
131 | 148 | ||
132 | if (!(flags & MONO_FLAG)) | 149 | read_ape_tags(fd, id3); |
133 | totalsamples /= 2; | 150 | return true; |
134 | } | 151 | } |
152 | else { /* block did not contain audio, so seek to the end and see if there's another */ | ||
153 | uint32_t meta_bytes = buf [4] + (buf [5] << 8) + (buf [6] << 16) - 24; | ||
135 | 154 | ||
136 | id3->length = ((int64_t) totalsamples * 1000) / id3->frequency; | 155 | if ((meta_bytes > 0 && lseek(fd, meta_bytes, SEEK_CUR) < 0) || |
137 | id3->bitrate = filesize (fd) / (id3->length / 8); | 156 | read(fd, buf, 32) < 32) |
157 | break; | ||
138 | 158 | ||
139 | read_ape_tags(fd, id3); | 159 | if (memcmp (buf, "wvpk", 4) != 0 || buf [9] != 4 || |
140 | return true; | 160 | buf [8] < 2 || buf [8] > 0x10) |
161 | break; | ||
162 | } | ||
141 | } | 163 | } |
142 | 164 | ||
143 | return false; | 165 | return false; |