diff options
-rw-r--r-- | apps/codecs/libwavpack/metadata.c | 9 | ||||
-rw-r--r-- | apps/codecs/libwavpack/wavpack.h | 1 | ||||
-rw-r--r-- | apps/codecs/libwavpack/wputils.c | 4 | ||||
-rw-r--r-- | apps/metadata/wavpack.c | 108 |
4 files changed, 77 insertions, 45 deletions
diff --git a/apps/codecs/libwavpack/metadata.c b/apps/codecs/libwavpack/metadata.c index c944093b19..4dce10100f 100644 --- a/apps/codecs/libwavpack/metadata.c +++ b/apps/codecs/libwavpack/metadata.c | |||
@@ -19,15 +19,16 @@ int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd) | |||
19 | uint32_t bytes_to_read; | 19 | uint32_t bytes_to_read; |
20 | uchar tchar; | 20 | uchar tchar; |
21 | 21 | ||
22 | if (!wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1)) | 22 | if (wpc->stream.block_bytes_left < 2 || !wpc->infile (&wpmd->id, 1) || !wpc->infile (&tchar, 1)) |
23 | return FALSE; | 23 | return FALSE; |
24 | 24 | ||
25 | wpmd->byte_length = tchar << 1; | 25 | wpmd->byte_length = tchar << 1; |
26 | wpc->stream.block_bytes_left -= 2; | ||
26 | 27 | ||
27 | if (wpmd->id & ID_LARGE) { | 28 | if (wpmd->id & ID_LARGE) { |
28 | wpmd->id &= ~ID_LARGE; | 29 | wpmd->id &= ~ID_LARGE; |
29 | 30 | ||
30 | if (!wpc->infile (&tchar, 1)) | 31 | if (wpc->stream.block_bytes_left < 2 || !wpc->infile (&tchar, 1)) |
31 | return FALSE; | 32 | return FALSE; |
32 | 33 | ||
33 | wpmd->byte_length += (int32_t) tchar << 9; | 34 | wpmd->byte_length += (int32_t) tchar << 9; |
@@ -36,8 +37,12 @@ int read_metadata_buff (WavpackContext *wpc, WavpackMetadata *wpmd) | |||
36 | return FALSE; | 37 | return FALSE; |
37 | 38 | ||
38 | wpmd->byte_length += (int32_t) tchar << 17; | 39 | wpmd->byte_length += (int32_t) tchar << 17; |
40 | wpc->stream.block_bytes_left -= 2; | ||
39 | } | 41 | } |
40 | 42 | ||
43 | if ((wpc->stream.block_bytes_left -= wpmd->byte_length) < 0) | ||
44 | return FALSE; | ||
45 | |||
41 | if (wpmd->id & ID_ODD_SIZE) { | 46 | if (wpmd->id & ID_ODD_SIZE) { |
42 | wpmd->id &= ~ID_ODD_SIZE; | 47 | wpmd->id &= ~ID_ODD_SIZE; |
43 | wpmd->byte_length--; | 48 | wpmd->byte_length--; |
diff --git a/apps/codecs/libwavpack/wavpack.h b/apps/codecs/libwavpack/wavpack.h index ee7c969b4c..b15a176f33 100644 --- a/apps/codecs/libwavpack/wavpack.h +++ b/apps/codecs/libwavpack/wavpack.h | |||
@@ -205,6 +205,7 @@ typedef struct { | |||
205 | 205 | ||
206 | int num_terms, mute_error; | 206 | int num_terms, mute_error; |
207 | uint32_t sample_index, crc; | 207 | uint32_t sample_index, crc; |
208 | int32_t block_bytes_left; | ||
208 | 209 | ||
209 | uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups; | 210 | uchar int32_sent_bits, int32_zeros, int32_ones, int32_dups; |
210 | uchar float_flags, float_shift, float_max_exp, float_norm_exp; | 211 | uchar float_flags, float_shift, float_max_exp, float_norm_exp; |
diff --git a/apps/codecs/libwavpack/wputils.c b/apps/codecs/libwavpack/wputils.c index 7fabc7ab34..b0ccd3ba83 100644 --- a/apps/codecs/libwavpack/wputils.c +++ b/apps/codecs/libwavpack/wputils.c | |||
@@ -69,6 +69,8 @@ WavpackContext *WavpackOpenFileInput (read_stream infile, char *error) | |||
69 | return NULL; | 69 | return NULL; |
70 | } | 70 | } |
71 | 71 | ||
72 | wps->block_bytes_left = wps->wphdr.ckSize - 24; | ||
73 | |||
72 | if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < MIN_STREAM_VERS || | 74 | if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < MIN_STREAM_VERS || |
73 | wps->wphdr.version > MAX_STREAM_VERS) { | 75 | wps->wphdr.version > MAX_STREAM_VERS) { |
74 | strcpy_loc (error, "invalid WavPack file!"); | 76 | strcpy_loc (error, "invalid WavPack file!"); |
@@ -171,6 +173,8 @@ uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t sa | |||
171 | if (bcount == (uint32_t) -1) | 173 | if (bcount == (uint32_t) -1) |
172 | break; | 174 | break; |
173 | 175 | ||
176 | wps->block_bytes_left = wps->wphdr.ckSize - 24; | ||
177 | |||
174 | if (wps->wphdr.version < MIN_STREAM_VERS || wps->wphdr.version > MAX_STREAM_VERS) { | 178 | if (wps->wphdr.version < MIN_STREAM_VERS || wps->wphdr.version > MAX_STREAM_VERS) { |
175 | strcpy_loc (wpc->error_message, "invalid WavPack file!"); | 179 | strcpy_loc (wpc->error_message, "invalid WavPack file!"); |
176 | break; | 180 | break; |
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; |