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