1 ////////////////////////////////////////////////////////////////////////////
2 // **** WAVPACK **** //
3 // Hybrid Lossless Wavefile Compressor //
4 // Copyright (c) 1998 - 2019 David Bryant. //
5 // All Rights Reserved. //
6 // Distributed under the BSD Software License (see license.txt) //
7 ////////////////////////////////////////////////////////////////////////////
8
9 // open_utils.c
10
11 // This module provides all the code required to open an existing WavPack file
12 // for reading by using a reader callback mechanism (NOT a filename). This
13 // includes the code required to find and parse WavPack blocks, process any
14 // included metadata, and queue up the bitstreams containing the encoded audio
15 // data. It does not the actual code to unpack audio data and this was done so
16 // that programs that just want to query WavPack files for information (like,
17 // for example, taggers) don't need to link in a lot of unnecessary code.
18
19 #include <stdlib.h>
20 #include <string.h>
21
22 #include "wavpack_local.h"
23
24 // This function is identical to WavpackOpenFileInput() except that instead
25 // of providing a filename to open, the caller provides a pointer to a set of
26 // reader callbacks and instances of up to two streams. The first of these
27 // streams is required and contains the regular WavPack data stream; the second
28 // contains the "correction" file if desired. Unlike the standard open
29 // function which handles the correction file transparently, in this case it
30 // is the responsibility of the caller to be aware of correction files.
31
32 static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int get_wrapper);
33
WavpackOpenFileInputEx64(WavpackStreamReader64 * reader,void * wv_id,void * wvc_id,char * error,int flags,int norm_offset)34 WavpackContext *WavpackOpenFileInputEx64 (WavpackStreamReader64 *reader, void *wv_id, void *wvc_id, char *error, int flags, int norm_offset)
35 {
36 WavpackContext *wpc = (WavpackContext *)malloc (sizeof (WavpackContext));
37 WavpackStream *wps;
38 int num_blocks = 0;
39 unsigned char first_byte;
40 uint32_t bcount;
41
42 if (!wpc) {
43 if (error) strcpy (error, "can't allocate memory");
44 return NULL;
45 }
46
47 CLEAR (*wpc);
48 wpc->wv_in = wv_id;
49 wpc->wvc_in = wvc_id;
50 wpc->reader = reader;
51 wpc->total_samples = -1;
52 wpc->norm_offset = norm_offset;
53 wpc->max_streams = OLD_MAX_STREAMS; // use this until overwritten with actual number
54 wpc->open_flags = flags;
55
56 wpc->filelen = wpc->reader->get_length (wpc->wv_in);
57
58 #ifndef NO_TAGS
59 if ((flags & (OPEN_TAGS | OPEN_EDIT_TAGS)) && wpc->reader->can_seek (wpc->wv_in)) {
60 load_tag (wpc);
61 wpc->reader->set_pos_abs (wpc->wv_in, 0);
62
63 if ((flags & OPEN_EDIT_TAGS) && !editable_tag (&wpc->m_tag)) {
64 if (error) strcpy (error, "can't edit tags located at the beginning of files!");
65 return WavpackCloseFile (wpc);
66 }
67 }
68 #endif
69
70 if (wpc->reader->read_bytes (wpc->wv_in, &first_byte, 1) != 1) {
71 if (error) strcpy (error, "can't read all of WavPack file!");
72 return WavpackCloseFile (wpc);
73 }
74
75 wpc->reader->push_back_byte (wpc->wv_in, first_byte);
76
77 if (first_byte == 'R') {
78 #ifdef ENABLE_LEGACY
79 return open_file3 (wpc, error);
80 #else
81 if (error) strcpy (error, "this legacy WavPack file is deprecated, use version 4.80.0 to transcode");
82 return WavpackCloseFile (wpc);
83 #endif
84 }
85
86 wpc->streams = (WavpackStream **)(malloc ((wpc->num_streams = 1) * sizeof (wpc->streams [0])));
87 if (!wpc->streams) {
88 if (error) strcpy (error, "can't allocate memory");
89 return WavpackCloseFile (wpc);
90 }
91
92 wpc->streams [0] = wps = (WavpackStream *)malloc (sizeof (WavpackStream));
93 if (!wps) {
94 if (error) strcpy (error, "can't allocate memory");
95 return WavpackCloseFile (wpc);
96 }
97 CLEAR (*wps);
98
99 while (!wps->wphdr.block_samples) {
100
101 wpc->filepos = wpc->reader->get_pos (wpc->wv_in);
102 bcount = read_next_header (wpc->reader, wpc->wv_in, &wps->wphdr);
103
104 if (bcount == (uint32_t) -1 ||
105 (!wps->wphdr.block_samples && num_blocks++ > 16)) {
106 if (error) strcpy (error, "not compatible with this version of WavPack file!");
107 return WavpackCloseFile (wpc);
108 }
109
110 wpc->filepos += bcount;
111 wps->blockbuff = (unsigned char *)malloc (wps->wphdr.ckSize + 8);
112 if (!wps->blockbuff) {
113 if (error) strcpy (error, "can't allocate memory");
114 return WavpackCloseFile (wpc);
115 }
116 memcpy (wps->blockbuff, &wps->wphdr, 32);
117
118 if (wpc->reader->read_bytes (wpc->wv_in, wps->blockbuff + 32, wps->wphdr.ckSize - 24) != wps->wphdr.ckSize - 24) {
119 if (error) strcpy (error, "can't read all of WavPack file!");
120 return WavpackCloseFile (wpc);
121 }
122
123 // if block does not verify, flag error, free buffer, and continue
124 if (!WavpackVerifySingleBlock (wps->blockbuff, !(flags & OPEN_NO_CHECKSUM))) {
125 wps->wphdr.block_samples = 0;
126 free (wps->blockbuff);
127 wps->blockbuff = NULL;
128 wpc->crc_errors++;
129 continue;
130 }
131
132 wps->init_done = FALSE;
133
134 if (wps->wphdr.block_samples) {
135 if (flags & OPEN_STREAMING)
136 SET_BLOCK_INDEX (wps->wphdr, 0);
137 else if (wpc->total_samples == -1) {
138 if (GET_BLOCK_INDEX (wps->wphdr) || GET_TOTAL_SAMPLES (wps->wphdr) == -1) {
139 wpc->initial_index = GET_BLOCK_INDEX (wps->wphdr);
140 SET_BLOCK_INDEX (wps->wphdr, 0);
141
142 if (wpc->reader->can_seek (wpc->wv_in)) {
143 int64_t final_index = -1;
144
145 seek_eof_information (wpc, &final_index, FALSE);
146
147 if (final_index != -1)
148 wpc->total_samples = final_index - wpc->initial_index;
149 }
150 }
151 else
152 wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
153 }
154 }
155 else if (wpc->total_samples == -1 && !GET_BLOCK_INDEX (wps->wphdr) && GET_TOTAL_SAMPLES (wps->wphdr))
156 wpc->total_samples = GET_TOTAL_SAMPLES (wps->wphdr);
157
158 if (wpc->wvc_in && wps->wphdr.block_samples && (wps->wphdr.flags & HYBRID_FLAG)) {
159 unsigned char ch;
160
161 if (wpc->reader->read_bytes (wpc->wvc_in, &ch, 1) == 1) {
162 wpc->reader->push_back_byte (wpc->wvc_in, ch);
163 wpc->file2len = wpc->reader->get_length (wpc->wvc_in);
164 wpc->wvc_flag = TRUE;
165 }
166 }
167
168 if (wpc->wvc_flag && !read_wvc_block (wpc)) {
169 if (error) strcpy (error, "not compatible with this version of correction file!");
170 return WavpackCloseFile (wpc);
171 }
172
173 if (!wps->init_done && !unpack_init (wpc)) {
174 if (error) strcpy (error, wpc->error_message [0] ? wpc->error_message :
175 "not compatible with this version of WavPack file!");
176
177 return WavpackCloseFile (wpc);
178 }
179
180 if (!wps->wphdr.block_samples) { // free blockbuff if we're going to loop again
181 free (wps->blockbuff);
182 wps->blockbuff = NULL;
183 }
184
185 wps->init_done = TRUE;
186 }
187
188 wpc->config.flags &= ~0xff;
189 wpc->config.flags |= wps->wphdr.flags & 0xff;
190
191 if (!wpc->config.num_channels) {
192 wpc->config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
193 wpc->config.channel_mask = 0x5 - wpc->config.num_channels;
194 }
195
196 if ((flags & OPEN_2CH_MAX) && !(wps->wphdr.flags & FINAL_BLOCK))
197 wpc->reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2;
198
199 if (wps->wphdr.flags & DSD_FLAG) {
200 #ifdef ENABLE_DSD
201 if (flags & OPEN_DSD_NATIVE) {
202 wpc->config.bytes_per_sample = 1;
203 wpc->config.bits_per_sample = 8;
204 }
205 else if (flags & OPEN_DSD_AS_PCM) {
206 wpc->decimation_context = decimate_dsd_init (wpc->reduced_channels ?
207 wpc->reduced_channels : wpc->config.num_channels);
208
209 wpc->config.bytes_per_sample = 3;
210 wpc->config.bits_per_sample = 24;
211 }
212 else {
213 if (error) strcpy (error, "not configured to handle DSD WavPack files!");
214 return WavpackCloseFile (wpc);
215 }
216 #else
217 if (error) strcpy (error, "not configured to handle DSD WavPack files!");
218 return WavpackCloseFile (wpc);
219 #endif
220 }
221 else {
222 wpc->config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1;
223 wpc->config.float_norm_exp = wps->float_norm_exp;
224
225 wpc->config.bits_per_sample = (wpc->config.bytes_per_sample * 8) -
226 ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB);
227 }
228
229 if (!wpc->config.sample_rate) {
230 if (!wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK)
231 wpc->config.sample_rate = 44100;
232 else
233 wpc->config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB];
234 }
235
236 return wpc;
237 }
238
239 // This function returns the major version number of the WavPack program
240 // (or library) that created the open file. Currently, this can be 1 to 5.
241 // Minor versions are not recorded in WavPack files.
242
WavpackGetVersion(WavpackContext * wpc)243 int WavpackGetVersion (WavpackContext *wpc)
244 {
245 if (wpc) {
246 #ifdef ENABLE_LEGACY
247 if (wpc->stream3)
248 return get_version3 (wpc);
249 #endif
250 return wpc->version_five ? 5 : 4;
251 }
252
253 return 0;
254 }
255
256 // Return the file format specified in the call to WavpackSetFileInformation()
257 // when the file was created. For all files created prior to WavPack 5.0 this
258 // will 0 (WP_FORMAT_WAV).
259
WavpackGetFileFormat(WavpackContext * wpc)260 unsigned char WavpackGetFileFormat (WavpackContext *wpc)
261 {
262 return wpc->file_format;
263 }
264
265 // Return a string representing the recommended file extension for the open
266 // WavPack file. For all files created prior to WavPack 5.0 this will be "wav",
267 // even for raw files with no RIFF into. This string is specified in the
268 // call to WavpackSetFileInformation() when the file was created.
269
WavpackGetFileExtension(WavpackContext * wpc)270 char *WavpackGetFileExtension (WavpackContext *wpc)
271 {
272 if (wpc && wpc->file_extension [0])
273 return wpc->file_extension;
274 else
275 return "wav";
276 }
277
278 // This function initializes everything required to unpack a WavPack block
279 // and must be called before unpack_samples() is called to obtain audio data.
280 // It is assumed that the WavpackHeader has been read into the wps->wphdr
281 // (in the current WavpackStream) and that the entire block has been read at
282 // wps->blockbuff. If a correction file is available (wpc->wvc_flag = TRUE)
283 // then the corresponding correction block must be read into wps->block2buff
284 // and its WavpackHeader has overwritten the header at wps->wphdr. This is
285 // where all the metadata blocks are scanned including those that contain
286 // bitstream data.
287
288 static int read_metadata_buff (WavpackMetadata *wpmd, unsigned char *blockbuff, unsigned char **buffptr);
289 static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd);
290 static void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end);
291
unpack_init(WavpackContext * wpc)292 int unpack_init (WavpackContext *wpc)
293 {
294 WavpackStream *wps = wpc->streams [wpc->current_stream];
295 unsigned char *blockptr, *block2ptr;
296 WavpackMetadata wpmd;
297
298 wps->num_terms = 0;
299 wps->mute_error = FALSE;
300 wps->crc = wps->crc_x = 0xffffffff;
301 wps->dsd.ready = 0;
302 CLEAR (wps->wvbits);
303 CLEAR (wps->wvcbits);
304 CLEAR (wps->wvxbits);
305 CLEAR (wps->decorr_passes);
306 CLEAR (wps->dc);
307 CLEAR (wps->w);
308
309 if (!(wps->wphdr.flags & MONO_FLAG) && wpc->config.num_channels && wps->wphdr.block_samples &&
310 (wpc->reduced_channels == 1 || wpc->config.num_channels == 1)) {
311 wps->mute_error = TRUE;
312 return FALSE;
313 }
314
315 if ((wps->wphdr.flags & UNKNOWN_FLAGS) || (wps->wphdr.flags & MONO_DATA) == MONO_DATA) {
316 wps->mute_error = TRUE;
317 return FALSE;
318 }
319
320 blockptr = wps->blockbuff + sizeof (WavpackHeader);
321
322 while (read_metadata_buff (&wpmd, wps->blockbuff, &blockptr))
323 if (!process_metadata (wpc, &wpmd)) {
324 wps->mute_error = TRUE;
325 return FALSE;
326 }
327
328 if (wps->wphdr.block_samples && wpc->wvc_flag && wps->block2buff) {
329 block2ptr = wps->block2buff + sizeof (WavpackHeader);
330
331 while (read_metadata_buff (&wpmd, wps->block2buff, &block2ptr))
332 if (!process_metadata (wpc, &wpmd)) {
333 wps->mute_error = TRUE;
334 return FALSE;
335 }
336 }
337
338 if (wps->wphdr.block_samples && ((wps->wphdr.flags & DSD_FLAG) ? !wps->dsd.ready : !bs_is_open (&wps->wvbits))) {
339 if (bs_is_open (&wps->wvcbits))
340 strcpy (wpc->error_message, "can't unpack correction files alone!");
341
342 wps->mute_error = TRUE;
343 return FALSE;
344 }
345
346 if (wps->wphdr.block_samples && !bs_is_open (&wps->wvxbits)) {
347 if ((wps->wphdr.flags & INT32_DATA) && wps->int32_sent_bits)
348 wpc->lossy_blocks = TRUE;
349
350 if ((wps->wphdr.flags & FLOAT_DATA) &&
351 wps->float_flags & (FLOAT_EXCEPTIONS | FLOAT_ZEROS_SENT | FLOAT_SHIFT_SENT | FLOAT_SHIFT_SAME))
352 wpc->lossy_blocks = TRUE;
353 }
354
355 if (wps->wphdr.block_samples)
356 wps->sample_index = GET_BLOCK_INDEX (wps->wphdr);
357
358 return TRUE;
359 }
360
361 //////////////////////////////// matadata handlers ///////////////////////////////
362
363 // These functions handle specific metadata types and are called directly
364 // during WavPack block parsing by process_metadata() at the bottom.
365
366 // This function initializes the main bitstream for audio samples, which must
367 // be in the "wv" file.
368
init_wv_bitstream(WavpackStream * wps,WavpackMetadata * wpmd)369 static int init_wv_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
370 {
371 if (!wpmd->byte_length || (wpmd->byte_length & 1))
372 return FALSE;
373
374 bs_open_read (&wps->wvbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length);
375 return TRUE;
376 }
377
378 // This function initializes the "correction" bitstream for audio samples,
379 // which currently must be in the "wvc" file.
380
init_wvc_bitstream(WavpackStream * wps,WavpackMetadata * wpmd)381 static int init_wvc_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
382 {
383 if (!wpmd->byte_length || (wpmd->byte_length & 1))
384 return FALSE;
385
386 bs_open_read (&wps->wvcbits, wpmd->data, (unsigned char *) wpmd->data + wpmd->byte_length);
387 return TRUE;
388 }
389
390 // This function initializes the "extra" bitstream for audio samples which
391 // contains the information required to losslessly decompress 32-bit float data
392 // or integer data that exceeds 24 bits. This bitstream is in the "wv" file
393 // for pure lossless data or the "wvc" file for hybrid lossless. This data
394 // would not be used for hybrid lossy mode. There is also a 32-bit CRC stored
395 // in the first 4 bytes of these blocks.
396
init_wvx_bitstream(WavpackStream * wps,WavpackMetadata * wpmd)397 static int init_wvx_bitstream (WavpackStream *wps, WavpackMetadata *wpmd)
398 {
399 unsigned char *cp = (unsigned char *)wpmd->data;
400
401 if (wpmd->byte_length <= 4 || (wpmd->byte_length & 1))
402 return FALSE;
403
404 wps->crc_wvx = *cp++;
405 wps->crc_wvx |= (uint32_t) *cp++ << 8;
406 wps->crc_wvx |= (uint32_t) *cp++ << 16;
407 wps->crc_wvx |= (uint32_t) *cp++ << 24;
408
409 bs_open_read (&wps->wvxbits, cp, (unsigned char *) wpmd->data + wpmd->byte_length);
410 return TRUE;
411 }
412
413 // Read the int32 data from the specified metadata into the specified stream.
414 // This data is used for integer data that has more than 24 bits of magnitude
415 // or, in some cases, used to eliminate redundant bits from any audio stream.
416
read_int32_info(WavpackStream * wps,WavpackMetadata * wpmd)417 static int read_int32_info (WavpackStream *wps, WavpackMetadata *wpmd)
418 {
419 int bytecnt = wpmd->byte_length;
420 char *byteptr = (char *)wpmd->data;
421
422 if (bytecnt != 4)
423 return FALSE;
424
425 wps->int32_sent_bits = *byteptr++;
426 wps->int32_zeros = *byteptr++;
427 wps->int32_ones = *byteptr++;
428 wps->int32_dups = *byteptr;
429
430 return TRUE;
431 }
432
read_float_info(WavpackStream * wps,WavpackMetadata * wpmd)433 static int read_float_info (WavpackStream *wps, WavpackMetadata *wpmd)
434 {
435 int bytecnt = wpmd->byte_length;
436 char *byteptr = (char *)wpmd->data;
437
438 if (bytecnt != 4)
439 return FALSE;
440
441 wps->float_flags = *byteptr++;
442 wps->float_shift = *byteptr++;
443 wps->float_max_exp = *byteptr++;
444 wps->float_norm_exp = *byteptr;
445 return TRUE;
446 }
447
448 // Read multichannel information from metadata. The first byte is the total
449 // number of channels and the following bytes represent the channel_mask
450 // as described for Microsoft WAVEFORMATEX.
451
read_channel_info(WavpackContext * wpc,WavpackMetadata * wpmd)452 static int read_channel_info (WavpackContext *wpc, WavpackMetadata *wpmd)
453 {
454 int bytecnt = wpmd->byte_length, shift = 0, mask_bits;
455 unsigned char *byteptr = (unsigned char *)wpmd->data;
456 uint32_t mask = 0;
457
458 if (!bytecnt || bytecnt > 7)
459 return FALSE;
460
461 if (!wpc->config.num_channels) {
462
463 // if bytecnt is 6 or 7 we are using new configuration with "unlimited" streams
464
465 if (bytecnt >= 6) {
466 wpc->config.num_channels = (byteptr [0] | ((byteptr [2] & 0xf) << 8)) + 1;
467 wpc->max_streams = (byteptr [1] | ((byteptr [2] & 0xf0) << 4)) + 1;
468
469 if (wpc->config.num_channels < wpc->max_streams)
470 return FALSE;
471
472 byteptr += 3;
473 mask = *byteptr++;
474 mask |= (uint32_t) *byteptr++ << 8;
475 mask |= (uint32_t) *byteptr++ << 16;
476
477 if (bytecnt == 7) // this was introduced in 5.0
478 mask |= (uint32_t) *byteptr << 24;
479 }
480 else {
481 wpc->config.num_channels = *byteptr++;
482
483 while (--bytecnt) {
484 mask |= (uint32_t) *byteptr++ << shift;
485 shift += 8;
486 }
487 }
488
489 if (wpc->config.num_channels > wpc->max_streams * 2)
490 return FALSE;
491
492 wpc->config.channel_mask = mask;
493
494 for (mask_bits = 0; mask; mask >>= 1)
495 if ((mask & 1) && ++mask_bits > wpc->config.num_channels)
496 return FALSE;
497 }
498
499 return TRUE;
500 }
501
502 // Read multichannel identity information from metadata. Data is an array of
503 // unsigned characters representing any channels in the file that DO NOT
504 // match one the 18 Microsoft standard channels (and are represented in the
505 // channel mask). A value of 0 is not allowed and 0xff means an unknown or
506 // undefined channel identity.
507
read_channel_identities(WavpackContext * wpc,WavpackMetadata * wpmd)508 static int read_channel_identities (WavpackContext *wpc, WavpackMetadata *wpmd)
509 {
510 unsigned char *idents = wpmd->data;
511 int i;
512
513 if (!wpmd->data || !wpmd->byte_length)
514 return FALSE;
515
516 for (i = 0; i < wpmd->byte_length; ++i)
517 if (!idents [i])
518 return FALSE;
519
520 if (!wpc->channel_identities) {
521 wpc->channel_identities = (unsigned char *)malloc (wpmd->byte_length + 1);
522 memcpy (wpc->channel_identities, wpmd->data, wpmd->byte_length);
523 wpc->channel_identities [wpmd->byte_length] = 0;
524 }
525
526 return TRUE;
527 }
528
529 // Read configuration information from metadata.
530
read_config_info(WavpackContext * wpc,WavpackMetadata * wpmd)531 static int read_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
532 {
533 int bytecnt = wpmd->byte_length;
534 unsigned char *byteptr = (unsigned char *)wpmd->data;
535
536 if (bytecnt >= 3) {
537 wpc->config.flags &= 0xff;
538 wpc->config.flags |= (uint32_t) *byteptr++ << 8;
539 wpc->config.flags |= (uint32_t) *byteptr++ << 16;
540 wpc->config.flags |= (uint32_t) *byteptr++ << 24;
541 bytecnt -= 3;
542
543 if (bytecnt && (wpc->config.flags & CONFIG_EXTRA_MODE)) {
544 wpc->config.xmode = *byteptr++;
545 bytecnt--;
546 }
547
548 // we used an extra config byte here for the 5.0.0 alpha, so still
549 // honor it now (but this has been replaced with NEW_CONFIG)
550
551 if (bytecnt) {
552 wpc->config.qmode = (wpc->config.qmode & ~0xff) | *byteptr;
553 wpc->version_five = 1;
554 }
555 }
556
557 return TRUE;
558 }
559
560 // Read "new" configuration information from metadata.
561
read_new_config_info(WavpackContext * wpc,WavpackMetadata * wpmd)562 static int read_new_config_info (WavpackContext *wpc, WavpackMetadata *wpmd)
563 {
564 int bytecnt = wpmd->byte_length;
565 unsigned char *byteptr = (unsigned char *)wpmd->data;
566
567 wpc->version_five = 1; // just having this block signals version 5.0
568
569 wpc->file_format = wpc->config.qmode = wpc->channel_layout = 0;
570
571 if (wpc->channel_reordering) {
572 free (wpc->channel_reordering);
573 wpc->channel_reordering = NULL;
574 }
575
576 // if there's any data, the first two bytes are file_format and qmode flags
577
578 if (bytecnt >= 2) {
579 wpc->file_format = *byteptr++;
580 wpc->config.qmode = (wpc->config.qmode & ~0xff) | *byteptr++;
581 bytecnt -= 2;
582
583 // another byte indicates a channel layout
584
585 if (bytecnt) {
586 int nchans, i;
587
588 wpc->channel_layout = (uint32_t) *byteptr++ << 16;
589 bytecnt--;
590
591 // another byte means we have a channel count for the layout and maybe a reordering
592
593 if (bytecnt) {
594 wpc->channel_layout += nchans = *byteptr++;
595 bytecnt--;
596
597 // any more means there's a reordering string
598
599 if (bytecnt) {
600 if (bytecnt > nchans)
601 return FALSE;
602
603 wpc->channel_reordering = (unsigned char *)malloc (nchans);
604
605 // note that redundant reordering info is not stored, so we fill in the rest
606
607 if (wpc->channel_reordering) {
608 for (i = 0; i < nchans; ++i)
609 if (bytecnt) {
610 wpc->channel_reordering [i] = *byteptr++;
611
612 if (wpc->channel_reordering [i] >= nchans) // make sure index is in range
613 wpc->channel_reordering [i] = 0;
614
615 bytecnt--;
616 }
617 else
618 wpc->channel_reordering [i] = i;
619 }
620 }
621 }
622 else
623 wpc->channel_layout += wpc->config.num_channels;
624 }
625 }
626
627 return TRUE;
628 }
629
630 // Read non-standard sampling rate from metadata.
631
read_sample_rate(WavpackContext * wpc,WavpackMetadata * wpmd)632 static int read_sample_rate (WavpackContext *wpc, WavpackMetadata *wpmd)
633 {
634 int bytecnt = wpmd->byte_length;
635 unsigned char *byteptr = (unsigned char *)wpmd->data;
636
637 if (bytecnt == 3 || bytecnt == 4) {
638 wpc->config.sample_rate = (int32_t) *byteptr++;
639 wpc->config.sample_rate |= (int32_t) *byteptr++ << 8;
640 wpc->config.sample_rate |= (int32_t) *byteptr++ << 16;
641
642 // for sampling rates > 16777215 (non-audio probably, or ...)
643
644 if (bytecnt == 4)
645 wpc->config.sample_rate |= (int32_t) (*byteptr & 0x7f) << 24;
646 }
647
648 return TRUE;
649 }
650
651 // Read wrapper data from metadata. Currently, this consists of the RIFF
652 // header and trailer that wav files contain around the audio data but could
653 // be used for other formats as well. Because WavPack files contain all the
654 // information required for decoding and playback, this data can probably
655 // be ignored except when an exact wavefile restoration is needed.
656
read_wrapper_data(WavpackContext * wpc,WavpackMetadata * wpmd)657 static int read_wrapper_data (WavpackContext *wpc, WavpackMetadata *wpmd)
658 {
659 if ((wpc->open_flags & OPEN_WRAPPER) && wpc->wrapper_bytes < MAX_WRAPPER_BYTES && wpmd->byte_length) {
660 wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + wpmd->byte_length);
661 if (!wpc->wrapper_data)
662 return FALSE;
663 memcpy (wpc->wrapper_data + wpc->wrapper_bytes, wpmd->data, wpmd->byte_length);
664 wpc->wrapper_bytes += wpmd->byte_length;
665 }
666
667 return TRUE;
668 }
669
read_metadata_buff(WavpackMetadata * wpmd,unsigned char * blockbuff,unsigned char ** buffptr)670 static int read_metadata_buff (WavpackMetadata *wpmd, unsigned char *blockbuff, unsigned char **buffptr)
671 {
672 WavpackHeader *wphdr = (WavpackHeader *) blockbuff;
673 unsigned char *buffend = blockbuff + wphdr->ckSize + 8;
674
675 if (buffend - *buffptr < 2)
676 return FALSE;
677
678 wpmd->id = *(*buffptr)++;
679 wpmd->byte_length = *(*buffptr)++ << 1;
680
681 if (wpmd->id & ID_LARGE) {
682 wpmd->id &= ~ID_LARGE;
683
684 if (buffend - *buffptr < 2)
685 return FALSE;
686
687 wpmd->byte_length += *(*buffptr)++ << 9;
688 wpmd->byte_length += *(*buffptr)++ << 17;
689 }
690
691 if (wpmd->id & ID_ODD_SIZE) {
692 if (!wpmd->byte_length) // odd size and zero length makes no sense
693 return FALSE;
694 wpmd->id &= ~ID_ODD_SIZE;
695 wpmd->byte_length--;
696 }
697
698 if (wpmd->byte_length) {
699 if (buffend - *buffptr < wpmd->byte_length + (wpmd->byte_length & 1)) {
700 wpmd->data = NULL;
701 return FALSE;
702 }
703
704 wpmd->data = *buffptr;
705 (*buffptr) += wpmd->byte_length + (wpmd->byte_length & 1);
706 }
707 else
708 wpmd->data = NULL;
709
710 return TRUE;
711 }
712
process_metadata(WavpackContext * wpc,WavpackMetadata * wpmd)713 static int process_metadata (WavpackContext *wpc, WavpackMetadata *wpmd)
714 {
715 WavpackStream *wps = wpc->streams [wpc->current_stream];
716
717 switch (wpmd->id) {
718 case ID_DUMMY:
719 return TRUE;
720
721 case ID_DECORR_TERMS:
722 return read_decorr_terms (wps, wpmd);
723
724 case ID_DECORR_WEIGHTS:
725 return read_decorr_weights (wps, wpmd);
726
727 case ID_DECORR_SAMPLES:
728 return read_decorr_samples (wps, wpmd);
729
730 case ID_ENTROPY_VARS:
731 return read_entropy_vars (wps, wpmd);
732
733 case ID_HYBRID_PROFILE:
734 return read_hybrid_profile (wps, wpmd);
735
736 case ID_SHAPING_WEIGHTS:
737 return read_shaping_info (wps, wpmd);
738
739 case ID_FLOAT_INFO:
740 return read_float_info (wps, wpmd);
741
742 case ID_INT32_INFO:
743 return read_int32_info (wps, wpmd);
744
745 case ID_CHANNEL_INFO:
746 return read_channel_info (wpc, wpmd);
747
748 case ID_CHANNEL_IDENTITIES:
749 return read_channel_identities (wpc, wpmd);
750
751 case ID_CONFIG_BLOCK:
752 return read_config_info (wpc, wpmd);
753
754 case ID_NEW_CONFIG_BLOCK:
755 return read_new_config_info (wpc, wpmd);
756
757 case ID_SAMPLE_RATE:
758 return read_sample_rate (wpc, wpmd);
759
760 case ID_WV_BITSTREAM:
761 return init_wv_bitstream (wps, wpmd);
762
763 case ID_WVC_BITSTREAM:
764 return init_wvc_bitstream (wps, wpmd);
765
766 case ID_WVX_BITSTREAM:
767 return init_wvx_bitstream (wps, wpmd);
768
769 case ID_DSD_BLOCK:
770 #ifdef ENABLE_DSD
771 return init_dsd_block (wpc, wpmd);
772 #else
773 strcpy (wpc->error_message, "not configured to handle DSD WavPack files!");
774 return FALSE;
775 #endif
776
777 case ID_ALT_HEADER: case ID_ALT_TRAILER:
778 if (!(wpc->open_flags & OPEN_ALT_TYPES))
779 return TRUE;
780
781 case ID_RIFF_HEADER: case ID_RIFF_TRAILER:
782 return read_wrapper_data (wpc, wpmd);
783
784 case ID_ALT_MD5_CHECKSUM:
785 if (!(wpc->open_flags & OPEN_ALT_TYPES))
786 return TRUE;
787
788 case ID_MD5_CHECKSUM:
789 if (wpmd->byte_length == 16) {
790 memcpy (wpc->config.md5_checksum, wpmd->data, 16);
791 wpc->config.flags |= CONFIG_MD5_CHECKSUM;
792 wpc->config.md5_read = 1;
793 }
794
795 return TRUE;
796
797 case ID_ALT_EXTENSION:
798 if (wpmd->byte_length && wpmd->byte_length < sizeof (wpc->file_extension)) {
799 memcpy (wpc->file_extension, wpmd->data, wpmd->byte_length);
800 wpc->file_extension [wpmd->byte_length] = 0;
801 }
802
803 return TRUE;
804
805 // we don't actually verify the checksum here (it's done right after the
806 // block is read), but it's a good indicator of version 5 files
807
808 case ID_BLOCK_CHECKSUM:
809 wpc->version_five = 1;
810 return TRUE;
811
812 default:
813 return (wpmd->id & ID_OPTIONAL_DATA) ? TRUE : FALSE;
814 }
815 }
816
817 //////////////////////////////// bitstream management ///////////////////////////////
818
819 // Open the specified BitStream and associate with the specified buffer.
820
821 static void bs_read (Bitstream *bs);
822
bs_open_read(Bitstream * bs,void * buffer_start,void * buffer_end)823 static void bs_open_read (Bitstream *bs, void *buffer_start, void *buffer_end)
824 {
825 bs->error = bs->sr = bs->bc = 0;
826 bs->ptr = (bs->buf = buffer_start) - 1;
827 bs->end = buffer_end;
828 bs->wrap = bs_read;
829 }
830
831 // This function is only called from the getbit() and getbits() macros when
832 // the BitStream has been exhausted and more data is required. Sinve these
833 // bistreams no longer access files, this function simple sets an error and
834 // resets the buffer.
835
bs_read(Bitstream * bs)836 static void bs_read (Bitstream *bs)
837 {
838 bs->ptr = bs->buf;
839 bs->error = 1;
840 }
841
842 // This function is called to close the bitstream. It returns the number of
843 // full bytes actually read as bits.
844
bs_close_read(Bitstream * bs)845 uint32_t bs_close_read (Bitstream *bs)
846 {
847 uint32_t bytes_read;
848
849 if (bs->bc < sizeof (*(bs->ptr)) * 8)
850 bs->ptr++;
851
852 bytes_read = (uint32_t)(bs->ptr - bs->buf) * sizeof (*(bs->ptr));
853
854 if (!(bytes_read & 1))
855 ++bytes_read;
856
857 CLEAR (*bs);
858 return bytes_read;
859 }
860
861 // Normally the trailing wrapper will not be available when a WavPack file is first
862 // opened for reading because it is stored in the final block of the file. This
863 // function forces a seek to the end of the file to pick up any trailing wrapper
864 // stored there (then use WavPackGetWrapper**() to obtain). This can obviously only
865 // be used for seekable files (not pipes) and is not available for pre-4.0 WavPack
866 // files.
867
WavpackSeekTrailingWrapper(WavpackContext * wpc)868 void WavpackSeekTrailingWrapper (WavpackContext *wpc)
869 {
870 if ((wpc->open_flags & OPEN_WRAPPER) &&
871 wpc->reader->can_seek (wpc->wv_in) && !wpc->stream3)
872 seek_eof_information (wpc, NULL, TRUE);
873 }
874
875 // Get any MD5 checksum stored in the metadata (should be called after reading
876 // last sample or an extra seek will occur). A return value of FALSE indicates
877 // that no MD5 checksum was stored.
878
WavpackGetMD5Sum(WavpackContext * wpc,unsigned char data[16])879 int WavpackGetMD5Sum (WavpackContext *wpc, unsigned char data [16])
880 {
881 if (wpc->config.flags & CONFIG_MD5_CHECKSUM) {
882 if (!wpc->config.md5_read && wpc->reader->can_seek (wpc->wv_in))
883 seek_eof_information (wpc, NULL, FALSE);
884
885 if (wpc->config.md5_read) {
886 memcpy (data, wpc->config.md5_checksum, 16);
887 return TRUE;
888 }
889 }
890
891 return FALSE;
892 }
893
894 // Read from current file position until a valid 32-byte WavPack 4.0 header is
895 // found and read into the specified pointer. The number of bytes skipped is
896 // returned. If no WavPack header is found within 1 meg, then a -1 is returned
897 // to indicate the error. No additional bytes are read past the header and it
898 // is returned in the processor's native endian mode. Seeking is not required.
899
read_next_header(WavpackStreamReader64 * reader,void * id,WavpackHeader * wphdr)900 uint32_t read_next_header (WavpackStreamReader64 *reader, void *id, WavpackHeader *wphdr)
901 {
902 unsigned char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp;
903 uint32_t bytes_skipped = 0;
904 int bleft;
905
906 while (1) {
907 if (sp < ep) {
908 bleft = (int)(ep - sp);
909 memmove (buffer, sp, bleft);
910 }
911 else
912 bleft = 0;
913
914 if (reader->read_bytes (id, buffer + bleft, sizeof (*wphdr) - bleft) != sizeof (*wphdr) - bleft)
915 return -1;
916
917 sp = buffer;
918
919 if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' &&
920 !(*++sp & 1) && sp [2] < 16 && !sp [3] && (sp [2] || sp [1] || *sp >= 24) && sp [5] == 4 &&
921 sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff) && sp [18] < 3 && !sp [19]) {
922 memcpy (wphdr, buffer, sizeof (*wphdr));
923 WavpackLittleEndianToNative (wphdr, WavpackHeaderFormat);
924 return bytes_skipped;
925 }
926
927 while (sp < ep && *sp != 'w')
928 sp++;
929
930 if ((bytes_skipped += (uint32_t)(sp - buffer)) > 1024 * 1024)
931 return -1;
932 }
933 }
934
935 // Compare the regular wv file block header to a potential matching wvc
936 // file block header and return action code based on analysis:
937 //
938 // 0 = use wvc block (assuming rest of block is readable)
939 // 1 = bad match; try to read next wvc block
940 // -1 = bad match; ignore wvc file for this block and backup fp (if
941 // possible) and try to use this block next time
942
match_wvc_header(WavpackHeader * wv_hdr,WavpackHeader * wvc_hdr)943 static int match_wvc_header (WavpackHeader *wv_hdr, WavpackHeader *wvc_hdr)
944 {
945 if (GET_BLOCK_INDEX (*wv_hdr) == GET_BLOCK_INDEX (*wvc_hdr) &&
946 wv_hdr->block_samples == wvc_hdr->block_samples) {
947 int wvi = 0, wvci = 0;
948
949 if (wv_hdr->flags == wvc_hdr->flags)
950 return 0;
951
952 if (wv_hdr->flags & INITIAL_BLOCK)
953 wvi -= 1;
954
955 if (wv_hdr->flags & FINAL_BLOCK)
956 wvi += 1;
957
958 if (wvc_hdr->flags & INITIAL_BLOCK)
959 wvci -= 1;
960
961 if (wvc_hdr->flags & FINAL_BLOCK)
962 wvci += 1;
963
964 return (wvci - wvi < 0) ? 1 : -1;
965 }
966
967 if ((GET_BLOCK_INDEX (*wvc_hdr) - GET_BLOCK_INDEX (*wv_hdr)) & 0x8000000000LL)
968 return 1;
969 else
970 return -1;
971 }
972
973 // Read the wvc block that matches the regular wv block that has been
974 // read for the current stream. If an exact match is not found then
975 // we either keep reading or back up and (possibly) use the block
976 // later. The skip_wvc flag is set if not matching wvc block is found
977 // so that we can still decode using only the lossy version (although
978 // we flag this as an error). A return of FALSE indicates a serious
979 // error (not just that we missed one wvc block).
980
read_wvc_block(WavpackContext * wpc)981 int read_wvc_block (WavpackContext *wpc)
982 {
983 WavpackStream *wps = wpc->streams [wpc->current_stream];
984 int64_t bcount, file2pos;
985 WavpackHeader orig_wphdr;
986 WavpackHeader wphdr;
987 int compare_result;
988
989 while (1) {
990 file2pos = wpc->reader->get_pos (wpc->wvc_in);
991 bcount = read_next_header (wpc->reader, wpc->wvc_in, &wphdr);
992
993 if (bcount == (uint32_t) -1) {
994 wps->wvc_skip = TRUE;
995 wpc->crc_errors++;
996 return FALSE;
997 }
998
999 memcpy (&orig_wphdr, &wphdr, 32); // save original header for verify step
1000
1001 if (wpc->open_flags & OPEN_STREAMING)
1002 SET_BLOCK_INDEX (wphdr, wps->sample_index = 0);
1003 else
1004 SET_BLOCK_INDEX (wphdr, GET_BLOCK_INDEX (wphdr) - wpc->initial_index);
1005
1006 if (wphdr.flags & INITIAL_BLOCK)
1007 wpc->file2pos = file2pos + bcount;
1008
1009 compare_result = match_wvc_header (&wps->wphdr, &wphdr);
1010
1011 if (!compare_result) {
1012 wps->block2buff = (unsigned char *)malloc (wphdr.ckSize + 8);
1013 if (!wps->block2buff)
1014 return FALSE;
1015
1016 if (wpc->reader->read_bytes (wpc->wvc_in, wps->block2buff + 32, wphdr.ckSize - 24) !=
1017 wphdr.ckSize - 24) {
1018 free (wps->block2buff);
1019 wps->block2buff = NULL;
1020 wps->wvc_skip = TRUE;
1021 wpc->crc_errors++;
1022 return FALSE;
1023 }
1024
1025 memcpy (wps->block2buff, &orig_wphdr, 32);
1026
1027 // don't use corrupt blocks
1028 if (!WavpackVerifySingleBlock (wps->block2buff, !(wpc->open_flags & OPEN_NO_CHECKSUM))) {
1029 free (wps->block2buff);
1030 wps->block2buff = NULL;
1031 wps->wvc_skip = TRUE;
1032 wpc->crc_errors++;
1033 return TRUE;
1034 }
1035
1036 wps->wvc_skip = FALSE;
1037 memcpy (wps->block2buff, &wphdr, 32);
1038 memcpy (&wps->wphdr, &wphdr, 32);
1039 return TRUE;
1040 }
1041 else if (compare_result == -1) {
1042 wps->wvc_skip = TRUE;
1043 wpc->reader->set_pos_rel (wpc->wvc_in, -32, SEEK_CUR);
1044 wpc->crc_errors++;
1045 return TRUE;
1046 }
1047 }
1048 }
1049
1050 // This function is used to seek to end of a file to obtain certain information
1051 // that is stored there at the file creation time because it is not known at
1052 // the start. This includes the MD5 sum and and trailing part of the file
1053 // wrapper, and in some rare cases may include the total number of samples in
1054 // the file (although we usually try to back up and write that at the front of
1055 // the file). Note this function restores the file position to its original
1056 // location (and obviously requires a seekable file). The normal return value
1057 // is TRUE indicating no errors, although this does not actually mean that any
1058 // information was retrieved. An error return of FALSE usually means the file
1059 // terminated unexpectedly. Note that this could be used to get all three
1060 // types of information in one go, but it's not actually used that way now.
1061
seek_eof_information(WavpackContext * wpc,int64_t * final_index,int get_wrapper)1062 static int seek_eof_information (WavpackContext *wpc, int64_t *final_index, int get_wrapper)
1063 {
1064 int64_t restore_pos, last_pos = -1;
1065 WavpackStreamReader64 *reader = wpc->reader;
1066 int alt_types = wpc->open_flags & OPEN_ALT_TYPES;
1067 uint32_t blocks = 0, audio_blocks = 0;
1068 void *id = wpc->wv_in;
1069 WavpackHeader wphdr;
1070
1071 restore_pos = reader->get_pos (id); // we restore file position when done
1072
1073 // start 1MB from the end-of-file, or from the start if the file is not that big
1074
1075 if (reader->get_length (id) > (int64_t) 1048576)
1076 reader->set_pos_rel (id, -1048576, SEEK_END);
1077 else
1078 reader->set_pos_abs (id, 0);
1079
1080 // Note that we go backward (without parsing inside blocks) until we find a block
1081 // with audio (careful to not get stuck in a loop). Only then do we go forward
1082 // parsing all blocks in their entirety.
1083
1084 while (1) {
1085 uint32_t bcount = read_next_header (reader, id, &wphdr);
1086 int64_t current_pos = reader->get_pos (id);
1087
1088 // if we just got to the same place as last time, we're stuck and need to give up
1089
1090 if (current_pos == last_pos) {
1091 reader->set_pos_abs (id, restore_pos);
1092 return FALSE;
1093 }
1094
1095 last_pos = current_pos;
1096
1097 // We enter here if we just read 1 MB without seeing any WavPack block headers.
1098 // Since WavPack blocks are < 1 MB, that means we're in a big APE tag, or we got
1099 // to the end-of-file.
1100
1101 if (bcount == (uint32_t) -1) {
1102
1103 // if we have not seen any blocks at all yet, back up almost 2 MB (or to the
1104 // beginning of the file) and try again
1105
1106 if (!blocks) {
1107 if (current_pos > (int64_t) 2000000)
1108 reader->set_pos_rel (id, -2000000, SEEK_CUR);
1109 else
1110 reader->set_pos_abs (id, 0);
1111
1112 continue;
1113 }
1114
1115 // if we have seen WavPack blocks, then this means we've done all we can do here
1116
1117 reader->set_pos_abs (id, restore_pos);
1118 return TRUE;
1119 }
1120
1121 blocks++;
1122
1123 // If the block has audio samples, calculate a final index, although this is not
1124 // final since this may not be the last block with audio. On the other hand, if
1125 // this block does not have audio, and we haven't seen one with audio, we have
1126 // to go back some more.
1127
1128 if (wphdr.block_samples) {
1129 if (final_index)
1130 *final_index = GET_BLOCK_INDEX (wphdr) + wphdr.block_samples;
1131
1132 audio_blocks++;
1133 }
1134 else if (!audio_blocks) {
1135 if (current_pos > (int64_t) 1048576)
1136 reader->set_pos_rel (id, -1048576, SEEK_CUR);
1137 else
1138 reader->set_pos_abs (id, 0);
1139
1140 continue;
1141 }
1142
1143 // at this point we have seen at least one block with audio, so we parse the
1144 // entire block looking for MD5 metadata or (conditionally) trailing wrappers
1145
1146 bcount = wphdr.ckSize - sizeof (WavpackHeader) + 8;
1147
1148 while (bcount >= 2) {
1149 unsigned char meta_id, c1, c2;
1150 uint32_t meta_bc, meta_size;
1151
1152 if (reader->read_bytes (id, &meta_id, 1) != 1 ||
1153 reader->read_bytes (id, &c1, 1) != 1) {
1154 reader->set_pos_abs (id, restore_pos);
1155 return FALSE;
1156 }
1157
1158 meta_bc = c1 << 1;
1159 bcount -= 2;
1160
1161 if (meta_id & ID_LARGE) {
1162 if (bcount < 2 || reader->read_bytes (id, &c1, 1) != 1 ||
1163 reader->read_bytes (id, &c2, 1) != 1) {
1164 reader->set_pos_abs (id, restore_pos);
1165 return FALSE;
1166 }
1167
1168 meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
1169 bcount -= 2;
1170 }
1171
1172 meta_size = (meta_id & ID_ODD_SIZE) ? meta_bc - 1 : meta_bc;
1173 meta_id &= ID_UNIQUE;
1174
1175 if (get_wrapper && (meta_id == ID_RIFF_TRAILER || (alt_types && meta_id == ID_ALT_TRAILER)) && meta_bc) {
1176 wpc->wrapper_data = (unsigned char *)realloc (wpc->wrapper_data, wpc->wrapper_bytes + meta_bc);
1177
1178 if (!wpc->wrapper_data) {
1179 reader->set_pos_abs (id, restore_pos);
1180 return FALSE;
1181 }
1182
1183 if (reader->read_bytes (id, wpc->wrapper_data + wpc->wrapper_bytes, meta_bc) == meta_bc)
1184 wpc->wrapper_bytes += meta_size;
1185 else {
1186 reader->set_pos_abs (id, restore_pos);
1187 return FALSE;
1188 }
1189 }
1190 else if (meta_id == ID_MD5_CHECKSUM || (alt_types && meta_id == ID_ALT_MD5_CHECKSUM)) {
1191 if (meta_bc == 16 && bcount >= 16) {
1192 if (reader->read_bytes (id, wpc->config.md5_checksum, 16) == 16)
1193 wpc->config.md5_read = TRUE;
1194 else {
1195 reader->set_pos_abs (id, restore_pos);
1196 return FALSE;
1197 }
1198 }
1199 else
1200 reader->set_pos_rel (id, meta_bc, SEEK_CUR);
1201 }
1202 else
1203 reader->set_pos_rel (id, meta_bc, SEEK_CUR);
1204
1205 bcount -= meta_bc;
1206 }
1207 }
1208 }
1209
1210 // Quickly verify the referenced block. It is assumed that the WavPack header has been converted
1211 // to native endian format. If a block checksum is performed, that is done in little-endian
1212 // (file) format. It is also assumed that the caller has made sure that the block length
1213 // indicated in the header is correct (we won't overflow the buffer). If a checksum is present,
1214 // then it is checked, otherwise we just check that all the metadata blocks are formatted
1215 // correctly (without looking at their contents). Returns FALSE for bad block.
1216
WavpackVerifySingleBlock(unsigned char * buffer,int verify_checksum)1217 int WavpackVerifySingleBlock (unsigned char *buffer, int verify_checksum)
1218 {
1219 WavpackHeader *wphdr = (WavpackHeader *) buffer;
1220 uint32_t checksum_passed = 0, bcount, meta_bc;
1221 unsigned char *dp, meta_id, c1, c2;
1222
1223 if (strncmp (wphdr->ckID, "wvpk", 4) || wphdr->ckSize + 8 < sizeof (WavpackHeader))
1224 return FALSE;
1225
1226 bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8;
1227 dp = (unsigned char *)(wphdr + 1);
1228
1229 while (bcount >= 2) {
1230 meta_id = *dp++;
1231 c1 = *dp++;
1232
1233 meta_bc = c1 << 1;
1234 bcount -= 2;
1235
1236 if (meta_id & ID_LARGE) {
1237 if (bcount < 2)
1238 return FALSE;
1239
1240 c1 = *dp++;
1241 c2 = *dp++;
1242 meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
1243 bcount -= 2;
1244 }
1245
1246 if (bcount < meta_bc)
1247 return FALSE;
1248
1249 if (verify_checksum && (meta_id & ID_UNIQUE) == ID_BLOCK_CHECKSUM) {
1250 #ifdef BITSTREAM_SHORTS
1251 uint16_t *csptr = (uint16_t*) buffer;
1252 #else
1253 unsigned char *csptr = buffer;
1254 #endif
1255 int wcount = (int)(dp - 2 - buffer) >> 1;
1256 uint32_t csum = (uint32_t) -1;
1257
1258 if ((meta_id & ID_ODD_SIZE) || meta_bc < 2 || meta_bc > 4)
1259 return FALSE;
1260
1261 #ifdef BITSTREAM_SHORTS
1262 while (wcount--)
1263 csum = (csum * 3) + *csptr++;
1264 #else
1265 WavpackNativeToLittleEndian ((WavpackHeader *) buffer, WavpackHeaderFormat);
1266
1267 while (wcount--) {
1268 csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
1269 csptr += 2;
1270 }
1271
1272 WavpackLittleEndianToNative ((WavpackHeader *) buffer, WavpackHeaderFormat);
1273 #endif
1274
1275 if (meta_bc == 4) {
1276 if (*dp != (csum & 0xff) || dp[1] != ((csum >> 8) & 0xff) || dp[2] != ((csum >> 16) & 0xff) || dp[3] != ((csum >> 24) & 0xff))
1277 return FALSE;
1278 }
1279 else {
1280 csum ^= csum >> 16;
1281
1282 if (*dp != (csum & 0xff) || dp[1] != ((csum >> 8) & 0xff))
1283 return FALSE;
1284 }
1285
1286 checksum_passed++;
1287 }
1288
1289 bcount -= meta_bc;
1290 dp += meta_bc;
1291 }
1292
1293 return (bcount == 0) && (!verify_checksum || !(wphdr->flags & HAS_CHECKSUM) || checksum_passed);
1294 }
1295