Coverage Report

Created: 2023-06-07 06:30

/src/wavpack/src/common_utils.c
Line
Count
Source (jump to first uncovered line)
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
55
int WavpackGetMode (WavpackContext *wpc)
56
5.95k
{
57
5.95k
    int mode = 0;
58
59
5.95k
    if (wpc) {
60
5.95k
        if (wpc->config.flags & CONFIG_HYBRID_FLAG)
61
2.44k
            mode |= MODE_HYBRID;
62
3.51k
        else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
63
3.47k
            mode |= MODE_LOSSLESS;
64
65
5.95k
        if (wpc->wvc_flag)
66
0
            mode |= (MODE_LOSSLESS | MODE_WVC);
67
68
5.95k
        if (wpc->lossy_blocks)
69
90
            mode &= ~MODE_LOSSLESS;
70
71
5.95k
        if (wpc->config.flags & CONFIG_FLOAT_DATA)
72
1.75k
            mode |= MODE_FLOAT;
73
74
5.95k
        if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG)) {
75
98
            mode |= MODE_HIGH;
76
77
98
            if ((wpc->config.flags & CONFIG_VERY_HIGH_FLAG) ||
78
98
                (wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.version < 0x405))
79
86
                    mode |= MODE_VERY_HIGH;
80
98
        }
81
82
5.95k
        if (wpc->config.flags & CONFIG_FAST_FLAG)
83
108
            mode |= MODE_FAST;
84
85
5.95k
        if (wpc->config.flags & CONFIG_EXTRA_MODE)
86
117
            mode |= (MODE_EXTRA | (wpc->config.xmode << 12));
87
88
5.95k
        if (wpc->config.flags & CONFIG_CREATE_EXE)
89
98
            mode |= MODE_SFX;
90
91
5.95k
        if (wpc->config.flags & CONFIG_MD5_CHECKSUM)
92
129
            mode |= MODE_MD5;
93
94
5.95k
        if ((wpc->config.flags & CONFIG_HYBRID_FLAG) && (wpc->config.flags & CONFIG_DYNAMIC_SHAPING) &&
95
5.95k
            wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.version >= 0x407)
96
19
                mode |= MODE_DNS;
97
98
5.95k
#ifndef NO_TAGS
99
5.95k
        if (valid_tag (&wpc->m_tag)) {
100
842
            mode |= MODE_VALID_TAG;
101
102
842
            if (valid_tag (&wpc->m_tag) == 'A')
103
739
                mode |= MODE_APETAG;
104
842
        }
105
5.95k
#endif
106
107
5.95k
        mode |= (wpc->config.qmode << 16) & 0xFF0000;
108
5.95k
    }
109
110
5.95k
    return mode;
111
5.95k
}
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 application (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
132
int WavpackGetQualifyMode (WavpackContext *wpc)
133
5.95k
{
134
5.95k
    return wpc->config.qmode & 0xFF;
135
5.95k
}
136
137
// This function returns a pointer to a string describing the last error
138
// generated by WavPack.
139
140
char *WavpackGetErrorMessage (WavpackContext *wpc)
141
5.95k
{
142
5.95k
    return wpc->error_message;
143
5.95k
}
144
145
// Get total number of samples contained in the WavPack file, or -1 if unknown
146
147
uint32_t WavpackGetNumSamples (WavpackContext *wpc)
148
5.95k
{
149
5.95k
    return (uint32_t) WavpackGetNumSamples64 (wpc);
150
5.95k
}
151
152
int64_t WavpackGetNumSamples64 (WavpackContext *wpc)
153
11.9k
{
154
11.9k
    return wpc ? wpc->total_samples : -1;
155
11.9k
}
156
157
// Get the current sample index position, or -1 if unknown
158
159
uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
160
5.95k
{
161
5.95k
    return (uint32_t) WavpackGetSampleIndex64 (wpc);
162
5.95k
}
163
164
int64_t WavpackGetSampleIndex64 (WavpackContext *wpc)
165
17.8k
{
166
17.8k
    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
17.8k
        if (wpc->streams && wpc->streams [0])
174
17.8k
            return wpc->streams [0]->sample_index;
175
17.8k
#endif
176
17.8k
    }
177
178
0
    return -1;
179
17.8k
}
180
181
// Get the number of errors encountered so far
182
183
int WavpackGetNumErrors (WavpackContext *wpc)
184
5.95k
{
185
5.95k
    return wpc ? wpc->crc_errors : 0;
186
5.95k
}
187
188
// return TRUE if any uncorrected lossy blocks were actually written or read
189
190
int WavpackLossyBlocks (WavpackContext *wpc)
191
5.95k
{
192
5.95k
    return wpc ? wpc->lossy_blocks : 0;
193
5.95k
}
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
199
double WavpackGetProgress (WavpackContext *wpc)
200
5.95k
{
201
5.95k
    if (wpc && wpc->total_samples != -1 && wpc->total_samples != 0)
202
5.91k
        return (double) WavpackGetSampleIndex64 (wpc) / wpc->total_samples;
203
45
    else
204
45
        return -1.0;
205
5.95k
}
206
207
// Return the total size of the WavPack file(s) in bytes.
208
209
uint32_t WavpackGetFileSize (WavpackContext *wpc)
210
0
{
211
0
    return (uint32_t) (wpc ? wpc->filelen + wpc->file2len : 0);
212
0
}
213
214
int64_t WavpackGetFileSize64 (WavpackContext *wpc)
215
0
{
216
0
    return wpc ? wpc->filelen + wpc->file2len : 0;
217
0
}
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
224
double WavpackGetRatio (WavpackContext *wpc)
225
5.95k
{
226
5.95k
    if (wpc && wpc->total_samples != -1 && wpc->filelen) {
227
5.91k
        double output_size = (double) wpc->total_samples * wpc->config.num_channels *
228
5.91k
            wpc->config.bytes_per_sample;
229
5.91k
        double input_size = (double) wpc->filelen + wpc->file2len;
230
231
5.91k
        if (output_size >= 1.0 && input_size >= 1.0)
232
5.74k
            return input_size / output_size;
233
5.91k
    }
234
235
214
    return 0.0;
236
5.95k
}
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
242
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc)
243
5.95k
{
244
5.95k
    if (wpc && wpc->total_samples != -1 && wpc->filelen && WavpackGetSampleRate (wpc)) {
245
5.85k
        double output_time = (double) wpc->total_samples / WavpackGetSampleRate (wpc);
246
5.85k
        double input_size = (double) wpc->filelen + (count_wvc ? wpc->file2len : 0);
247
248
5.85k
        if (output_time >= 0.1 && input_size >= 1.0)
249
4.22k
            return input_size * 8.0 / output_time;
250
5.85k
    }
251
252
1.72k
    return 0.0;
253
5.95k
}
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
260
double WavpackGetInstantBitrate (WavpackContext *wpc)
261
5.95k
{
262
5.95k
    if (wpc && wpc->stream3)
263
0
        return WavpackGetAverageBitrate (wpc, TRUE);
264
265
5.95k
    if (wpc && wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.block_samples && WavpackGetSampleRate (wpc)) {
266
5.89k
        double output_time = (double) wpc->streams [0]->wphdr.block_samples / WavpackGetSampleRate (wpc);
267
5.89k
        double input_size = 0;
268
5.89k
        int si;
269
270
11.7k
        for (si = 0; si < wpc->num_streams; ++si) {
271
5.89k
            if (wpc->streams [si]->blockbuff)
272
5.89k
                input_size += ((WavpackHeader *) wpc->streams [si]->blockbuff)->ckSize;
273
274
5.89k
            if (wpc->streams [si]->block2buff)
275
0
                input_size += ((WavpackHeader *) wpc->streams [si]->block2buff)->ckSize;
276
5.89k
        }
277
278
5.89k
        if (output_time > 0.0 && input_size >= 1.0)
279
5.89k
            return input_size * 8.0 / output_time;
280
5.89k
    }
281
282
66
    return 0.0;
283
5.95k
}
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
303
uint32_t WavpackGetChannelLayout (WavpackContext *wpc, unsigned char *reorder)
304
6.01k
{
305
6.01k
    if ((wpc->channel_layout & 0xff) && wpc->channel_reordering && reorder)
306
17
        memcpy (reorder, wpc->channel_reordering, wpc->channel_layout & 0xff);
307
308
6.01k
    return wpc->channel_layout;
309
6.01k
}
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 "unassigned" 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
324
void WavpackGetChannelIdentities (WavpackContext *wpc, unsigned char *identities)
325
5.95k
{
326
5.95k
    int num_channels = wpc->config.num_channels, index = 1;
327
5.95k
    uint32_t channel_mask = wpc->config.channel_mask;
328
5.95k
    unsigned char *src = wpc->channel_identities;
329
330
555k
    while (num_channels--) {
331
549k
        if (channel_mask) {
332
27.3k
            while (!(channel_mask & 1)) {
333
10.7k
                channel_mask >>= 1;
334
10.7k
                index++;
335
10.7k
            }
336
337
16.5k
            *identities++ = index++;
338
16.5k
            channel_mask >>= 1;
339
16.5k
        }
340
533k
        else if (src && *src)
341
154
            *identities++ = *src++;
342
533k
        else
343
533k
            *identities++ = 0xff;
344
549k
    }
345
346
5.95k
    *identities = 0;
347
5.95k
}
348
349
#ifdef ENABLE_THREADS
350
351
static void worker_threads_destroy (WavpackContext *wpc)
352
7.99k
{
353
7.99k
    if (wpc->workers) {
354
0
        int i;
355
356
0
        for (i = 0; i < wpc->num_workers; ++i) {
357
0
            wp_mutex_obtain (wpc->mutex);
358
0
            wpc->workers [i].state = Quit;
359
0
            wp_condvar_signal (wpc->workers [i].worker_cond);
360
0
            wp_mutex_release (wpc->mutex);
361
0
            wp_thread_join (wpc->workers [i].thread);
362
0
            wp_thread_delete (wpc->workers [i].thread);
363
0
            wp_condvar_delete (wpc->workers [i].worker_cond);
364
0
        }
365
366
0
        free (wpc->workers);
367
0
        wpc->workers = NULL;
368
0
        wp_mutex_delete (wpc->mutex);
369
0
    }
370
7.99k
}
371
372
#endif
373
374
// For local use only. Install a callback to be executed when WavpackCloseFile() is called,
375
// usually used to dump some statistics accumulated during encode or decode.
376
377
void install_close_callback (WavpackContext *wpc, void cb_func (void *wpc))
378
0
{
379
0
    wpc->close_callback = cb_func;
380
0
}
381
382
// Close the specified WavPack file and release all resources used by it.
383
// Returns NULL.
384
385
WavpackContext *WavpackCloseFile (WavpackContext *wpc)
386
7.99k
{
387
7.99k
    if (wpc->close_callback)
388
0
        wpc->close_callback (wpc);
389
390
7.99k
    if (wpc->streams) {
391
7.98k
        free_streams (wpc);
392
393
7.98k
        if (wpc->streams [0])
394
7.98k
            free (wpc->streams [0]);
395
396
7.98k
        free (wpc->streams);
397
7.98k
    }
398
399
#ifdef ENABLE_LEGACY
400
    if (wpc->stream3)
401
        free_stream3 (wpc);
402
#endif
403
404
7.99k
    if (wpc->reader && wpc->reader->close && wpc->wv_in)
405
7.99k
        wpc->reader->close (wpc->wv_in);
406
407
7.99k
    if (wpc->reader && wpc->reader->close && wpc->wvc_in)
408
0
        wpc->reader->close (wpc->wvc_in);
409
410
7.99k
    WavpackFreeWrapper (wpc);
411
412
7.99k
    if (wpc->metadata) {
413
0
        int i;
414
415
0
        for (i = 0; i < wpc->metacount; ++i)
416
0
            if (wpc->metadata [i].data)
417
0
                free (wpc->metadata [i].data);
418
419
0
        free (wpc->metadata);
420
0
    }
421
422
7.99k
    if (wpc->channel_identities)
423
57
        free (wpc->channel_identities);
424
425
7.99k
    if (wpc->channel_reordering)
426
55
        free (wpc->channel_reordering);
427
428
7.99k
#ifndef NO_TAGS
429
7.99k
    free_tag (&wpc->m_tag);
430
7.99k
#endif
431
432
7.99k
#ifdef ENABLE_DSD
433
7.99k
    if (wpc->decimation_context)
434
978
        decimate_dsd_destroy (wpc->decimation_context);
435
7.99k
#endif
436
437
7.99k
#ifdef ENABLE_THREADS
438
7.99k
    worker_threads_destroy (wpc);
439
7.99k
#endif
440
441
7.99k
    free (wpc);
442
443
7.99k
    return NULL;
444
7.99k
}
445
446
// These routines are used to access (and free) header and trailer data that
447
// was retrieved from the Wavpack file. The header will be available before
448
// the samples are decoded and the trailer will be available after all samples
449
// have been read.
450
451
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc)
452
5.95k
{
453
5.95k
    return wpc ? wpc->wrapper_bytes : 0;
454
5.95k
}
455
456
unsigned char *WavpackGetWrapperData (WavpackContext *wpc)
457
32
{
458
32
    return wpc ? wpc->wrapper_data : NULL;
459
32
}
460
461
void WavpackFreeWrapper (WavpackContext *wpc)
462
7.99k
{
463
7.99k
    if (wpc && wpc->wrapper_data) {
464
106
        free (wpc->wrapper_data);
465
106
        wpc->wrapper_data = NULL;
466
106
        wpc->wrapper_bytes = 0;
467
106
    }
468
7.99k
}
469
470
// Returns the sample rate of the specified WavPack file
471
472
uint32_t WavpackGetSampleRate (WavpackContext *wpc)
473
29.5k
{
474
29.5k
    return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier : wpc->config.sample_rate) : 44100;
475
29.5k
}
476
477
// Returns the native sample rate of the specified WavPack file
478
// (provides the native rate for DSD files rather than the "byte" rate that's used for
479
//   seeking, duration, etc. and would generally be used just for user facing reports)
480
481
uint32_t WavpackGetNativeSampleRate (WavpackContext *wpc)
482
5.95k
{
483
5.95k
    return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier * 8 : wpc->config.sample_rate) : 44100;
484
5.95k
}
485
486
// Returns the number of channels of the specified WavPack file. Note that
487
// this is the actual number of channels contained in the file even if the
488
// OPEN_2CH_MAX flag was specified when the file was opened.
489
490
int WavpackGetNumChannels (WavpackContext *wpc)
491
5.95k
{
492
5.95k
    return wpc ? wpc->config.num_channels : 2;
493
5.95k
}
494
495
// Returns the standard Microsoft channel mask for the specified WavPack
496
// file. A value of zero indicates that there is no speaker assignment
497
// information.
498
499
int WavpackGetChannelMask (WavpackContext *wpc)
500
5.95k
{
501
5.95k
    return wpc ? wpc->config.channel_mask : 0;
502
5.95k
}
503
504
// Return the normalization value for floating point data (valid only
505
// if floating point data is present). A value of 127 indicates that
506
// the floating point range is +/- 1.0. Higher values indicate a
507
// larger floating point range. Note that if the client specified
508
// OPEN_NORMALIZE we return the normalized value (i.e., 127 + offset)
509
// rather than what's in the file (which isn't really relevant).
510
511
int WavpackGetFloatNormExp (WavpackContext *wpc)
512
5.95k
{
513
5.95k
    return (wpc->open_flags & OPEN_NORMALIZE) ? 127 + wpc->norm_offset : wpc->config.float_norm_exp;
514
5.95k
}
515
516
// Returns the actual number of valid bits per sample contained in the
517
// original file, which may or may not be a multiple of 8. Floating data
518
// always has 32 bits, integers may be from 1 to 32 bits each. When this
519
// value is not a multiple of 8, then the "extra" bits are located in the
520
// LSBs of the results. That is, values are right justified when unpacked
521
// into ints, but are left justified in the number of bytes used by the
522
// original data.
523
524
int WavpackGetBitsPerSample (WavpackContext *wpc)
525
5.95k
{
526
5.95k
    return wpc ? wpc->config.bits_per_sample : 16;
527
5.95k
}
528
529
// Returns the number of bytes used for each sample (1 to 4) in the original
530
// file. This is required information for the user of this module because the
531
// audio data is returned in the LOWER bytes of the long buffer and must be
532
// left-shifted 8, 16, or 24 bits if normalized longs are required.
533
534
int WavpackGetBytesPerSample (WavpackContext *wpc)
535
11.9k
{
536
11.9k
    return wpc ? wpc->config.bytes_per_sample : 2;
537
11.9k
}
538
539
// If the OPEN_2CH_MAX flag is specified when opening the file, this function
540
// will return the actual number of channels decoded from the file (which may
541
// or may not be less than the actual number of channels, but will always be
542
// 1 or 2). Normally, this will be the front left and right channels of a
543
// multichannel file.
544
545
int WavpackGetReducedChannels (WavpackContext *wpc)
546
5.95k
{
547
5.95k
    if (wpc)
548
5.95k
        return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
549
0
    else
550
0
        return 2;
551
5.95k
}
552
553
// Free all memory allocated for raw WavPack blocks (for all allocated streams)
554
// and free all additional streams. This does not free the default stream ([0])
555
// which is always kept around.
556
557
void free_streams (WavpackContext *wpc)
558
88.6k
{
559
88.6k
    int si = wpc->num_streams;
560
561
199k
    while (si--) {
562
110k
        free_single_stream (wpc->streams [si]);
563
564
110k
        if (si) {
565
22.3k
            wpc->num_streams--;
566
22.3k
            free (wpc->streams [si]);
567
22.3k
            wpc->streams [si] = NULL;
568
22.3k
        }
569
110k
    }
570
88.6k
}
571
572
// Free all resources associated with the specified stream
573
574
void free_single_stream (WavpackStream *wps)
575
110k
{
576
110k
    if (wps->blockbuff) {
577
98.1k
        free (wps->blockbuff);
578
98.1k
        wps->blockbuff = NULL;
579
98.1k
    }
580
581
110k
    if (wps->block2buff) {
582
0
        free (wps->block2buff);
583
0
        wps->block2buff = NULL;
584
0
    }
585
586
110k
    if (wps->sample_buffer) {
587
0
        free (wps->sample_buffer);
588
0
        wps->sample_buffer = NULL;
589
0
    }
590
591
110k
    if (wps->pre_sample_buffer) {
592
0
        free (wps->pre_sample_buffer);
593
0
        wps->sample_buffer = NULL;
594
0
    }
595
596
110k
    if (wps->dc.shaping_data) {
597
0
        free (wps->dc.shaping_data);
598
0
        wps->dc.shaping_data = NULL;
599
0
    }
600
601
110k
#ifdef ENABLE_DSD
602
110k
    free_dsd_tables (wps);
603
110k
#endif
604
110k
}
605
606
// Free all DSD-related resources associated with the specified stream
607
608
void free_dsd_tables (WavpackStream *wps)
609
114k
{
610
114k
    if (wps->dsd.probabilities) {
611
3.67k
        free (wps->dsd.probabilities);
612
3.67k
        wps->dsd.probabilities = NULL;
613
3.67k
    }
614
615
114k
    if (wps->dsd.summed_probabilities) {
616
3.67k
        free (wps->dsd.summed_probabilities);
617
3.67k
        wps->dsd.summed_probabilities = NULL;
618
3.67k
    }
619
620
114k
    if (wps->dsd.lookup_buffer) {
621
3.67k
        free (wps->dsd.lookup_buffer);
622
3.67k
        wps->dsd.lookup_buffer = NULL;
623
3.67k
    }
624
625
114k
    if (wps->dsd.value_lookup) {
626
3.67k
        free (wps->dsd.value_lookup);
627
3.67k
        wps->dsd.value_lookup = NULL;
628
3.67k
    }
629
630
114k
    if (wps->dsd.ptable) {
631
3.27k
        free (wps->dsd.ptable);
632
3.27k
        wps->dsd.ptable = NULL;
633
3.27k
    }
634
114k
}
635
636
void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp)
637
48.3k
{
638
48.3k
    f32 *fvalues = (f32 *) values;
639
48.3k
    int exp;
640
641
48.3k
    if (!delta_exp)
642
315
        return;
643
644
81.2M
    while (num_values--) {
645
81.2M
        if ((exp = get_exponent (*fvalues)) == 0 || exp + delta_exp <= 0)
646
65.2M
            *fvalues = 0;
647
15.9M
        else if (exp == 255 || (exp += delta_exp) >= 255) {
648
2.04M
            set_exponent (*fvalues, 255);
649
2.04M
            set_mantissa (*fvalues, 0);
650
2.04M
        }
651
13.8M
        else
652
13.8M
            set_exponent (*fvalues, exp);
653
654
81.2M
        fvalues++;
655
81.2M
    }
656
48.0k
}
657
658
void WavpackLittleEndianToNative (void *data, char *format)
659
284k
{
660
284k
    unsigned char *cp = (unsigned char *) data;
661
284k
    int64_t temp64;
662
284k
    int32_t temp32;
663
284k
    int16_t temp16;
664
665
2.83M
    while (*format) {
666
2.55M
        switch (*format) {
667
0
            case 'D':
668
0
                temp64 = cp [0] + ((int64_t) cp [1] << 8) + ((int64_t) cp [2] << 16) + ((int64_t) cp [3] << 24) +
669
0
                    ((int64_t) cp [4] << 32) + ((int64_t) cp [5] << 40) + ((int64_t) cp [6] << 48) + ((uint64_t) cp [7] << 56);
670
0
                memcpy (cp, &temp64, 8);
671
0
                cp += 8;
672
0
                break;
673
674
1.70M
            case 'L':
675
1.70M
                temp32 = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int64_t) cp [3] << 24);
676
1.70M
                memcpy (cp, &temp32, 4);
677
1.70M
                cp += 4;
678
1.70M
                break;
679
680
282k
            case 'S':
681
282k
                temp16 = cp [0] + (cp [1] << 8);
682
282k
                memcpy (cp, &temp16, 2);
683
282k
                cp += 2;
684
282k
                break;
685
686
566k
            default:
687
566k
                if (isdigit (*format))
688
566k
                    cp += *format - '0';
689
690
566k
                break;
691
2.55M
        }
692
693
2.55M
        format++;
694
2.55M
    }
695
284k
}
696
697
void WavpackNativeToLittleEndian (void *data, char *format)
698
126
{
699
126
    unsigned char *cp = (unsigned char *) data;
700
126
    int64_t temp64;
701
126
    int32_t temp32;
702
126
    int16_t temp16;
703
704
756
    while (*format) {
705
630
        switch (*format) {
706
0
            case 'D':
707
0
                memcpy (&temp64, cp, sizeof (temp64));
708
0
                *cp++ = (unsigned char) temp64;
709
0
                *cp++ = (unsigned char) (temp64 >> 8);
710
0
                *cp++ = (unsigned char) (temp64 >> 16);
711
0
                *cp++ = (unsigned char) (temp64 >> 24);
712
0
                *cp++ = (unsigned char) (temp64 >> 32);
713
0
                *cp++ = (unsigned char) (temp64 >> 40);
714
0
                *cp++ = (unsigned char) (temp64 >> 48);
715
0
                *cp++ = (unsigned char) (temp64 >> 56);
716
0
                break;
717
718
504
            case 'L':
719
504
                memcpy (&temp32, cp, sizeof (temp32));
720
504
                *cp++ = (unsigned char) temp32;
721
504
                *cp++ = (unsigned char) (temp32 >> 8);
722
504
                *cp++ = (unsigned char) (temp32 >> 16);
723
504
                *cp++ = (unsigned char) (temp32 >> 24);
724
504
                break;
725
726
0
            case 'S':
727
0
                memcpy (&temp16, cp, sizeof (temp16));
728
0
                *cp++ = (unsigned char) temp16;
729
0
                *cp++ = (unsigned char) (temp16 >> 8);
730
0
                break;
731
732
126
            default:
733
126
                if (isdigit (*format))
734
126
                    cp += *format - '0';
735
736
126
                break;
737
630
        }
738
739
630
        format++;
740
630
    }
741
126
}
742
743
void WavpackBigEndianToNative (void *data, char *format)
744
0
{
745
0
    unsigned char *cp = (unsigned char *) data;
746
0
    int64_t temp64;
747
0
    int32_t temp32;
748
0
    int16_t temp16;
749
750
0
    while (*format) {
751
0
        switch (*format) {
752
0
            case 'D':
753
0
                temp64 = cp [7] + ((int64_t) cp [6] << 8) + ((int64_t) cp [5] << 16) + ((int64_t) cp [4] << 24) +
754
0
                    ((int64_t) cp [3] << 32) + ((int64_t) cp [2] << 40) + ((int64_t) cp [1] << 48) + ((uint64_t) cp [0] << 56);
755
0
                memcpy (cp, &temp64, 8);
756
0
                cp += 8;
757
0
                break;
758
759
0
            case 'L':
760
0
                temp32 = cp [3] + ((int32_t) cp [2] << 8) + ((int32_t) cp [1] << 16) + ((int64_t) cp [0] << 24);
761
0
                memcpy (cp, &temp32, 4);
762
0
                cp += 4;
763
0
                break;
764
765
0
            case 'S':
766
0
                temp16 = cp [1] + (cp [0] << 8);
767
0
                memcpy (cp, &temp16, 2);
768
0
                cp += 2;
769
0
                break;
770
771
0
            default:
772
0
                if (isdigit (*format))
773
0
                    cp += *format - '0';
774
775
0
                break;
776
0
        }
777
778
0
        format++;
779
0
    }
780
0
}
781
782
void WavpackNativeToBigEndian (void *data, char *format)
783
0
{
784
0
    unsigned char *cp = (unsigned char *) data;
785
0
    int64_t temp64;
786
0
    int32_t temp32;
787
0
    int16_t temp16;
788
789
0
    while (*format) {
790
0
        switch (*format) {
791
0
            case 'D':
792
0
                memcpy (&temp64, cp, sizeof (temp64));
793
0
                *cp++ = (unsigned char) (temp64 >> 56);
794
0
                *cp++ = (unsigned char) (temp64 >> 48);
795
0
                *cp++ = (unsigned char) (temp64 >> 40);
796
0
                *cp++ = (unsigned char) (temp64 >> 32);
797
0
                *cp++ = (unsigned char) (temp64 >> 24);
798
0
                *cp++ = (unsigned char) (temp64 >> 16);
799
0
                *cp++ = (unsigned char) (temp64 >> 8);
800
0
                *cp++ = (unsigned char) temp64;
801
0
                break;
802
803
0
            case 'L':
804
0
                memcpy (&temp32, cp, sizeof (temp32));
805
0
                *cp++ = (unsigned char) (temp32 >> 24);
806
0
                *cp++ = (unsigned char) (temp32 >> 16);
807
0
                *cp++ = (unsigned char) (temp32 >> 8);
808
0
                *cp++ = (unsigned char) temp32;
809
0
                break;
810
811
0
            case 'S':
812
0
                memcpy (&temp16, cp, sizeof (temp16));
813
0
                *cp++ = (unsigned char) (temp16 >> 8);
814
0
                *cp++ = (unsigned char) temp16;
815
0
                break;
816
817
0
            default:
818
0
                if (isdigit (*format))
819
0
                    cp += *format - '0';
820
821
0
                break;
822
0
        }
823
824
0
        format++;
825
0
    }
826
0
}
827
828
uint32_t WavpackGetLibraryVersion (void)
829
7.99k
{
830
7.99k
    return (LIBWAVPACK_MAJOR<<16)
831
7.99k
          |(LIBWAVPACK_MINOR<<8)
832
7.99k
          |(LIBWAVPACK_MICRO<<0);
833
7.99k
}
834
835
const char *WavpackGetLibraryVersionString (void)
836
7.99k
{
837
7.99k
    return LIBWAVPACK_VERSION_STRING;
838
7.99k
}
839