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 // common_utils.c
10 
11 // This module provides a lot of the trivial WavPack API functions and several
12 // functions that are common to both reading and writing WavPack files (like
13 // WavpackCloseFile()). Functions here are restricted to those that have few
14 // external dependencies and this is done so that applications that statically
15 // link to the WavPack library (like the command-line utilities on Windows)
16 // do not need to include the entire library image if they only use a subset
17 // of it. This module will be loaded for ANY WavPack application.
18 
19 #include <stdlib.h>
20 #include <string.h>
21 #include <ctype.h>
22 
23 #include "wavpack_local.h"
24 
25 #ifndef LIBWAVPACK_VERSION_STRING
26 #include "wavpack_version.h"
27 #endif
28 
29 ///////////////////////////// local table storage ////////////////////////////
30 
31 const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
32     24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
33 
34 ///////////////////////////// executable code ////////////////////////////////
35 
36 // This function obtains general information about an open input file and
37 // returns a mask with the following bit values:
38 
39 // MODE_WVC:  a .wvc file has been found and will be used for lossless
40 // MODE_LOSSLESS:  file is lossless (either pure or hybrid)
41 // MODE_HYBRID:  file is hybrid mode (either lossy or lossless)
42 // MODE_FLOAT:  audio data is 32-bit ieee floating point
43 // MODE_VALID_TAG:  file contains a valid ID3v1 or APEv2 tag
44 // MODE_HIGH:  file was created in "high" mode (information only)
45 // MODE_FAST:  file was created in "fast" mode (information only)
46 // MODE_EXTRA:  file was created using "extra" mode (information only)
47 // MODE_APETAG:  file contains a valid APEv2 tag
48 // MODE_SFX:  file was created as a "self-extracting" executable
49 // MODE_VERY_HIGH:  file was created in the "very high" mode (or in
50 //                  the "high" mode prior to 4.4)
51 // MODE_MD5:  file contains an MD5 checksum
52 // MODE_XMODE:  level used for extra mode (1-6, 0=unknown)
53 // MODE_DNS:  dynamic noise shaping
54 
WavpackGetMode(WavpackContext * wpc)55 int WavpackGetMode (WavpackContext *wpc)
56 {
57     int mode = 0;
58 
59     if (wpc) {
60         if (wpc->config.flags & CONFIG_HYBRID_FLAG)
61             mode |= MODE_HYBRID;
62         else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
63             mode |= MODE_LOSSLESS;
64 
65         if (wpc->wvc_flag)
66             mode |= (MODE_LOSSLESS | MODE_WVC);
67 
68         if (wpc->lossy_blocks)
69             mode &= ~MODE_LOSSLESS;
70 
71         if (wpc->config.flags & CONFIG_FLOAT_DATA)
72             mode |= MODE_FLOAT;
73 
74         if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG)) {
75             mode |= MODE_HIGH;
76 
77             if ((wpc->config.flags & CONFIG_VERY_HIGH_FLAG) ||
78                 (wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.version < 0x405))
79                     mode |= MODE_VERY_HIGH;
80         }
81 
82         if (wpc->config.flags & CONFIG_FAST_FLAG)
83             mode |= MODE_FAST;
84 
85         if (wpc->config.flags & CONFIG_EXTRA_MODE)
86             mode |= (MODE_EXTRA | (wpc->config.xmode << 12));
87 
88         if (wpc->config.flags & CONFIG_CREATE_EXE)
89             mode |= MODE_SFX;
90 
91         if (wpc->config.flags & CONFIG_MD5_CHECKSUM)
92             mode |= MODE_MD5;
93 
94         if ((wpc->config.flags & CONFIG_HYBRID_FLAG) && (wpc->config.flags & CONFIG_DYNAMIC_SHAPING) &&
95             wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.version >= 0x407)
96                 mode |= MODE_DNS;
97 
98 #ifndef NO_TAGS
99         if (valid_tag (&wpc->m_tag)) {
100             mode |= MODE_VALID_TAG;
101 
102             if (valid_tag (&wpc->m_tag) == 'A')
103                 mode |= MODE_APETAG;
104         }
105 #endif
106 
107         mode |= (wpc->config.qmode << 16) & 0xFF0000;
108     }
109 
110     return mode;
111 }
112 
113 // This function obtains information about specific file features that were
114 // added for version 5.0, specifically qualifications added to support CAF
115 // and DSD files. Except for indicating the presence of DSD data, these
116 // bits are meant to simply indicate the format of the data in the original
117 // source file and do NOT indicate how the library will return the data to
118 // the appication (which is always the same). This means that in general an
119 // application that simply wants to play or process the audio data need not
120 // be concerned about these. If the file is DSD audio, then either of the
121 // QMDOE_DSD_LSB_FIRST or QMODE_DSD_MSB_FIRST bits will be set (but the
122 // DSD audio is always returned to the caller MSB first).
123 
124 // QMODE_BIG_ENDIAN        0x1     // big-endian data format (opposite of WAV format)
125 // QMODE_SIGNED_BYTES      0x2     // 8-bit audio data is signed (opposite of WAV format)
126 // QMODE_UNSIGNED_WORDS    0x4     // audio data (other than 8-bit) is unsigned (opposite of WAV format)
127 // QMODE_REORDERED_CHANS   0x8     // source channels were not Microsoft order, so they were reordered
128 // QMODE_DSD_LSB_FIRST     0x10    // DSD bytes, LSB first (most Sony .dsf files)
129 // QMODE_DSD_MSB_FIRST     0x20    // DSD bytes, MSB first (Philips .dff files)
130 // QMODE_DSD_IN_BLOCKS     0x40    // DSD data is blocked by channels (Sony .dsf only)
131 
WavpackGetQualifyMode(WavpackContext * wpc)132 int WavpackGetQualifyMode (WavpackContext *wpc)
133 {
134     return wpc->config.qmode & 0xFF;
135 }
136 
137 // This function returns a pointer to a string describing the last error
138 // generated by WavPack.
139 
WavpackGetErrorMessage(WavpackContext * wpc)140 char *WavpackGetErrorMessage (WavpackContext *wpc)
141 {
142     return wpc->error_message;
143 }
144 
145 // Get total number of samples contained in the WavPack file, or -1 if unknown
146 
WavpackGetNumSamples(WavpackContext * wpc)147 uint32_t WavpackGetNumSamples (WavpackContext *wpc)
148 {
149     return (uint32_t) WavpackGetNumSamples64 (wpc);
150 }
151 
WavpackGetNumSamples64(WavpackContext * wpc)152 int64_t WavpackGetNumSamples64 (WavpackContext *wpc)
153 {
154     return wpc ? wpc->total_samples : -1;
155 }
156 
157 // Get the current sample index position, or -1 if unknown
158 
WavpackGetSampleIndex(WavpackContext * wpc)159 uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
160 {
161     return (uint32_t) WavpackGetSampleIndex64 (wpc);
162 }
163 
WavpackGetSampleIndex64(WavpackContext * wpc)164 int64_t WavpackGetSampleIndex64 (WavpackContext *wpc)
165 {
166     if (wpc) {
167 #ifdef ENABLE_LEGACY
168         if (wpc->stream3)
169             return get_sample_index3 (wpc);
170         else if (wpc->streams && wpc->streams [0])
171             return wpc->streams [0]->sample_index;
172 #else
173         if (wpc->streams && wpc->streams [0])
174             return wpc->streams [0]->sample_index;
175 #endif
176     }
177 
178     return -1;
179 }
180 
181 // Get the number of errors encountered so far
182 
WavpackGetNumErrors(WavpackContext * wpc)183 int WavpackGetNumErrors (WavpackContext *wpc)
184 {
185     return wpc ? wpc->crc_errors : 0;
186 }
187 
188 // return TRUE if any uncorrected lossy blocks were actually written or read
189 
WavpackLossyBlocks(WavpackContext * wpc)190 int WavpackLossyBlocks (WavpackContext *wpc)
191 {
192     return wpc ? wpc->lossy_blocks : 0;
193 }
194 
195 // Calculate the progress through the file as a double from 0.0 (for begin)
196 // to 1.0 (for done). A return value of -1.0 indicates that the progress is
197 // unknown.
198 
WavpackGetProgress(WavpackContext * wpc)199 double WavpackGetProgress (WavpackContext *wpc)
200 {
201     if (wpc && wpc->total_samples != -1 && wpc->total_samples != 0)
202         return (double) WavpackGetSampleIndex64 (wpc) / wpc->total_samples;
203     else
204         return -1.0;
205 }
206 
207 // Return the total size of the WavPack file(s) in bytes.
208 
WavpackGetFileSize(WavpackContext * wpc)209 uint32_t WavpackGetFileSize (WavpackContext *wpc)
210 {
211     return (uint32_t) (wpc ? wpc->filelen + wpc->file2len : 0);
212 }
213 
WavpackGetFileSize64(WavpackContext * wpc)214 int64_t WavpackGetFileSize64 (WavpackContext *wpc)
215 {
216     return wpc ? wpc->filelen + wpc->file2len : 0;
217 }
218 
219 // Calculate the ratio of the specified WavPack file size to the size of the
220 // original audio data as a double greater than 0.0 and (usually) smaller than
221 // 1.0. A value greater than 1.0 represents "negative" compression and a
222 // return value of 0.0 indicates that the ratio cannot be determined.
223 
WavpackGetRatio(WavpackContext * wpc)224 double WavpackGetRatio (WavpackContext *wpc)
225 {
226     if (wpc && wpc->total_samples != -1 && wpc->filelen) {
227         double output_size = (double) wpc->total_samples * wpc->config.num_channels *
228             wpc->config.bytes_per_sample;
229         double input_size = (double) wpc->filelen + wpc->file2len;
230 
231         if (output_size >= 1.0 && input_size >= 1.0)
232             return input_size / output_size;
233     }
234 
235     return 0.0;
236 }
237 
238 // Calculate the average bitrate of the WavPack file in bits per second. A
239 // return of 0.0 indicates that the bitrate cannot be determined. An option is
240 // provided to use (or not use) any attendant .wvc file.
241 
WavpackGetAverageBitrate(WavpackContext * wpc,int count_wvc)242 double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc)
243 {
244     if (wpc && wpc->total_samples != -1 && wpc->filelen && WavpackGetSampleRate (wpc)) {
245         double output_time = (double) wpc->total_samples / WavpackGetSampleRate (wpc);
246         double input_size = (double) wpc->filelen + (count_wvc ? wpc->file2len : 0);
247 
248         if (output_time >= 0.1 && input_size >= 1.0)
249             return input_size * 8.0 / output_time;
250     }
251 
252     return 0.0;
253 }
254 
255 // Calculate the bitrate of the current WavPack file block in bits per second.
256 // This can be used for an "instant" bit display and gets updated from about
257 // 1 to 4 times per second. A return of 0.0 indicates that the bitrate cannot
258 // be determined.
259 
WavpackGetInstantBitrate(WavpackContext * wpc)260 double WavpackGetInstantBitrate (WavpackContext *wpc)
261 {
262     if (wpc && wpc->stream3)
263         return WavpackGetAverageBitrate (wpc, TRUE);
264 
265     if (wpc && wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.block_samples && WavpackGetSampleRate (wpc)) {
266         double output_time = (double) wpc->streams [0]->wphdr.block_samples / WavpackGetSampleRate (wpc);
267         double input_size = 0;
268         int si;
269 
270         for (si = 0; si < wpc->num_streams; ++si) {
271             if (wpc->streams [si]->blockbuff)
272                 input_size += ((WavpackHeader *) wpc->streams [si]->blockbuff)->ckSize;
273 
274             if (wpc->streams [si]->block2buff)
275                 input_size += ((WavpackHeader *) wpc->streams [si]->block2buff)->ckSize;
276         }
277 
278         if (output_time > 0.0 && input_size >= 1.0)
279             return input_size * 8.0 / output_time;
280     }
281 
282     return 0.0;
283 }
284 
285 // This function allows retrieving the Core Audio File channel layout, many of which do not
286 // conform to the Microsoft ordering standard that WavPack requires internally (at least for
287 // those channels present in the "channel mask"). In addition to the layout tag, this function
288 // returns the reordering string (if stored in the file) to allow the unpacker to reorder the
289 // channels back to the specified layout (if it wants to restore the CAF order). The number of
290 // channels in the layout is determined from the lower nybble of the layout word (and should
291 // probably match the number of channels in the file), and if a reorder string is requested
292 // then that much space must be allocated. Note that all the reordering is actually done
293 // outside of this library, and that if reordering is done then the appropriate qmode bit
294 // will be set.
295 //
296 // Note: Normally this function would not be used by an application unless it specifically
297 // wanted to restore a non-standard channel order (to check an MD5, for example) or obtain
298 // the Core Audio channel layout ID. For simple file decoding for playback, the channel_mask
299 // should provide all the information required unless there are non-Microsoft channels
300 // involved, in which case WavpackGetChannelIdentities() will provide the identities of
301 // the other channels (if they are known).
302 
WavpackGetChannelLayout(WavpackContext * wpc,unsigned char * reorder)303 uint32_t WavpackGetChannelLayout (WavpackContext *wpc, unsigned char *reorder)
304 {
305     if ((wpc->channel_layout & 0xff) && wpc->channel_reordering && reorder)
306         memcpy (reorder, wpc->channel_reordering, wpc->channel_layout & 0xff);
307 
308     return wpc->channel_layout;
309 }
310 
311 // This function provides the identities of ALL the channels in the file, including the
312 // standard Microsoft channels (which come first, in order, and are numbered 1-18) and also
313 // any non-Microsoft channels (which can be in any order and have values from 33-254). The
314 // value 0x00 is invalid and 0xFF indicates an "unknown" or "unnassigned" channel. The
315 // string is NULL terminated so the caller must supply enough space for the number
316 // of channels indicated by WavpackGetNumChannels(), plus one.
317 //
318 // Note that this function returns the actual order of the channels in the Wavpack file
319 // (i.e., the order returned by WavpackUnpackSamples()). If the file includes a "reordering"
320 // string because the source file was not in Microsoft order that is NOT taken into account
321 // here and really only needs to be considered if doing an MD5 verification or if it's
322 // required to restore the original order/file (like wvunpack does).
323 
WavpackGetChannelIdentities(WavpackContext * wpc,unsigned char * identities)324 void WavpackGetChannelIdentities (WavpackContext *wpc, unsigned char *identities)
325 {
326     int num_channels = wpc->config.num_channels, index = 1;
327     uint32_t channel_mask = wpc->config.channel_mask;
328     unsigned char *src = wpc->channel_identities;
329 
330     while (num_channels--) {
331         if (channel_mask) {
332             while (!(channel_mask & 1)) {
333                 channel_mask >>= 1;
334                 index++;
335             }
336 
337             *identities++ = index++;
338             channel_mask >>= 1;
339         }
340         else if (src && *src)
341             *identities++ = *src++;
342         else
343             *identities++ = 0xff;
344     }
345 
346     *identities = 0;
347 }
348 
349 // For local use only. Install a callback to be executed when WavpackCloseFile() is called,
350 // usually used to dump some statistics accumulated during encode or decode.
351 
install_close_callback(WavpackContext * wpc,void cb_func (void * wpc))352 void install_close_callback (WavpackContext *wpc, void cb_func (void *wpc))
353 {
354     wpc->close_callback = cb_func;
355 }
356 
357 // Close the specified WavPack file and release all resources used by it.
358 // Returns NULL.
359 
WavpackCloseFile(WavpackContext * wpc)360 WavpackContext *WavpackCloseFile (WavpackContext *wpc)
361 {
362     if (wpc->close_callback)
363         wpc->close_callback (wpc);
364 
365     if (wpc->streams) {
366         free_streams (wpc);
367 
368         if (wpc->streams [0])
369             free (wpc->streams [0]);
370 
371         free (wpc->streams);
372     }
373 
374 #ifdef ENABLE_LEGACY
375     if (wpc->stream3)
376         free_stream3 (wpc);
377 #endif
378 
379     if (wpc->reader && wpc->reader->close && wpc->wv_in)
380         wpc->reader->close (wpc->wv_in);
381 
382     if (wpc->reader && wpc->reader->close && wpc->wvc_in)
383         wpc->reader->close (wpc->wvc_in);
384 
385     WavpackFreeWrapper (wpc);
386 
387     if (wpc->metadata) {
388         int i;
389 
390         for (i = 0; i < wpc->metacount; ++i)
391             if (wpc->metadata [i].data)
392                 free (wpc->metadata [i].data);
393 
394         free (wpc->metadata);
395     }
396 
397     if (wpc->channel_identities)
398         free (wpc->channel_identities);
399 
400     if (wpc->channel_reordering)
401         free (wpc->channel_reordering);
402 
403 #ifndef NO_TAGS
404     free_tag (&wpc->m_tag);
405 #endif
406 
407 #ifdef ENABLE_DSD
408     if (wpc->decimation_context)
409         decimate_dsd_destroy (wpc->decimation_context);
410 #endif
411 
412     free (wpc);
413 
414     return NULL;
415 }
416 
417 // These routines are used to access (and free) header and trailer data that
418 // was retrieved from the Wavpack file. The header will be available before
419 // the samples are decoded and the trailer will be available after all samples
420 // have been read.
421 
WavpackGetWrapperBytes(WavpackContext * wpc)422 uint32_t WavpackGetWrapperBytes (WavpackContext *wpc)
423 {
424     return wpc ? wpc->wrapper_bytes : 0;
425 }
426 
WavpackGetWrapperData(WavpackContext * wpc)427 unsigned char *WavpackGetWrapperData (WavpackContext *wpc)
428 {
429     return wpc ? wpc->wrapper_data : NULL;
430 }
431 
WavpackFreeWrapper(WavpackContext * wpc)432 void WavpackFreeWrapper (WavpackContext *wpc)
433 {
434     if (wpc && wpc->wrapper_data) {
435         free (wpc->wrapper_data);
436         wpc->wrapper_data = NULL;
437         wpc->wrapper_bytes = 0;
438     }
439 }
440 
441 // Returns the sample rate of the specified WavPack file
442 
WavpackGetSampleRate(WavpackContext * wpc)443 uint32_t WavpackGetSampleRate (WavpackContext *wpc)
444 {
445     return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier : wpc->config.sample_rate) : 44100;
446 }
447 
448 // Returns the native sample rate of the specified WavPack file
449 // (provides the native rate for DSD files rather than the "byte" rate that's used for
450 //   seeking, duration, etc. and would generally be used just for user facing reports)
451 
WavpackGetNativeSampleRate(WavpackContext * wpc)452 uint32_t WavpackGetNativeSampleRate (WavpackContext *wpc)
453 {
454     return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier * 8 : wpc->config.sample_rate) : 44100;
455 }
456 
457 // Returns the number of channels of the specified WavPack file. Note that
458 // this is the actual number of channels contained in the file even if the
459 // OPEN_2CH_MAX flag was specified when the file was opened.
460 
WavpackGetNumChannels(WavpackContext * wpc)461 int WavpackGetNumChannels (WavpackContext *wpc)
462 {
463     return wpc ? wpc->config.num_channels : 2;
464 }
465 
466 // Returns the standard Microsoft channel mask for the specified WavPack
467 // file. A value of zero indicates that there is no speaker assignment
468 // information.
469 
WavpackGetChannelMask(WavpackContext * wpc)470 int WavpackGetChannelMask (WavpackContext *wpc)
471 {
472     return wpc ? wpc->config.channel_mask : 0;
473 }
474 
475 // Return the normalization value for floating point data (valid only
476 // if floating point data is present). A value of 127 indicates that
477 // the floating point range is +/- 1.0. Higher values indicate a
478 // larger floating point range. Note that if the client specified
479 // OPEN_NORMALIZE we return the normalized value (i.e., 127 + offset)
480 // rather than what's in the file (which isn't really relevant).
481 
WavpackGetFloatNormExp(WavpackContext * wpc)482 int WavpackGetFloatNormExp (WavpackContext *wpc)
483 {
484     return (wpc->open_flags & OPEN_NORMALIZE) ? 127 + wpc->norm_offset : wpc->config.float_norm_exp;
485 }
486 
487 // Returns the actual number of valid bits per sample contained in the
488 // original file, which may or may not be a multiple of 8. Floating data
489 // always has 32 bits, integers may be from 1 to 32 bits each. When this
490 // value is not a multiple of 8, then the "extra" bits are located in the
491 // LSBs of the results. That is, values are right justified when unpacked
492 // into ints, but are left justified in the number of bytes used by the
493 // original data.
494 
WavpackGetBitsPerSample(WavpackContext * wpc)495 int WavpackGetBitsPerSample (WavpackContext *wpc)
496 {
497     return wpc ? wpc->config.bits_per_sample : 16;
498 }
499 
500 // Returns the number of bytes used for each sample (1 to 4) in the original
501 // file. This is required information for the user of this module because the
502 // audio data is returned in the LOWER bytes of the long buffer and must be
503 // left-shifted 8, 16, or 24 bits if normalized longs are required.
504 
WavpackGetBytesPerSample(WavpackContext * wpc)505 int WavpackGetBytesPerSample (WavpackContext *wpc)
506 {
507     return wpc ? wpc->config.bytes_per_sample : 2;
508 }
509 
510 // If the OPEN_2CH_MAX flag is specified when opening the file, this function
511 // will return the actual number of channels decoded from the file (which may
512 // or may not be less than the actual number of channels, but will always be
513 // 1 or 2). Normally, this will be the front left and right channels of a
514 // multichannel file.
515 
WavpackGetReducedChannels(WavpackContext * wpc)516 int WavpackGetReducedChannels (WavpackContext *wpc)
517 {
518     if (wpc)
519         return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
520     else
521         return 2;
522 }
523 
524 // Free all memory allocated for raw WavPack blocks (for all allocated streams)
525 // and free all additional streams. This does not free the default stream ([0])
526 // which is always kept around.
527 
free_streams(WavpackContext * wpc)528 void free_streams (WavpackContext *wpc)
529 {
530     int si = wpc->num_streams;
531 
532     while (si--) {
533         if (wpc->streams [si]->blockbuff) {
534             free (wpc->streams [si]->blockbuff);
535             wpc->streams [si]->blockbuff = NULL;
536         }
537 
538         if (wpc->streams [si]->block2buff) {
539             free (wpc->streams [si]->block2buff);
540             wpc->streams [si]->block2buff = NULL;
541         }
542 
543         if (wpc->streams [si]->sample_buffer) {
544             free (wpc->streams [si]->sample_buffer);
545             wpc->streams [si]->sample_buffer = NULL;
546         }
547 
548         if (wpc->streams [si]->dc.shaping_data) {
549             free (wpc->streams [si]->dc.shaping_data);
550             wpc->streams [si]->dc.shaping_data = NULL;
551         }
552 
553 #ifdef ENABLE_DSD
554         free_dsd_tables (wpc->streams [si]);
555 #endif
556 
557         if (si) {
558             wpc->num_streams--;
559             free (wpc->streams [si]);
560             wpc->streams [si] = NULL;
561         }
562     }
563 
564     wpc->current_stream = 0;
565 }
566 
free_dsd_tables(WavpackStream * wps)567 void free_dsd_tables (WavpackStream *wps)
568 {
569     if (wps->dsd.probabilities) {
570         free (wps->dsd.probabilities);
571         wps->dsd.probabilities = NULL;
572     }
573 
574     if (wps->dsd.summed_probabilities) {
575         free (wps->dsd.summed_probabilities);
576         wps->dsd.summed_probabilities = NULL;
577     }
578 
579     if (wps->dsd.lookup_buffer) {
580         free (wps->dsd.lookup_buffer);
581         wps->dsd.lookup_buffer = NULL;
582     }
583 
584     if (wps->dsd.value_lookup) {
585         free (wps->dsd.value_lookup);
586         wps->dsd.value_lookup = NULL;
587     }
588 
589     if (wps->dsd.ptable) {
590         free (wps->dsd.ptable);
591         wps->dsd.ptable = NULL;
592     }
593 }
594 
WavpackFloatNormalize(int32_t * values,int32_t num_values,int delta_exp)595 void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp)
596 {
597     f32 *fvalues = (f32 *) values;
598     int exp;
599 
600     if (!delta_exp)
601         return;
602 
603     while (num_values--) {
604         if ((exp = get_exponent (*fvalues)) == 0 || exp + delta_exp <= 0)
605             *fvalues = 0;
606         else if (exp == 255 || (exp += delta_exp) >= 255) {
607             set_exponent (*fvalues, 255);
608             set_mantissa (*fvalues, 0);
609         }
610         else
611             set_exponent (*fvalues, exp);
612 
613         fvalues++;
614     }
615 }
616 
WavpackLittleEndianToNative(void * data,char * format)617 void WavpackLittleEndianToNative (void *data, char *format)
618 {
619     unsigned char *cp = (unsigned char *) data;
620     int64_t temp;
621 
622     while (*format) {
623         switch (*format) {
624             case 'D':
625                 temp = cp [0] + ((int64_t) cp [1] << 8) + ((int64_t) cp [2] << 16) + ((int64_t) cp [3] << 24) +
626                     ((int64_t) cp [4] << 32) + ((int64_t) cp [5] << 40) + ((int64_t) cp [6] << 48) + ((uint64_t) cp [7] << 56);
627                 * (int64_t *) cp = temp;
628                 cp += 8;
629                 break;
630 
631             case 'L':
632                 temp = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int64_t) cp [3] << 24);
633                 * (int32_t *) cp = (int32_t) temp;
634                 cp += 4;
635                 break;
636 
637             case 'S':
638                 temp = cp [0] + (cp [1] << 8);
639                 * (int16_t *) cp = (int16_t) temp;
640                 cp += 2;
641                 break;
642 
643             default:
644                 if (isdigit (*format))
645                     cp += *format - '0';
646 
647                 break;
648         }
649 
650         format++;
651     }
652 }
653 
WavpackNativeToLittleEndian(void * data,char * format)654 void WavpackNativeToLittleEndian (void *data, char *format)
655 {
656     unsigned char *cp = (unsigned char *) data;
657     int64_t temp;
658 
659     while (*format) {
660         switch (*format) {
661             case 'D':
662                 temp = * (int64_t *) cp;
663                 *cp++ = (unsigned char) temp;
664                 *cp++ = (unsigned char) (temp >> 8);
665                 *cp++ = (unsigned char) (temp >> 16);
666                 *cp++ = (unsigned char) (temp >> 24);
667                 *cp++ = (unsigned char) (temp >> 32);
668                 *cp++ = (unsigned char) (temp >> 40);
669                 *cp++ = (unsigned char) (temp >> 48);
670                 *cp++ = (unsigned char) (temp >> 56);
671                 break;
672 
673             case 'L':
674                 temp = * (int32_t *) cp;
675                 *cp++ = (unsigned char) temp;
676                 *cp++ = (unsigned char) (temp >> 8);
677                 *cp++ = (unsigned char) (temp >> 16);
678                 *cp++ = (unsigned char) (temp >> 24);
679                 break;
680 
681             case 'S':
682                 temp = * (int16_t *) cp;
683                 *cp++ = (unsigned char) temp;
684                 *cp++ = (unsigned char) (temp >> 8);
685                 break;
686 
687             default:
688                 if (isdigit (*format))
689                     cp += *format - '0';
690 
691                 break;
692         }
693 
694         format++;
695     }
696 }
697 
WavpackBigEndianToNative(void * data,char * format)698 void WavpackBigEndianToNative (void *data, char *format)
699 {
700     unsigned char *cp = (unsigned char *) data;
701     int64_t temp;
702 
703     while (*format) {
704         switch (*format) {
705             case 'D':
706                 temp = cp [7] + ((int64_t) cp [6] << 8) + ((int64_t) cp [5] << 16) + ((int64_t) cp [4] << 24) +
707                     ((int64_t) cp [3] << 32) + ((int64_t) cp [2] << 40) + ((int64_t) cp [1] << 48) + ((uint64_t) cp [0] << 56);
708                 * (int64_t *) cp = temp;
709                 cp += 8;
710                 break;
711 
712             case 'L':
713                 temp = cp [3] + ((int32_t) cp [2] << 8) + ((int32_t) cp [1] << 16) + ((int64_t) cp [0] << 24);
714                 * (int32_t *) cp = (int32_t) temp;
715                 cp += 4;
716                 break;
717 
718             case 'S':
719                 temp = cp [1] + (cp [0] << 8);
720                 * (int16_t *) cp = (int16_t) temp;
721                 cp += 2;
722                 break;
723 
724             default:
725                 if (isdigit (*format))
726                     cp += *format - '0';
727 
728                 break;
729         }
730 
731         format++;
732     }
733 }
734 
WavpackNativeToBigEndian(void * data,char * format)735 void WavpackNativeToBigEndian (void *data, char *format)
736 {
737     unsigned char *cp = (unsigned char *) data;
738     int64_t temp;
739 
740     while (*format) {
741         switch (*format) {
742             case 'D':
743                 temp = * (int64_t *) cp;
744                 *cp++ = (unsigned char) (temp >> 56);
745                 *cp++ = (unsigned char) (temp >> 48);
746                 *cp++ = (unsigned char) (temp >> 40);
747                 *cp++ = (unsigned char) (temp >> 32);
748                 *cp++ = (unsigned char) (temp >> 24);
749                 *cp++ = (unsigned char) (temp >> 16);
750                 *cp++ = (unsigned char) (temp >> 8);
751                 *cp++ = (unsigned char) temp;
752                 break;
753 
754             case 'L':
755                 temp = * (int32_t *) cp;
756                 *cp++ = (unsigned char) (temp >> 24);
757                 *cp++ = (unsigned char) (temp >> 16);
758                 *cp++ = (unsigned char) (temp >> 8);
759                 *cp++ = (unsigned char) temp;
760                 break;
761 
762             case 'S':
763                 temp = * (int16_t *) cp;
764                 *cp++ = (unsigned char) (temp >> 8);
765                 *cp++ = (unsigned char) temp;
766                 break;
767 
768             default:
769                 if (isdigit (*format))
770                     cp += *format - '0';
771 
772                 break;
773         }
774 
775         format++;
776     }
777 }
778 
WavpackGetLibraryVersion(void)779 uint32_t WavpackGetLibraryVersion (void)
780 {
781     return (LIBWAVPACK_MAJOR<<16)
782           |(LIBWAVPACK_MINOR<<8)
783           |(LIBWAVPACK_MICRO<<0);
784 }
785 
WavpackGetLibraryVersionString(void)786 const char *WavpackGetLibraryVersionString (void)
787 {
788     return LIBWAVPACK_VERSION_STRING;
789 }
790 
791