1 ////////////////////////////////////////////////////////////////////////////
2 // **** WAVPACK **** //
3 // Hybrid Lossless Wavefile Compressor //
4 // Copyright (c) 1998 - 2013 Conifer Software. //
5 // All Rights Reserved. //
6 // Distributed under the BSD Software License (see license.txt) //
7 ////////////////////////////////////////////////////////////////////////////
8
9 // pack_utils.c
10
11 // This module provides the high-level API for creating WavPack files from
12 // audio data. It manages the buffers used to deinterleave the data passed
13 // in from the application into the individual streams and it handles the
14 // generation of riff headers and the "fixup" on the first WavPack block
15 // header for the case where the number of samples was unknown (or wrong).
16 // The actual audio stream compression is handled in the pack.c module.
17
18 #include <stdlib.h>
19 #include <string.h>
20 #include <math.h>
21
22 #include "wavpack_local.h"
23
24 ///////////////////////////// executable code ////////////////////////////////
25
26 // Open context for writing WavPack files. The returned context pointer is used
27 // in all following calls to the library. The "blockout" function will be used
28 // to store the actual completed WavPack blocks and will be called with the id
29 // pointers containing user defined data (one for the wv file and one for the
30 // wvc file). A return value of NULL indicates that memory could not be
31 // allocated for the context.
32
WavpackOpenFileOutput(WavpackBlockOutput blockout,void * wv_id,void * wvc_id)33 WavpackContext *WavpackOpenFileOutput (WavpackBlockOutput blockout, void *wv_id, void *wvc_id)
34 {
35 WavpackContext *wpc = malloc (sizeof (WavpackContext));
36
37 if (!wpc)
38 return NULL;
39
40 CLEAR (*wpc);
41 wpc->total_samples = -1;
42 wpc->stream_version = CUR_STREAM_VERS;
43 wpc->blockout = blockout;
44 wpc->wv_out = wv_id;
45 wpc->wvc_out = wvc_id;
46 return wpc;
47 }
48
49 static int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, unsigned char id);
50
51 // New for version 5.0, this function allows the application to store a file extension and a
52 // file_format identification. The extension would be used by the unpacker if the user had not
53 // specified the target filename, and specifically handles the case where the original file
54 // had the "wrong" extension for the file format (e.g., a Wave64 file having a "wav" extension)
55 // or an alternative (e.g., "bwf") or where the file format is not known. Specifying a file
56 // format besides the default WP_FORMAT_WAV will ensure that old decoders will not be able to
57 // see the non-wav wrapper provided with WavpackAddWrapper() (which they would end up putting
58 // on a file with a .wav extension).
59
WavpackSetFileInformation(WavpackContext * wpc,char * file_extension,unsigned char file_format)60 void WavpackSetFileInformation (WavpackContext *wpc, char *file_extension, unsigned char file_format)
61 {
62 if (file_extension && strlen (file_extension) < sizeof (wpc->file_extension)) {
63 add_to_metadata (wpc, file_extension, (uint32_t) strlen (file_extension), ID_ALT_EXTENSION);
64 strcpy (wpc->file_extension, file_extension);
65 }
66
67 wpc->file_format = file_format;
68 }
69
70 // Set configuration for writing WavPack files. This must be done before
71 // sending any actual samples, however it is okay to send wrapper or other
72 // metadata before calling this. The "config" structure contains the following
73 // required information:
74
75 // config->bytes_per_sample see WavpackGetBytesPerSample() for info
76 // config->bits_per_sample see WavpackGetBitsPerSample() for info
77 // config->channel_mask Microsoft standard (mono = 4, stereo = 3)
78 // config->num_channels self evident
79 // config->sample_rate self evident
80
81 // In addition, the following fields and flags may be set:
82
83 // config->flags:
84 // --------------
85 // o CONFIG_HYBRID_FLAG select hybrid mode (must set bitrate)
86 // o CONFIG_JOINT_STEREO select joint stereo (must set override also)
87 // o CONFIG_JOINT_OVERRIDE override default joint stereo selection
88 // o CONFIG_HYBRID_SHAPE select hybrid noise shaping (set override &
89 // shaping_weight != 0.0)
90 // o CONFIG_SHAPE_OVERRIDE override default hybrid noise shaping
91 // (set CONFIG_HYBRID_SHAPE and shaping_weight)
92 // o CONFIG_FAST_FLAG "fast" compression mode
93 // o CONFIG_HIGH_FLAG "high" compression mode
94 // o CONFIG_BITRATE_KBPS hybrid bitrate is kbps, not bits / sample
95 // o CONFIG_CREATE_WVC create correction file
96 // o CONFIG_OPTIMIZE_WVC maximize bybrid compression (-cc option)
97 // o CONFIG_CALC_NOISE calc noise in hybrid mode
98 // o CONFIG_EXTRA_MODE extra processing mode (slow!)
99 // o CONFIG_SKIP_WVX no wvx stream for floats & large ints
100 // o CONFIG_MD5_CHECKSUM specify if you plan to store MD5 signature
101 // o CONFIG_CREATE_EXE specify if you plan to prepend sfx module
102 // o CONFIG_OPTIMIZE_MONO detect and optimize for mono files posing as
103 // stereo (uses a more recent stream format that
104 // is not compatible with decoders < 4.3)
105
106 // config->bitrate hybrid bitrate in either bits/sample or kbps
107 // config->shaping_weight hybrid noise shaping coefficient override
108 // config->block_samples force samples per WavPack block (0 = use deflt)
109 // config->float_norm_exp select floating-point data (127 for +/-1.0)
110 // config->xmode extra mode processing value override
111
112 // If the number of samples to be written is known then it should be passed
113 // here. If the duration is not known then pass -1. In the case that the size
114 // is not known (or the writing is terminated early) then it is suggested that
115 // the application retrieve the first block written and let the library update
116 // the total samples indication. A function is provided to do this update and
117 // it should be done to the "correction" file also. If this cannot be done
118 // (because a pipe is being used, for instance) then a valid WavPack will still
119 // be created, but when applications want to access that file they will have
120 // to seek all the way to the end to determine the actual duration. Also, if
121 // a RIFF header has been included then it should be updated as well or the
122 // WavPack file will not be directly unpackable to a valid wav file (although
123 // it will still be usable by itself). A return of FALSE indicates an error.
124 //
125 // The enhanced version of this function now allows setting the identities of
126 // any channels that are NOT standard Microsoft channels and are therefore not
127 // represented in the channel mask. WavPack files require that all the Microsoft
128 // channels come first (and in Microsoft order) and these are followed by any
129 // other channels (which can be in any order).
130 //
131 // The identities are provided in a NULL-terminated string (0x00 is not an allowed
132 // channel ID). The Microsoft channels may be provided as well (and will be checked)
133 // but it is really only necessary to provide the "unknown" channels. Any truly
134 // unknown channels are indicated with a 0xFF.
135 //
136 // The channel IDs so far reserved are listed here:
137 //
138 // 0: not allowed / terminator
139 // 1 - 18: Microsoft standard channels
140 // 30, 31: Stereo mix from RF64 (not really recommended, but RF64 specifies this)
141 // 33 - 44: Core Audio channels (see Core Audio specification)
142 // 127 - 128: Amio LeftHeight, Amio RightHeight
143 // 138 - 142: Amio BottomFrontLeft/Center/Right, Amio ProximityLeft/Right
144 // 200 - 207: Core Audio channels (see Core Audio specification)
145 // 221 - 224: Core Audio channels 301 - 305 (offset by 80)
146 // 255: Present but unknown or unused channel
147 //
148 // All other channel IDs are reserved. Ask if something you need is missing.
149
150 // Table of channels that will automatically "pair" into a single stereo stream
151
152 static const struct { unsigned char a, b; } stereo_pairs [] = {
153 { 1, 2 }, // FL, FR
154 { 5, 6 }, // BL, BR
155 { 7, 8 }, // FLC, FRC
156 { 10, 11 }, // SL, SR
157 { 13, 15 }, // TFL, TFR
158 { 16, 18 }, // TBL, TBR
159 { 30, 31 }, // stereo mix L,R (RF64)
160 { 33, 34 }, // Rls, Rrs
161 { 35, 36 }, // Lw, Rw
162 { 38, 39 }, // Lt, Rt
163 { 127, 128 }, // Lh, Rh
164 { 138, 140 }, // Bfl, Bfr
165 { 141, 142 }, // Pl, Pr
166 { 200, 201 }, // Amb_W, Amb_X
167 { 202, 203 }, // Amb_Y, Amb_Z
168 { 204, 205 }, // MS_Mid, MS_Side
169 { 206, 207 }, // XY_X, XY_Y
170 { 221, 222 }, // Hph_L, Hph_R
171 };
172
173 #define NUM_STEREO_PAIRS (sizeof (stereo_pairs) / sizeof (stereo_pairs [0]))
174
175 // Legacy version of this function for compatibility with existing applications. Note that this version
176 // also generates older streams to be compatible with all decoders back to 4.0, but of course cannot be
177 // used with > 2^32 samples or non-Microsoft channels. The older stream version only differs in that it
178 // does not support the "mono optimization" feature where stereo blocks containing identical audio data
179 // in both channels are encoded in mono for better efficiency.
180
WavpackSetConfiguration(WavpackContext * wpc,WavpackConfig * config,uint32_t total_samples)181 int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples)
182 {
183 config->flags |= CONFIG_COMPATIBLE_WRITE; // write earlier version streams
184
185 if (total_samples == (uint32_t) -1)
186 return WavpackSetConfiguration64 (wpc, config, -1, NULL);
187 else
188 return WavpackSetConfiguration64 (wpc, config, total_samples, NULL);
189 }
190
WavpackSetConfiguration64(WavpackContext * wpc,WavpackConfig * config,int64_t total_samples,const unsigned char * chan_ids)191 int WavpackSetConfiguration64 (WavpackContext *wpc, WavpackConfig *config, int64_t total_samples, const unsigned char *chan_ids)
192 {
193 uint32_t flags, bps = 0;
194 uint32_t chan_mask = config->channel_mask;
195 int num_chans = config->num_channels;
196 int i;
197
198 if (config->sample_rate <= 0) {
199 strcpy (wpc->error_message, "sample rate cannot be zero or negative!");
200 return FALSE;
201 }
202
203 if (num_chans <= 0 || num_chans > NEW_MAX_STREAMS * 2) {
204 strcpy (wpc->error_message, "invalid channel count!");
205 return FALSE;
206 }
207
208 if (config->block_samples && (config->block_samples < 16 || config->block_samples > 131072)) {
209 strcpy (wpc->error_message, "invalid custom block samples!");
210 return FALSE;
211 }
212
213 wpc->stream_version = (config->flags & CONFIG_COMPATIBLE_WRITE) ? CUR_STREAM_VERS : MAX_STREAM_VERS;
214
215 if ((config->qmode & QMODE_DSD_AUDIO) && config->bytes_per_sample == 1 && config->bits_per_sample == 8) {
216 #ifdef ENABLE_DSD
217 wpc->dsd_multiplier = 1;
218 flags = DSD_FLAG;
219
220 for (i = 14; i >= 0; --i)
221 if (config->sample_rate % sample_rates [i] == 0) {
222 int divisor = config->sample_rate / sample_rates [i];
223
224 if (divisor && (divisor & (divisor - 1)) == 0) {
225 config->sample_rate /= divisor;
226 wpc->dsd_multiplier = divisor;
227 break;
228 }
229 }
230
231 // most options that don't apply to DSD we can simply ignore for now, but NOT hybrid mode!
232 if (config->flags & CONFIG_HYBRID_FLAG) {
233 strcpy (wpc->error_message, "hybrid mode not available for DSD!");
234 return FALSE;
235 }
236
237 // with DSD, very few PCM options work (or make sense), so only allow those that do
238 config->flags &= (CONFIG_HIGH_FLAG | CONFIG_MD5_CHECKSUM | CONFIG_PAIR_UNDEF_CHANS);
239 config->float_norm_exp = config->xmode = 0;
240 #else
241 strcpy (wpc->error_message, "libwavpack not configured for DSD!");
242 return FALSE;
243 #endif
244 }
245 else
246 flags = config->bytes_per_sample - 1;
247
248 wpc->total_samples = total_samples;
249 wpc->config.sample_rate = config->sample_rate;
250 wpc->config.num_channels = config->num_channels;
251 wpc->config.channel_mask = config->channel_mask;
252 wpc->config.bits_per_sample = config->bits_per_sample;
253 wpc->config.bytes_per_sample = config->bytes_per_sample;
254 wpc->config.block_samples = config->block_samples;
255 wpc->config.flags = config->flags;
256 wpc->config.qmode = config->qmode;
257
258 if (config->flags & CONFIG_VERY_HIGH_FLAG)
259 wpc->config.flags |= CONFIG_HIGH_FLAG;
260
261 for (i = 0; i < 15; ++i)
262 if (wpc->config.sample_rate == sample_rates [i])
263 break;
264
265 flags |= i << SRATE_LSB;
266
267 // all of this stuff only applies to PCM
268
269 if (!(flags & DSD_FLAG)) {
270 if (config->float_norm_exp) {
271 if (config->bytes_per_sample != 4 || config->bits_per_sample != 32) {
272 strcpy (wpc->error_message, "incorrect bits/bytes configuration for float data!");
273 return FALSE;
274 }
275
276 wpc->config.float_norm_exp = config->float_norm_exp;
277 wpc->config.flags |= CONFIG_FLOAT_DATA;
278 flags |= FLOAT_DATA;
279 }
280 else {
281 if (config->bytes_per_sample < 1 || config->bytes_per_sample > 4) {
282 strcpy (wpc->error_message, "invalid bytes per sample!");
283 return FALSE;
284 }
285
286 if (config->bits_per_sample < 1 || config->bits_per_sample > config->bytes_per_sample * 8) {
287 strcpy (wpc->error_message, "invalid bits per sample!");
288 return FALSE;
289 }
290
291 flags |= ((config->bytes_per_sample * 8) - config->bits_per_sample) << SHIFT_LSB;
292 }
293
294 if (config->flags & CONFIG_HYBRID_FLAG) {
295 flags |= HYBRID_FLAG | HYBRID_BITRATE | HYBRID_BALANCE;
296
297 if (!(wpc->config.flags & CONFIG_SHAPE_OVERRIDE)) {
298 wpc->config.flags |= CONFIG_HYBRID_SHAPE | CONFIG_AUTO_SHAPING;
299 flags |= HYBRID_SHAPE | NEW_SHAPING;
300 }
301 else if (wpc->config.flags & CONFIG_HYBRID_SHAPE) {
302 wpc->config.shaping_weight = config->shaping_weight;
303 flags |= HYBRID_SHAPE | NEW_SHAPING;
304 }
305
306 if (wpc->config.flags & (CONFIG_CROSS_DECORR | CONFIG_OPTIMIZE_WVC))
307 flags |= CROSS_DECORR;
308
309 if (config->flags & CONFIG_BITRATE_KBPS) {
310 bps = (uint32_t) floor (config->bitrate * 256000.0 / config->sample_rate / config->num_channels + 0.5);
311
312 if (bps > (64 << 8))
313 bps = 64 << 8;
314 }
315 else
316 bps = (uint32_t) floor (config->bitrate * 256.0 + 0.5);
317 }
318 else
319 flags |= CROSS_DECORR;
320
321 if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO))
322 flags |= JOINT_STEREO;
323
324 if (config->flags & CONFIG_CREATE_WVC)
325 wpc->wvc_flag = TRUE;
326 }
327
328 // if a channel-identities string was specified, process that here, otherwise all channels
329 // not present in the channel mask are considered "unassigned"
330
331 if (chan_ids) {
332 int lastchan = 0, mask_copy = chan_mask;
333
334 if ((int) strlen ((char *) chan_ids) > num_chans) { // can't be more than num channels!
335 strcpy (wpc->error_message, "chan_ids longer than num channels!");
336 return FALSE;
337 }
338
339 // skip past channels that are specified in the channel mask (no reason to store those)
340
341 while (*chan_ids)
342 if (*chan_ids <= 32 && *chan_ids > lastchan && (mask_copy & (1U << (*chan_ids-1)))) {
343 mask_copy &= ~(1U << (*chan_ids-1));
344 lastchan = *chan_ids++;
345 }
346 else
347 break;
348
349 // now scan the string for an actually defined channel (and don't store if there aren't any)
350
351 for (i = 0; chan_ids [i]; i++)
352 if (chan_ids [i] != 0xff) {
353 wpc->channel_identities = (unsigned char *) strdup ((char *) chan_ids);
354 break;
355 }
356 }
357
358 // This loop goes through all the channels and creates the Wavpack "streams" for them to go in.
359 // A stream can hold either one or two channels, so we have several rules to determine how many
360 // channels will go in each stream.
361
362 for (wpc->current_stream = 0; num_chans; wpc->current_stream++) {
363 WavpackStream *wps = malloc (sizeof (WavpackStream));
364 unsigned char left_chan_id = 0, right_chan_id = 0;
365 int pos, chans = 1;
366
367 // allocate the stream and initialize the pointer to it
368 wpc->streams = realloc (wpc->streams, (wpc->current_stream + 1) * sizeof (wpc->streams [0]));
369 wpc->streams [wpc->current_stream] = wps;
370 CLEAR (*wps);
371
372 // if there are any bits [still] set in the channel_mask, get the next one or two IDs from there
373 if (chan_mask)
374 for (pos = 0; pos < 32; ++pos)
375 if (chan_mask & (1U << pos)) {
376 if (left_chan_id) {
377 right_chan_id = pos + 1;
378 break;
379 }
380 else {
381 chan_mask &= ~(1U << pos);
382 left_chan_id = pos + 1;
383 }
384 }
385
386 // next check for any channels identified in the channel-identities string
387 while (!right_chan_id && chan_ids && *chan_ids)
388 if (left_chan_id)
389 right_chan_id = *chan_ids;
390 else
391 left_chan_id = *chan_ids++;
392
393 // assume anything we did not get is "unassigned"
394 if (!left_chan_id)
395 left_chan_id = right_chan_id = 0xff;
396 else if (!right_chan_id)
397 right_chan_id = 0xff;
398
399 // if we have 2 channels, this is where we decide if we can combine them into one stream:
400 // 1. they are "unassigned" and we've been told to combine unassigned pairs, or
401 // 2. they appear together in the valid "pairings" list
402 if (num_chans >= 2) {
403 if ((config->flags & CONFIG_PAIR_UNDEF_CHANS) && left_chan_id == 0xff && right_chan_id == 0xff)
404 chans = 2;
405 else
406 for (i = 0; i < NUM_STEREO_PAIRS; ++i)
407 if ((left_chan_id == stereo_pairs [i].a && right_chan_id == stereo_pairs [i].b) ||
408 (left_chan_id == stereo_pairs [i].b && right_chan_id == stereo_pairs [i].a)) {
409 if (right_chan_id <= 32 && (chan_mask & (1U << (right_chan_id-1))))
410 chan_mask &= ~(1U << (right_chan_id-1));
411 else if (chan_ids && *chan_ids == right_chan_id)
412 chan_ids++;
413
414 chans = 2;
415 break;
416 }
417 }
418
419 num_chans -= chans;
420
421 if (num_chans && wpc->current_stream == NEW_MAX_STREAMS - 1)
422 break;
423
424 memcpy (wps->wphdr.ckID, "wvpk", 4);
425 wps->wphdr.ckSize = sizeof (WavpackHeader) - 8;
426 SET_TOTAL_SAMPLES (wps->wphdr, wpc->total_samples);
427 wps->wphdr.version = wpc->stream_version;
428 wps->wphdr.flags = flags;
429 wps->bits = bps;
430
431 if (!wpc->current_stream)
432 wps->wphdr.flags |= INITIAL_BLOCK;
433
434 if (!num_chans)
435 wps->wphdr.flags |= FINAL_BLOCK;
436
437 if (chans == 1) {
438 wps->wphdr.flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE);
439 wps->wphdr.flags |= MONO_FLAG;
440 }
441 }
442
443 wpc->num_streams = wpc->current_stream;
444 wpc->current_stream = 0;
445
446 if (num_chans) {
447 strcpy (wpc->error_message, "too many channels!");
448 return FALSE;
449 }
450
451 if (config->flags & CONFIG_EXTRA_MODE)
452 wpc->config.xmode = config->xmode ? config->xmode : 1;
453
454 return TRUE;
455 }
456
457 // This function allows setting the Core Audio File channel layout, many of which do not
458 // conform to the Microsoft ordering standard that Wavpack requires internally (at least for
459 // those channels present in the "channel mask"). In addition to the layout tag, this function
460 // allows a reordering string to be stored in the file to allow the unpacker to reorder the
461 // channels back to the specified layout (if it is aware of this feature and wants to restore
462 // the CAF order). The number of channels in the layout is specified in the lower nybble of
463 // the layout word, and if a reorder string is specified it must be that long. Note that all
464 // the reordering is actually done outside of this library, and that if reordering is done
465 // then the appropriate qmode bit must be set to ensure that any MD5 sum is stored with a new
466 // ID so that old decoders don't try to verify it (and to let the decoder know that a reorder
467 // might be required).
468 //
469 // Note: This function should only be used to encode Core Audio files in such a way that a
470 // verbatim archive can be created. Applications can just include the chan_ids parameter in
471 // the call to WavpackSetConfiguration64() if there are non-Microsoft channels to specify,
472 // or do nothing special if only Microsoft channels are present (the vast majority of cases).
473
WavpackSetChannelLayout(WavpackContext * wpc,uint32_t layout_tag,const unsigned char * reorder)474 int WavpackSetChannelLayout (WavpackContext *wpc, uint32_t layout_tag, const unsigned char *reorder)
475 {
476 int nchans = layout_tag & 0xff;
477
478 if ((layout_tag & 0xff00ff00) || nchans > wpc->config.num_channels)
479 return FALSE;
480
481 wpc->channel_layout = layout_tag;
482
483 if (wpc->channel_reordering) {
484 free (wpc->channel_reordering);
485 wpc->channel_reordering = NULL;
486 }
487
488 if (nchans && reorder) {
489 int min_index = 256, i;
490
491 for (i = 0; i < nchans; ++i)
492 if (reorder [i] < min_index)
493 min_index = reorder [i];
494
495 wpc->channel_reordering = malloc (nchans);
496
497 if (wpc->channel_reordering)
498 for (i = 0; i < nchans; ++i)
499 wpc->channel_reordering [i] = reorder [i] - min_index;
500 }
501
502 return TRUE;
503 }
504
505 // Prepare to actually pack samples by determining the size of the WavPack
506 // blocks and allocating sample buffers and initializing each stream. Call
507 // after WavpackSetConfiguration() and before WavpackPackSamples(). A return
508 // of FALSE indicates an error.
509
510 static int write_metadata_block (WavpackContext *wpc);
511
WavpackPackInit(WavpackContext * wpc)512 int WavpackPackInit (WavpackContext *wpc)
513 {
514 if (wpc->metabytes > 16384) // 16384 bytes still leaves plenty of room for audio
515 write_metadata_block (wpc); // in this block (otherwise write a special one)
516
517 // The default block size is a compromise. Longer blocks provide better encoding efficiency,
518 // but longer blocks adversely affect memory requirements and seeking performance. For WavPack
519 // version 5.0, the default block sizes have been reduced by half from the previous version,
520 // but the difference in encoding efficiency will generally be less than 0.1 percent.
521
522 if (wpc->dsd_multiplier) {
523 wpc->block_samples = (wpc->config.sample_rate % 7) ? 48000 : 44100;
524
525 if (wpc->config.flags & CONFIG_HIGH_FLAG)
526 wpc->block_samples /= 2;
527
528 if (wpc->config.num_channels == 1)
529 wpc->block_samples *= 2;
530
531 while (wpc->block_samples > 12000 && (int64_t) wpc->block_samples * wpc->config.num_channels > 300000)
532 wpc->block_samples /= 2;
533 }
534 else {
535 int divisor = (wpc->config.flags & CONFIG_HIGH_FLAG) ? 2 : 4;
536
537 while (wpc->config.sample_rate % divisor)
538 divisor--;
539
540 wpc->block_samples = wpc->config.sample_rate / divisor;
541
542 while (wpc->block_samples > 12000 && (int64_t) wpc->block_samples * wpc->config.num_channels > 75000)
543 wpc->block_samples /= 2;
544
545 while ((int64_t) wpc->block_samples * wpc->config.num_channels < 20000)
546 wpc->block_samples *= 2;
547 }
548
549 if (wpc->config.block_samples) {
550 if ((wpc->config.flags & CONFIG_MERGE_BLOCKS) &&
551 wpc->block_samples > (uint32_t) wpc->config.block_samples) {
552 wpc->block_boundary = wpc->config.block_samples;
553 wpc->block_samples /= wpc->config.block_samples;
554 wpc->block_samples *= wpc->config.block_samples;
555 }
556 else
557 wpc->block_samples = wpc->config.block_samples;
558 }
559
560 wpc->ave_block_samples = wpc->block_samples;
561 wpc->max_samples = wpc->block_samples + (wpc->block_samples >> 1);
562
563 for (wpc->current_stream = 0; wpc->current_stream < wpc->num_streams; wpc->current_stream++) {
564 WavpackStream *wps = wpc->streams [wpc->current_stream];
565
566 wps->sample_buffer = malloc (wpc->max_samples * (wps->wphdr.flags & MONO_FLAG ? 4 : 8));
567
568 #ifdef ENABLE_DSD
569 if (wps->wphdr.flags & DSD_FLAG)
570 pack_dsd_init (wpc);
571 else
572 #endif
573 pack_init (wpc);
574 }
575
576 return TRUE;
577 }
578
579 // Pack the specified samples. Samples must be stored in longs in the native
580 // endian format of the executing processor. The number of samples specified
581 // indicates composite samples (sometimes called "frames"). So, the actual
582 // number of data points would be this "sample_count" times the number of
583 // channels. Note that samples are accumulated here until enough exist to
584 // create a complete WavPack block (or several blocks for multichannel audio).
585 // If an application wants to break a block at a specific sample, then it must
586 // simply call WavpackFlushSamples() to force an early termination. Completed
587 // WavPack blocks are send to the function provided in the initial call to
588 // WavpackOpenFileOutput(). A return of FALSE indicates an error.
589
590 static int pack_streams (WavpackContext *wpc, uint32_t block_samples);
591 static int create_riff_header (WavpackContext *wpc, int64_t total_samples, void *outbuffer);
592
WavpackPackSamples(WavpackContext * wpc,int32_t * sample_buffer,uint32_t sample_count)593 int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count)
594 {
595 int nch = wpc->config.num_channels;
596
597 while (sample_count) {
598 int32_t *source_pointer = sample_buffer;
599 unsigned int samples_to_copy;
600
601 if (!wpc->riff_header_added && !wpc->riff_header_created && !wpc->file_format) {
602 char riff_header [128];
603
604 if (!add_to_metadata (wpc, riff_header, create_riff_header (wpc, wpc->total_samples, riff_header), ID_RIFF_HEADER))
605 return FALSE;
606 }
607
608 if (wpc->acc_samples + sample_count > wpc->max_samples)
609 samples_to_copy = wpc->max_samples - wpc->acc_samples;
610 else
611 samples_to_copy = sample_count;
612
613 for (wpc->current_stream = 0; wpc->current_stream < wpc->num_streams; wpc->current_stream++) {
614 WavpackStream *wps = wpc->streams [wpc->current_stream];
615 int32_t *dptr, *sptr, cnt;
616
617 dptr = wps->sample_buffer + wpc->acc_samples * (wps->wphdr.flags & MONO_FLAG ? 1 : 2);
618 sptr = source_pointer;
619 cnt = samples_to_copy;
620
621 // This code used to just copy the 32-bit samples regardless of the actual size with the
622 // assumption that the caller had properly sign-extended the values (if they were smaller
623 // than 32 bits). However, several people have discovered that if the data isn't properly
624 // sign extended then ugly things happen (e.g. CRC errors that show up only on decode).
625 // To prevent this, we now explicitly sign-extend samples smaller than 32-bit when we
626 // copy, and the performance hit from doing this is very small (generally < 1%).
627
628 if (wps->wphdr.flags & MONO_FLAG) {
629 switch (wpc->config.bytes_per_sample) {
630 case 1:
631 while (cnt--) {
632 *dptr++ = (signed char) *sptr;
633 sptr += nch;
634 }
635
636 break;
637
638 case 2:
639 while (cnt--) {
640 *dptr++ = (int16_t) *sptr;
641 sptr += nch;
642 }
643
644 break;
645
646 case 3:
647 while (cnt--) {
648 *dptr++ = (int32_t)((uint32_t)*sptr << 8) >> 8;
649 sptr += nch;
650 }
651
652 break;
653
654 default:
655 while (cnt--) {
656 *dptr++ = *sptr;
657 sptr += nch;
658 }
659 }
660
661 source_pointer++;
662 }
663 else {
664 switch (wpc->config.bytes_per_sample) {
665 case 1:
666 while (cnt--) {
667 *dptr++ = (signed char) sptr [0];
668 *dptr++ = (signed char) sptr [1];
669 sptr += nch;
670 }
671
672 break;
673
674 case 2:
675 while (cnt--) {
676 *dptr++ = (int16_t) sptr [0];
677 *dptr++ = (int16_t) sptr [1];
678 sptr += nch;
679 }
680
681 break;
682
683 case 3:
684 while (cnt--) {
685 *dptr++ = (int32_t)((uint32_t)sptr [0] << 8) >> 8;
686 *dptr++ = (int32_t)((uint32_t)sptr [1] << 8) >> 8;
687 sptr += nch;
688 }
689
690 break;
691
692 default:
693 while (cnt--) {
694 *dptr++ = sptr [0];
695 *dptr++ = sptr [1];
696 sptr += nch;
697 }
698 }
699
700 source_pointer += 2;
701 }
702 }
703
704 sample_buffer += samples_to_copy * nch;
705 sample_count -= samples_to_copy;
706
707 if ((wpc->acc_samples += samples_to_copy) == wpc->max_samples &&
708 !pack_streams (wpc, wpc->block_samples))
709 return FALSE;
710 }
711
712 return TRUE;
713 }
714
715 // Flush all accumulated samples into WavPack blocks. This is normally called
716 // after all samples have been sent to WavpackPackSamples(), but can also be
717 // called to terminate a WavPack block at a specific sample (in other words it
718 // is possible to continue after this operation). This is also called to
719 // dump non-audio blocks like those holding metadata for various purposes.
720 // A return of FALSE indicates an error.
721
WavpackFlushSamples(WavpackContext * wpc)722 int WavpackFlushSamples (WavpackContext *wpc)
723 {
724 while (wpc->acc_samples) {
725 uint32_t block_samples;
726
727 if (wpc->acc_samples > wpc->block_samples)
728 block_samples = wpc->acc_samples / 2;
729 else
730 block_samples = wpc->acc_samples;
731
732 if (!pack_streams (wpc, block_samples))
733 return FALSE;
734 }
735
736 if (wpc->metacount)
737 write_metadata_block (wpc);
738
739 return TRUE;
740 }
741
742 // Note: The following function is no longer required because a proper wav
743 // header is now automatically generated for the application. However, if the
744 // application wants to generate its own header or wants to include additional
745 // chunks, then this function can still be used in which case the automatic
746 // wav header generation is suppressed.
747
748 // Add wrapper (currently RIFF only) to WavPack blocks. This should be called
749 // before sending any audio samples for the RIFF header or after all samples
750 // have been sent for any RIFF trailer. WavpackFlushSamples() should be called
751 // between sending the last samples and calling this for trailer data to make
752 // sure that headers and trailers don't get mixed up in very short files. If
753 // the exact contents of the RIFF header are not known because, for example,
754 // the file duration is uncertain or trailing chunks are possible, simply write
755 // a "dummy" header of the correct length. When all data has been written it
756 // will be possible to read the first block written and update the header
757 // directly. An example of this can be found in the Audition filter. A
758 // return of FALSE indicates an error.
759
WavpackAddWrapper(WavpackContext * wpc,void * data,uint32_t bcount)760 int WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount)
761 {
762 int64_t index = WavpackGetSampleIndex64 (wpc);
763 unsigned char meta_id;
764
765 if (!index || index == -1) {
766 wpc->riff_header_added = TRUE;
767 meta_id = wpc->file_format ? ID_ALT_HEADER : ID_RIFF_HEADER;
768 }
769 else {
770 wpc->riff_trailer_bytes += bcount;
771 meta_id = wpc->file_format ? ID_ALT_TRAILER : ID_RIFF_TRAILER;
772 }
773
774 return add_to_metadata (wpc, data, bcount, meta_id);
775 }
776
777 // Store computed MD5 sum in WavPack metadata. Note that the user must compute
778 // the 16 byte sum; it is not done here. A return of FALSE indicates an error.
779 // If any of the lower 8 bits of qmode are set, then this MD5 is stored with
780 // a metadata ID that old decoders do not recognize (because they would not
781 // interpret the qmode and would therefore fail the verification).
782
WavpackStoreMD5Sum(WavpackContext * wpc,unsigned char data[16])783 int WavpackStoreMD5Sum (WavpackContext *wpc, unsigned char data [16])
784 {
785 return add_to_metadata (wpc, data, 16, (wpc->config.qmode & 0xff) ? ID_ALT_MD5_CHECKSUM : ID_MD5_CHECKSUM);
786 }
787
788 #pragma pack(push,4)
789
790 typedef struct {
791 char ckID [4];
792 uint64_t chunkSize64;
793 } CS64Chunk;
794
795 typedef struct {
796 uint64_t riffSize64, dataSize64, sampleCount64;
797 uint32_t tableLength;
798 } DS64Chunk;
799
800 typedef struct {
801 char ckID [4];
802 uint32_t ckSize;
803 char junk [28];
804 } JunkChunk;
805
806 #pragma pack(pop)
807
808 #define DS64ChunkFormat "DDDL"
809
create_riff_header(WavpackContext * wpc,int64_t total_samples,void * outbuffer)810 static int create_riff_header (WavpackContext *wpc, int64_t total_samples, void *outbuffer)
811 {
812 int do_rf64 = 0, write_junk = 1;
813 ChunkHeader ds64hdr, datahdr, fmthdr;
814 char *outptr = outbuffer;
815 RiffChunkHeader riffhdr;
816 DS64Chunk ds64_chunk;
817 JunkChunk junkchunk;
818 WaveHeader wavhdr;
819
820 int64_t total_data_bytes, total_riff_bytes;
821 int32_t channel_mask = wpc->config.channel_mask;
822 int32_t sample_rate = wpc->config.sample_rate;
823 int bytes_per_sample = wpc->config.bytes_per_sample;
824 int bits_per_sample = wpc->config.bits_per_sample;
825 int format = (wpc->config.float_norm_exp) ? 3 : 1;
826 int num_channels = wpc->config.num_channels;
827 int wavhdrsize = 16;
828
829 wpc->riff_header_created = TRUE;
830
831 if (format == 3 && wpc->config.float_norm_exp != 127) {
832 strcpy (wpc->error_message, "can't create valid RIFF wav header for non-normalized floating data!");
833 return FALSE;
834 }
835
836 if (total_samples == -1)
837 total_samples = 0x7ffff000 / (bytes_per_sample * num_channels);
838
839 total_data_bytes = total_samples * bytes_per_sample * num_channels;
840
841 if (total_data_bytes > 0xff000000) {
842 write_junk = 0;
843 do_rf64 = 1;
844 }
845
846 CLEAR (wavhdr);
847
848 wavhdr.FormatTag = format;
849 wavhdr.NumChannels = num_channels;
850 wavhdr.SampleRate = sample_rate;
851 wavhdr.BytesPerSecond = sample_rate * num_channels * bytes_per_sample;
852 wavhdr.BlockAlign = bytes_per_sample * num_channels;
853 wavhdr.BitsPerSample = bits_per_sample;
854
855 if (num_channels > 2 || channel_mask != 0x5 - num_channels) {
856 wavhdrsize = sizeof (wavhdr);
857 wavhdr.cbSize = 22;
858 wavhdr.ValidBitsPerSample = bits_per_sample;
859 wavhdr.SubFormat = format;
860 wavhdr.ChannelMask = channel_mask;
861 wavhdr.FormatTag = 0xfffe;
862 wavhdr.BitsPerSample = bytes_per_sample * 8;
863 wavhdr.GUID [4] = 0x10;
864 wavhdr.GUID [6] = 0x80;
865 wavhdr.GUID [9] = 0xaa;
866 wavhdr.GUID [11] = 0x38;
867 wavhdr.GUID [12] = 0x9b;
868 wavhdr.GUID [13] = 0x71;
869 }
870
871 memcpy (riffhdr.ckID, do_rf64 ? "RF64" : "RIFF", sizeof (riffhdr.ckID));
872 memcpy (riffhdr.formType, "WAVE", sizeof (riffhdr.formType));
873 total_riff_bytes = sizeof (riffhdr) + wavhdrsize + sizeof (datahdr) + total_data_bytes + wpc->riff_trailer_bytes;
874 if (do_rf64) total_riff_bytes += sizeof (ds64hdr) + sizeof (ds64_chunk);
875 if (write_junk) total_riff_bytes += sizeof (junkchunk);
876 memcpy (fmthdr.ckID, "fmt ", sizeof (fmthdr.ckID));
877 memcpy (datahdr.ckID, "data", sizeof (datahdr.ckID));
878 fmthdr.ckSize = wavhdrsize;
879
880 if (write_junk) {
881 CLEAR (junkchunk);
882 memcpy (junkchunk.ckID, "junk", sizeof (junkchunk.ckID));
883 junkchunk.ckSize = sizeof (junkchunk) - 8;
884 WavpackNativeToLittleEndian (&junkchunk, ChunkHeaderFormat);
885 }
886
887 if (do_rf64) {
888 memcpy (ds64hdr.ckID, "ds64", sizeof (ds64hdr.ckID));
889 ds64hdr.ckSize = sizeof (ds64_chunk);
890 CLEAR (ds64_chunk);
891 ds64_chunk.riffSize64 = total_riff_bytes;
892 ds64_chunk.dataSize64 = total_data_bytes;
893 ds64_chunk.sampleCount64 = total_samples;
894 riffhdr.ckSize = (uint32_t) -1;
895 datahdr.ckSize = (uint32_t) -1;
896 WavpackNativeToLittleEndian (&ds64hdr, ChunkHeaderFormat);
897 WavpackNativeToLittleEndian (&ds64_chunk, DS64ChunkFormat);
898 }
899 else {
900 riffhdr.ckSize = (uint32_t) total_riff_bytes;
901 datahdr.ckSize = (uint32_t) total_data_bytes;
902 }
903
904 WavpackNativeToLittleEndian (&riffhdr, ChunkHeaderFormat);
905 WavpackNativeToLittleEndian (&fmthdr, ChunkHeaderFormat);
906 WavpackNativeToLittleEndian (&wavhdr, WaveHeaderFormat);
907 WavpackNativeToLittleEndian (&datahdr, ChunkHeaderFormat);
908
909 // write the RIFF chunks up to just before the data starts
910
911 outptr = (char *) memcpy (outptr, &riffhdr, sizeof (riffhdr)) + sizeof (riffhdr);
912
913 if (do_rf64) {
914 outptr = (char *) memcpy (outptr, &ds64hdr, sizeof (ds64hdr)) + sizeof (ds64hdr);
915 outptr = (char *) memcpy (outptr, &ds64_chunk, sizeof (ds64_chunk)) + sizeof (ds64_chunk);
916 }
917
918 if (write_junk)
919 outptr = (char *) memcpy (outptr, &junkchunk, sizeof (junkchunk)) + sizeof (junkchunk);
920
921 outptr = (char *) memcpy (outptr, &fmthdr, sizeof (fmthdr)) + sizeof (fmthdr);
922 outptr = (char *) memcpy (outptr, &wavhdr, wavhdrsize) + wavhdrsize;
923 outptr = (char *) memcpy (outptr, &datahdr, sizeof (datahdr)) + sizeof (datahdr);
924
925 return (int)(outptr - (char *) outbuffer);
926 }
927
928 static int block_add_checksum (unsigned char *buffer_start, unsigned char *buffer_end, int bytes);
929
pack_streams(WavpackContext * wpc,uint32_t block_samples)930 static int pack_streams (WavpackContext *wpc, uint32_t block_samples)
931 {
932 uint32_t max_blocksize, max_chans = 1, bcount;
933 unsigned char *outbuff, *outend, *out2buff, *out2end;
934 int result = TRUE, i;
935
936 // for calculating output (block) buffer size, first see if any streams are stereo
937
938 for (i = 0; i < wpc->num_streams; i++)
939 if (!(wpc->streams [i]->wphdr.flags & MONO_FLAG)) {
940 max_chans = 2;
941 break;
942 }
943
944 // then calculate maximum size based on bytes / sample
945
946 max_blocksize = block_samples * max_chans * ((wpc->streams [0]->wphdr.flags & BYTES_STORED) + 1);
947
948 // add margin based on how much "negative" compression is possible with pathological audio
949
950 if ((wpc->config.flags & CONFIG_FLOAT_DATA) && !(wpc->config.flags & CONFIG_SKIP_WVX))
951 max_blocksize += max_blocksize; // 100% margin for lossless float data
952 else
953 max_blocksize += max_blocksize >> 2; // otherwise 25% margin for everything else
954
955 max_blocksize += wpc->metabytes + 1024; // finally, add metadata & another 1K margin
956 max_blocksize += max_blocksize & 1; // and make sure it's even so we detect overflow
957
958 out2buff = (wpc->wvc_flag) ? malloc (max_blocksize) : NULL;
959 out2end = out2buff + max_blocksize;
960 outbuff = malloc (max_blocksize);
961 outend = outbuff + max_blocksize;
962
963 for (wpc->current_stream = 0; wpc->current_stream < wpc->num_streams; wpc->current_stream++) {
964 WavpackStream *wps = wpc->streams [wpc->current_stream];
965 uint32_t flags = wps->wphdr.flags;
966
967 flags &= ~MAG_MASK;
968 flags += (1U << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7);
969
970 SET_BLOCK_INDEX (wps->wphdr, wps->sample_index);
971 wps->wphdr.block_samples = block_samples;
972 wps->wphdr.flags = flags;
973 wps->block2buff = out2buff;
974 wps->block2end = out2end;
975 wps->blockbuff = outbuff;
976 wps->blockend = outend;
977
978 #ifdef ENABLE_DSD
979 if (flags & DSD_FLAG)
980 result = pack_dsd_block (wpc, wps->sample_buffer);
981 else
982 #endif
983 result = pack_block (wpc, wps->sample_buffer);
984
985 if (result) {
986 result = block_add_checksum (outbuff, outend, (flags & HYBRID_FLAG) ? 2 : 4);
987
988 if (result && out2buff)
989 result = block_add_checksum (out2buff, out2end, 2);
990 }
991
992 wps->blockbuff = wps->block2buff = NULL;
993
994 if (wps->wphdr.block_samples != block_samples)
995 block_samples = wps->wphdr.block_samples;
996
997 if (!result) {
998 strcpy (wpc->error_message, "output buffer overflowed!");
999 break;
1000 }
1001
1002 bcount = ((WavpackHeader *) outbuff)->ckSize + 8;
1003 WavpackNativeToLittleEndian ((WavpackHeader *) outbuff, WavpackHeaderFormat);
1004 result = wpc->blockout (wpc->wv_out, outbuff, bcount);
1005
1006 if (!result) {
1007 strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
1008 break;
1009 }
1010
1011 wpc->filelen += bcount;
1012
1013 if (out2buff) {
1014 bcount = ((WavpackHeader *) out2buff)->ckSize + 8;
1015 WavpackNativeToLittleEndian ((WavpackHeader *) out2buff, WavpackHeaderFormat);
1016 result = wpc->blockout (wpc->wvc_out, out2buff, bcount);
1017
1018 if (!result) {
1019 strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
1020 break;
1021 }
1022
1023 wpc->file2len += bcount;
1024 }
1025
1026 if (wpc->acc_samples != block_samples)
1027 memmove (wps->sample_buffer, wps->sample_buffer + block_samples * (flags & MONO_FLAG ? 1 : 2),
1028 (wpc->acc_samples - block_samples) * sizeof (int32_t) * (flags & MONO_FLAG ? 1 : 2));
1029 }
1030
1031 wpc->current_stream = 0;
1032 wpc->ave_block_samples = (wpc->ave_block_samples * 0x7 + block_samples + 0x4) >> 3;
1033 wpc->acc_samples -= block_samples;
1034 free (outbuff);
1035
1036 if (out2buff)
1037 free (out2buff);
1038
1039 return result;
1040 }
1041
1042 // Given the pointer to the first block written (to either a .wv or .wvc file),
1043 // update the block with the actual number of samples written. If the wav
1044 // header was generated by the library, then it is updated also. This should
1045 // be done if WavpackSetConfiguration() was called with an incorrect number
1046 // of samples (or -1). It is the responsibility of the application to read and
1047 // rewrite the block. An example of this can be found in the Audition filter.
1048
1049 static void block_update_checksum (unsigned char *buffer_start);
1050
WavpackUpdateNumSamples(WavpackContext * wpc,void * first_block)1051 void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block)
1052 {
1053 uint32_t wrapper_size;
1054
1055 WavpackLittleEndianToNative (first_block, WavpackHeaderFormat);
1056 SET_TOTAL_SAMPLES (* (WavpackHeader *) first_block, WavpackGetSampleIndex64 (wpc));
1057
1058 if (wpc->riff_header_created && WavpackGetWrapperLocation (first_block, &wrapper_size)) {
1059 unsigned char riff_header [128];
1060
1061 if (wrapper_size == create_riff_header (wpc, WavpackGetSampleIndex64 (wpc), riff_header))
1062 memcpy (WavpackGetWrapperLocation (first_block, NULL), riff_header, wrapper_size);
1063 }
1064
1065 block_update_checksum (first_block);
1066 WavpackNativeToLittleEndian (first_block, WavpackHeaderFormat);
1067 }
1068
1069 // Note: The following function is no longer required because the wav header
1070 // automatically generated for the application will also be updated by
1071 // WavpackUpdateNumSamples (). However, if the application wants to generate
1072 // its own header or wants to include additional chunks, then this function
1073 // still must be used to update the application generated header.
1074
1075 // Given the pointer to the first block written to a WavPack file, this
1076 // function returns the location of the stored RIFF header that was originally
1077 // written with WavpackAddWrapper(). This would normally be used to update
1078 // the wav header to indicate that a different number of samples was actually
1079 // written or if additional RIFF chunks are written at the end of the file.
1080 // The "size" parameter can be set to non-NULL to obtain the exact size of the
1081 // RIFF header, and the function will return FALSE if the header is not found
1082 // in the block's metadata (or it is not a valid WavPack block). It is the
1083 // responsibility of the application to read and rewrite the block. An example
1084 // of this can be found in the Audition filter.
1085
1086 static void *find_metadata (void *wavpack_block, int desired_id, uint32_t *size);
1087
WavpackGetWrapperLocation(void * first_block,uint32_t * size)1088 void *WavpackGetWrapperLocation (void *first_block, uint32_t *size)
1089 {
1090 void *loc;
1091
1092 WavpackLittleEndianToNative (first_block, WavpackHeaderFormat);
1093 loc = find_metadata (first_block, ID_RIFF_HEADER, size);
1094
1095 if (!loc)
1096 loc = find_metadata (first_block, ID_ALT_HEADER, size);
1097
1098 WavpackNativeToLittleEndian (first_block, WavpackHeaderFormat);
1099
1100 return loc;
1101 }
1102
find_metadata(void * wavpack_block,int desired_id,uint32_t * size)1103 static void *find_metadata (void *wavpack_block, int desired_id, uint32_t *size)
1104 {
1105 WavpackHeader *wphdr = wavpack_block;
1106 unsigned char *dp, meta_id, c1, c2;
1107 int32_t bcount, meta_bc;
1108
1109 if (strncmp (wphdr->ckID, "wvpk", 4))
1110 return NULL;
1111
1112 bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8;
1113 dp = (unsigned char *)(wphdr + 1);
1114
1115 while (bcount >= 2) {
1116 meta_id = *dp++;
1117 c1 = *dp++;
1118
1119 meta_bc = c1 << 1;
1120 bcount -= 2;
1121
1122 if (meta_id & ID_LARGE) {
1123 if (bcount < 2)
1124 break;
1125
1126 c1 = *dp++;
1127 c2 = *dp++;
1128 meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
1129 bcount -= 2;
1130 }
1131
1132 if ((meta_id & ID_UNIQUE) == desired_id) {
1133 if ((bcount - meta_bc) >= 0) {
1134 if (size)
1135 *size = meta_bc - ((meta_id & ID_ODD_SIZE) ? 1 : 0);
1136
1137 return dp;
1138 }
1139 else
1140 return NULL;
1141 }
1142
1143 bcount -= meta_bc;
1144 dp += meta_bc;
1145 }
1146
1147 return NULL;
1148 }
1149
copy_metadata(WavpackMetadata * wpmd,unsigned char * buffer_start,unsigned char * buffer_end)1150 int copy_metadata (WavpackMetadata *wpmd, unsigned char *buffer_start, unsigned char *buffer_end)
1151 {
1152 uint32_t mdsize = wpmd->byte_length + (wpmd->byte_length & 1);
1153 WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
1154
1155 mdsize += (wpmd->byte_length > 510) ? 4 : 2;
1156 buffer_start += wphdr->ckSize + 8;
1157
1158 if (buffer_start + mdsize >= buffer_end)
1159 return FALSE;
1160
1161 buffer_start [0] = wpmd->id | (wpmd->byte_length & 1 ? ID_ODD_SIZE : 0);
1162 buffer_start [1] = (wpmd->byte_length + 1) >> 1;
1163
1164 if (wpmd->byte_length > 510) {
1165 buffer_start [0] |= ID_LARGE;
1166 buffer_start [2] = (wpmd->byte_length + 1) >> 9;
1167 buffer_start [3] = (wpmd->byte_length + 1) >> 17;
1168 }
1169
1170 if (wpmd->data && wpmd->byte_length) {
1171 memcpy (buffer_start + (wpmd->byte_length > 510 ? 4 : 2), wpmd->data, wpmd->byte_length);
1172
1173 if (wpmd->byte_length & 1) // if size is odd, make sure pad byte is a zero
1174 buffer_start [mdsize - 1] = 0;
1175 }
1176
1177 wphdr->ckSize += mdsize;
1178 return TRUE;
1179 }
1180
add_to_metadata(WavpackContext * wpc,void * data,uint32_t bcount,unsigned char id)1181 static int add_to_metadata (WavpackContext *wpc, void *data, uint32_t bcount, unsigned char id)
1182 {
1183 WavpackMetadata *mdp;
1184 unsigned char *src = data;
1185
1186 while (bcount) {
1187 if (wpc->metacount) {
1188 uint32_t bc = bcount;
1189
1190 mdp = wpc->metadata + wpc->metacount - 1;
1191
1192 if (mdp->id == id) {
1193 if (wpc->metabytes + bcount > 1000000)
1194 bc = 1000000 - wpc->metabytes;
1195
1196 mdp->data = realloc (mdp->data, mdp->byte_length + bc);
1197 memcpy ((char *) mdp->data + mdp->byte_length, src, bc);
1198 mdp->byte_length += bc;
1199 wpc->metabytes += bc;
1200 bcount -= bc;
1201 src += bc;
1202
1203 if (wpc->metabytes >= 1000000 && !write_metadata_block (wpc))
1204 return FALSE;
1205 }
1206 }
1207
1208 if (bcount) {
1209 wpc->metadata = realloc (wpc->metadata, (wpc->metacount + 1) * sizeof (WavpackMetadata));
1210 mdp = wpc->metadata + wpc->metacount++;
1211 mdp->byte_length = 0;
1212 mdp->data = NULL;
1213 mdp->id = id;
1214 }
1215 }
1216
1217 return TRUE;
1218 }
1219
write_metadata(WavpackMetadata * wpmd,char * outdata)1220 static char *write_metadata (WavpackMetadata *wpmd, char *outdata)
1221 {
1222 unsigned char id = wpmd->id, wordlen [3];
1223
1224 wordlen [0] = (wpmd->byte_length + 1) >> 1;
1225 wordlen [1] = (wpmd->byte_length + 1) >> 9;
1226 wordlen [2] = (wpmd->byte_length + 1) >> 17;
1227
1228 if (wpmd->byte_length & 1)
1229 id |= ID_ODD_SIZE;
1230
1231 if (wordlen [1] || wordlen [2])
1232 id |= ID_LARGE;
1233
1234 *outdata++ = id;
1235 *outdata++ = wordlen [0];
1236
1237 if (id & ID_LARGE) {
1238 *outdata++ = wordlen [1];
1239 *outdata++ = wordlen [2];
1240 }
1241
1242 if (wpmd->data && wpmd->byte_length) {
1243 memcpy (outdata, wpmd->data, wpmd->byte_length);
1244 outdata += wpmd->byte_length;
1245
1246 if (wpmd->byte_length & 1)
1247 *outdata++ = 0;
1248 }
1249
1250 return outdata;
1251 }
1252
write_metadata_block(WavpackContext * wpc)1253 static int write_metadata_block (WavpackContext *wpc)
1254 {
1255 char *block_buff, *block_ptr;
1256 WavpackHeader *wphdr;
1257
1258 if (wpc->metacount) {
1259 int metacount = wpc->metacount, block_size = sizeof (WavpackHeader);
1260 WavpackMetadata *wpmdp = wpc->metadata;
1261
1262 while (metacount--) {
1263 block_size += wpmdp->byte_length + (wpmdp->byte_length & 1);
1264 block_size += (wpmdp->byte_length > 510) ? 4 : 2;
1265 wpmdp++;
1266 }
1267
1268 // allocate 6 extra bytes for 4-byte checksum (which we add last)
1269 wphdr = (WavpackHeader *) (block_buff = malloc (block_size + 6));
1270
1271 CLEAR (*wphdr);
1272 memcpy (wphdr->ckID, "wvpk", 4);
1273 SET_TOTAL_SAMPLES (*wphdr, wpc->total_samples);
1274 wphdr->version = wpc->stream_version;
1275 wphdr->ckSize = block_size - 8;
1276 wphdr->block_samples = 0;
1277
1278 block_ptr = (char *)(wphdr + 1);
1279
1280 wpmdp = wpc->metadata;
1281
1282 while (wpc->metacount) {
1283 block_ptr = write_metadata (wpmdp, block_ptr);
1284 wpc->metabytes -= wpmdp->byte_length;
1285 free_metadata (wpmdp++);
1286 wpc->metacount--;
1287 }
1288
1289 free (wpc->metadata);
1290 wpc->metadata = NULL;
1291 // add a 4-byte checksum here (increases block size by 6)
1292 block_add_checksum ((unsigned char *) block_buff, (unsigned char *) block_buff + (block_size += 6), 4);
1293 WavpackNativeToLittleEndian ((WavpackHeader *) block_buff, WavpackHeaderFormat);
1294
1295 if (!wpc->blockout (wpc->wv_out, block_buff, block_size)) {
1296 free (block_buff);
1297 strcpy (wpc->error_message, "can't write WavPack data, disk probably full!");
1298 return FALSE;
1299 }
1300
1301 free (block_buff);
1302 }
1303
1304 return TRUE;
1305 }
1306
free_metadata(WavpackMetadata * wpmd)1307 void free_metadata (WavpackMetadata *wpmd)
1308 {
1309 if (wpmd->data) {
1310 free (wpmd->data);
1311 wpmd->data = NULL;
1312 }
1313 }
1314
1315 // These two functions add or update the block checksums that were introduced in WavPack 5.0.
1316 // The presence of the checksum is indicated by a flag in the wavpack header (HAS_CHECKSUM)
1317 // and the actual metadata item should be the last one in the block, and can be either 2 or 4
1318 // bytes. Of course, older versions of the decoder will simply ignore both of these.
1319
block_add_checksum(unsigned char * buffer_start,unsigned char * buffer_end,int bytes)1320 static int block_add_checksum (unsigned char *buffer_start, unsigned char *buffer_end, int bytes)
1321 {
1322 WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
1323 #ifdef BITSTREAM_SHORTS
1324 uint16_t *csptr = (uint16_t*) buffer_start;
1325 #else
1326 unsigned char *csptr = buffer_start;
1327 #endif
1328 int bcount = wphdr->ckSize + 8, wcount;
1329 uint32_t csum = (uint32_t) -1;
1330
1331 if (bytes != 2 && bytes != 4)
1332 return FALSE;
1333
1334 if (bcount < sizeof (WavpackHeader) || (bcount & 1) || buffer_start + bcount + 2 + bytes > buffer_end)
1335 return FALSE;
1336
1337 wphdr->flags |= HAS_CHECKSUM;
1338 wphdr->ckSize += 2 + bytes;
1339 wcount = bcount >> 1;
1340
1341 #ifdef BITSTREAM_SHORTS
1342 while (wcount--)
1343 csum = (csum * 3) + *csptr++;
1344 #else
1345 WavpackNativeToLittleEndian ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
1346
1347 while (wcount--) {
1348 csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
1349 csptr += 2;
1350 }
1351
1352 WavpackLittleEndianToNative ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
1353 #endif
1354
1355 buffer_start += bcount;
1356 *buffer_start++ = ID_BLOCK_CHECKSUM;
1357 *buffer_start++ = bytes >> 1;
1358
1359 if (bytes == 4) {
1360 *buffer_start++ = csum;
1361 *buffer_start++ = csum >> 8;
1362 *buffer_start++ = csum >> 16;
1363 *buffer_start++ = csum >> 24;
1364 }
1365 else {
1366 csum ^= csum >> 16;
1367 *buffer_start++ = csum;
1368 *buffer_start++ = csum >> 8;
1369 }
1370
1371 return TRUE;
1372 }
1373
block_update_checksum(unsigned char * buffer_start)1374 static void block_update_checksum (unsigned char *buffer_start)
1375 {
1376 WavpackHeader *wphdr = (WavpackHeader *) buffer_start;
1377 unsigned char *dp, meta_id, c1, c2;
1378 uint32_t bcount, meta_bc;
1379
1380 if (!(wphdr->flags & HAS_CHECKSUM))
1381 return;
1382
1383 bcount = wphdr->ckSize - sizeof (WavpackHeader) + 8;
1384 dp = (unsigned char *)(wphdr + 1);
1385
1386 while (bcount >= 2) {
1387 meta_id = *dp++;
1388 c1 = *dp++;
1389
1390 meta_bc = c1 << 1;
1391 bcount -= 2;
1392
1393 if (meta_id & ID_LARGE) {
1394 if (bcount < 2)
1395 return;
1396
1397 c1 = *dp++;
1398 c2 = *dp++;
1399 meta_bc += ((uint32_t) c1 << 9) + ((uint32_t) c2 << 17);
1400 bcount -= 2;
1401 }
1402
1403 if (bcount < meta_bc)
1404 return;
1405
1406 if ((meta_id & ID_UNIQUE) == ID_BLOCK_CHECKSUM) {
1407 #ifdef BITSTREAM_SHORTS
1408 uint16_t *csptr = (uint16_t*) buffer_start;
1409 #else
1410 unsigned char *csptr = buffer_start;
1411 #endif
1412 int wcount = (int)(dp - 2 - buffer_start) >> 1;
1413 uint32_t csum = (uint32_t) -1;
1414
1415 if ((meta_id & ID_ODD_SIZE) || meta_bc < 2 || meta_bc > 4)
1416 return;
1417
1418 #ifdef BITSTREAM_SHORTS
1419 while (wcount--)
1420 csum = (csum * 3) + *csptr++;
1421 #else
1422 WavpackNativeToLittleEndian ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
1423
1424 while (wcount--) {
1425 csum = (csum * 3) + csptr [0] + (csptr [1] << 8);
1426 csptr += 2;
1427 }
1428
1429 WavpackLittleEndianToNative ((WavpackHeader *) buffer_start, WavpackHeaderFormat);
1430 #endif
1431
1432 if (meta_bc == 4) {
1433 *dp++ = csum;
1434 *dp++ = csum >> 8;
1435 *dp++ = csum >> 16;
1436 *dp++ = csum >> 24;
1437 return;
1438 }
1439 else {
1440 csum ^= csum >> 16;
1441 *dp++ = csum;
1442 *dp++ = csum >> 8;
1443 return;
1444 }
1445 }
1446
1447 bcount -= meta_bc;
1448 dp += meta_bc;
1449 }
1450 }
1451