Coverage Report

Created: 2025-08-09 07:00

/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
6.80k
{
57
6.80k
    int mode = 0;
58
59
6.80k
    if (wpc) {
60
6.80k
        if (wpc->config.flags & CONFIG_HYBRID_FLAG)
61
3.24k
            mode |= MODE_HYBRID;
62
3.55k
        else if (!(wpc->config.flags & CONFIG_LOSSY_MODE))
63
3.51k
            mode |= MODE_LOSSLESS;
64
65
6.80k
        if (wpc->wvc_flag)
66
0
            mode |= (MODE_LOSSLESS | MODE_WVC);
67
68
6.80k
        if (wpc->lossy_blocks)
69
115
            mode &= ~MODE_LOSSLESS;
70
71
6.80k
        if (wpc->config.flags & CONFIG_FLOAT_DATA)
72
2.02k
            mode |= MODE_FLOAT;
73
74
6.80k
        if (wpc->config.flags & (CONFIG_HIGH_FLAG | CONFIG_VERY_HIGH_FLAG)) {
75
143
            mode |= MODE_HIGH;
76
77
143
            if ((wpc->config.flags & CONFIG_VERY_HIGH_FLAG) ||
78
143
                (wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.version < 0x405))
79
124
                    mode |= MODE_VERY_HIGH;
80
143
        }
81
82
6.80k
        if (wpc->config.flags & CONFIG_FAST_FLAG)
83
114
            mode |= MODE_FAST;
84
85
6.80k
        if (wpc->config.flags & CONFIG_EXTRA_MODE)
86
136
            mode |= (MODE_EXTRA | (wpc->config.xmode << 12));
87
88
6.80k
        if (wpc->config.flags & CONFIG_CREATE_EXE)
89
137
            mode |= MODE_SFX;
90
91
6.80k
        if (wpc->config.flags & CONFIG_MD5_CHECKSUM)
92
189
            mode |= MODE_MD5;
93
94
6.80k
        if ((wpc->config.flags & CONFIG_HYBRID_FLAG) && (wpc->config.flags & CONFIG_DYNAMIC_SHAPING) &&
95
6.80k
            wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.version >= 0x407)
96
21
                mode |= MODE_DNS;
97
98
6.80k
#ifndef NO_TAGS
99
6.80k
        if (valid_tag (&wpc->m_tag)) {
100
913
            mode |= MODE_VALID_TAG;
101
102
913
            if (valid_tag (&wpc->m_tag) == 'A')
103
801
                mode |= MODE_APETAG;
104
913
        }
105
6.80k
#endif
106
107
6.80k
        mode |= (wpc->config.qmode << 16) & 0xFF0000;
108
6.80k
    }
109
110
6.80k
    return mode;
111
6.80k
}
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
6.80k
{
134
6.80k
    return wpc->config.qmode & 0xFF;
135
6.80k
}
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
6.80k
{
142
6.80k
    return wpc->error_message;
143
6.80k
}
144
145
// Get total number of samples contained in the WavPack file, or -1 if unknown
146
147
uint32_t WavpackGetNumSamples (WavpackContext *wpc)
148
6.80k
{
149
6.80k
    return (uint32_t) WavpackGetNumSamples64 (wpc);
150
6.80k
}
151
152
int64_t WavpackGetNumSamples64 (WavpackContext *wpc)
153
13.6k
{
154
13.6k
    return wpc ? wpc->total_samples : -1;
155
13.6k
}
156
157
// Get the current sample index position, or -1 if unknown
158
159
uint32_t WavpackGetSampleIndex (WavpackContext *wpc)
160
6.80k
{
161
6.80k
    return (uint32_t) WavpackGetSampleIndex64 (wpc);
162
6.80k
}
163
164
int64_t WavpackGetSampleIndex64 (WavpackContext *wpc)
165
20.3k
{
166
20.3k
    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
20.3k
        if (wpc->streams && wpc->streams [0])
174
20.3k
            return wpc->streams [0]->sample_index;
175
20.3k
#endif
176
20.3k
    }
177
178
0
    return -1;
179
20.3k
}
180
181
// Get the number of errors encountered so far
182
183
int WavpackGetNumErrors (WavpackContext *wpc)
184
6.80k
{
185
6.80k
    return wpc ? wpc->crc_errors : 0;
186
6.80k
}
187
188
// return TRUE if any uncorrected lossy blocks were actually written or read
189
190
int WavpackLossyBlocks (WavpackContext *wpc)
191
6.80k
{
192
6.80k
    return wpc ? wpc->lossy_blocks : 0;
193
6.80k
}
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
6.80k
{
201
6.80k
    if (wpc && wpc->total_samples != -1 && wpc->total_samples != 0)
202
6.71k
        return (double) WavpackGetSampleIndex64 (wpc) / wpc->total_samples;
203
90
    else
204
90
        return -1.0;
205
6.80k
}
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
// Get the actual number of total samples, or if writing a file this returns the number of
220
// samples written so far. This allows WavpackGetRatio() and WavpackGetAverageBitrate() to
221
// work during writing and specifically in cases where the initial length was unknown.
222
223
static int64_t actual_total_samples (WavpackContext *wpc)
224
26.9k
{
225
26.9k
    int64_t total_samples = wpc->total_samples;
226
227
26.9k
    if (wpc->wv_out && wpc->streams && wpc->streams [0] && wpc->streams [0]->sample_index)
228
0
        total_samples = wpc->streams [0]->sample_index;
229
230
26.9k
    return total_samples;
231
26.9k
}
232
233
// Calculate the ratio of the specified WavPack file size to the size of the
234
// original audio data as a double greater than 0.0 and (usually) smaller than
235
// 1.0. A value greater than 1.0 represents "negative" compression and a
236
// return value of 0.0 indicates that the ratio cannot be determined.
237
238
double WavpackGetRatio (WavpackContext *wpc)
239
6.80k
{
240
6.80k
    if (wpc && actual_total_samples (wpc) != -1 && wpc->filelen) {
241
6.72k
        double output_size = (double) actual_total_samples (wpc) * wpc->config.num_channels *
242
6.72k
            wpc->config.bytes_per_sample;
243
6.72k
        double input_size = (double) wpc->filelen + wpc->file2len;
244
245
6.72k
        if (output_size >= 1.0 && input_size >= 1.0)
246
6.43k
            return input_size / output_size;
247
6.72k
    }
248
249
363
    return 0.0;
250
6.80k
}
251
252
// Calculate the average bitrate of the WavPack file in bits per second. A
253
// return of 0.0 indicates that the bitrate cannot be determined. An option is
254
// provided to use (or not use) any attendant .wvc file.
255
256
double WavpackGetAverageBitrate (WavpackContext *wpc, int count_wvc)
257
6.80k
{
258
6.80k
    if (wpc && actual_total_samples (wpc) != -1 && wpc->filelen && WavpackGetSampleRate (wpc)) {
259
6.61k
        double output_time = (double) actual_total_samples (wpc) / WavpackGetSampleRate (wpc);
260
6.61k
        double input_size = (double) wpc->filelen + (count_wvc ? wpc->file2len : 0);
261
262
6.61k
        if (output_time >= 0.1 && input_size >= 1.0)
263
4.86k
            return input_size * 8.0 / output_time;
264
6.61k
    }
265
266
1.93k
    return 0.0;
267
6.80k
}
268
269
// Calculate the bitrate of the current WavPack file block in bits per second.
270
// This can be used for an "instant" bit display and gets updated from about
271
// 1 to 4 times per second. A return of 0.0 indicates that the bitrate cannot
272
// be determined.
273
274
double WavpackGetInstantBitrate (WavpackContext *wpc)
275
6.80k
{
276
6.80k
    if (wpc && wpc->stream3)
277
0
        return WavpackGetAverageBitrate (wpc, TRUE);
278
279
6.80k
    if (wpc && wpc->streams && wpc->streams [0] && wpc->streams [0]->wphdr.block_samples && WavpackGetSampleRate (wpc)) {
280
6.69k
        double output_time = (double) wpc->streams [0]->wphdr.block_samples / WavpackGetSampleRate (wpc);
281
6.69k
        double input_size = 0;
282
6.69k
        int si;
283
284
13.3k
        for (si = 0; si < wpc->num_streams; ++si) {
285
6.69k
            if (wpc->streams [si]->blockbuff)
286
6.69k
                input_size += ((WavpackHeader *) wpc->streams [si]->blockbuff)->ckSize;
287
288
6.69k
            if (wpc->streams [si]->block2buff)
289
0
                input_size += ((WavpackHeader *) wpc->streams [si]->block2buff)->ckSize;
290
6.69k
        }
291
292
6.69k
        if (output_time > 0.0 && input_size >= 1.0)
293
6.69k
            return input_size * 8.0 / output_time;
294
6.69k
    }
295
296
111
    return 0.0;
297
6.80k
}
298
299
// This function allows retrieving the Core Audio File channel layout, many of which do not
300
// conform to the Microsoft ordering standard that WavPack requires internally (at least for
301
// those channels present in the "channel mask"). In addition to the layout tag, this function
302
// returns the reordering string (if stored in the file) to allow the unpacker to reorder the
303
// channels back to the specified layout (if it wants to restore the CAF order). The number of
304
// channels in the layout is determined from the lower nybble of the layout word (and should
305
// probably match the number of channels in the file), and if a reorder string is requested
306
// then that much space must be allocated. Note that all the reordering is actually done
307
// outside of this library, and that if reordering is done then the appropriate qmode bit
308
// will be set.
309
//
310
// Note: Normally this function would not be used by an application unless it specifically
311
// wanted to restore a non-standard channel order (to check an MD5, for example) or obtain
312
// the Core Audio channel layout ID. For simple file decoding for playback, the channel_mask
313
// should provide all the information required unless there are non-Microsoft channels
314
// involved, in which case WavpackGetChannelIdentities() will provide the identities of
315
// the other channels (if they are known).
316
317
uint32_t WavpackGetChannelLayout (WavpackContext *wpc, unsigned char *reorder)
318
6.87k
{
319
6.87k
    if ((wpc->channel_layout & 0xff) && wpc->channel_reordering && reorder)
320
32
        memcpy (reorder, wpc->channel_reordering, wpc->channel_layout & 0xff);
321
322
6.87k
    return wpc->channel_layout;
323
6.87k
}
324
325
// This function provides the identities of ALL the channels in the file, including the
326
// standard Microsoft channels (which come first, in order, and are numbered 1-18) and also
327
// any non-Microsoft channels (which can be in any order and have values from 33-254). The
328
// value 0x00 is invalid and 0xFF indicates an "unknown" or "unassigned" channel. The
329
// string is NULL terminated so the caller must supply enough space for the number
330
// of channels indicated by WavpackGetNumChannels(), plus one.
331
//
332
// Note that this function returns the actual order of the channels in the Wavpack file
333
// (i.e., the order returned by WavpackUnpackSamples()). If the file includes a "reordering"
334
// string because the source file was not in Microsoft order that is NOT taken into account
335
// here and really only needs to be considered if doing an MD5 verification or if it's
336
// required to restore the original order/file (like wvunpack does).
337
338
void WavpackGetChannelIdentities (WavpackContext *wpc, unsigned char *identities)
339
6.80k
{
340
6.80k
    int num_channels = wpc->config.num_channels, index = 1;
341
6.80k
    uint32_t channel_mask = wpc->config.channel_mask;
342
6.80k
    unsigned char *src = wpc->channel_identities;
343
344
585k
    while (num_channels--) {
345
578k
        if (channel_mask) {
346
33.8k
            while (!(channel_mask & 1)) {
347
13.2k
                channel_mask >>= 1;
348
13.2k
                index++;
349
13.2k
            }
350
351
20.5k
            *identities++ = index++;
352
20.5k
            channel_mask >>= 1;
353
20.5k
        }
354
557k
        else if (src && *src)
355
351
            *identities++ = *src++;
356
557k
        else
357
557k
            *identities++ = 0xff;
358
578k
    }
359
360
6.80k
    *identities = 0;
361
6.80k
}
362
363
#ifdef ENABLE_THREADS
364
365
static void worker_threads_destroy (WavpackContext *wpc)
366
7.84k
{
367
7.84k
    if (wpc->workers) {
368
5.70k
        int i;
369
370
21.9k
        for (i = 0; i < wpc->num_workers; ++i) {
371
16.2k
            wp_mutex_obtain (wpc->mutex);
372
16.2k
            wpc->workers [i].state = Quit;
373
16.2k
            wp_condvar_signal (wpc->workers [i].worker_cond);
374
16.2k
            wp_mutex_release (wpc->mutex);
375
16.2k
            wp_thread_join (wpc->workers [i].thread);
376
16.2k
            wp_thread_delete (wpc->workers [i].thread);
377
16.2k
            wp_condvar_delete (wpc->workers [i].worker_cond);
378
16.2k
        }
379
380
5.70k
        free (wpc->workers);
381
5.70k
        wpc->workers = NULL;
382
5.70k
        wp_mutex_delete (wpc->mutex);
383
5.70k
    }
384
7.84k
}
385
386
#endif
387
388
// For local use only. Install a callback to be executed when WavpackCloseFile() is called,
389
// usually used to dump some statistics accumulated during encode or decode.
390
391
void install_close_callback (WavpackContext *wpc, void cb_func (void *wpc))
392
0
{
393
0
    wpc->close_callback = cb_func;
394
0
}
395
396
// Close the specified WavPack file and release all resources used by it.
397
// Returns NULL.
398
399
WavpackContext *WavpackCloseFile (WavpackContext *wpc)
400
7.84k
{
401
7.84k
    if (wpc->close_callback)
402
0
        wpc->close_callback (wpc);
403
404
7.84k
    if (wpc->streams) {
405
7.84k
        free_streams (wpc);
406
407
7.84k
        if (wpc->streams [0])
408
7.84k
            free (wpc->streams [0]);
409
410
7.84k
        free (wpc->streams);
411
7.84k
    }
412
413
#ifdef ENABLE_LEGACY
414
    if (wpc->stream3)
415
        free_stream3 (wpc);
416
#endif
417
418
7.84k
    if (wpc->reader && wpc->reader->close && wpc->wv_in)
419
7.84k
        wpc->reader->close (wpc->wv_in);
420
421
7.84k
    if (wpc->reader && wpc->reader->close && wpc->wvc_in)
422
0
        wpc->reader->close (wpc->wvc_in);
423
424
7.84k
    WavpackFreeWrapper (wpc);
425
426
7.84k
    if (wpc->metadata) {
427
0
        int i;
428
429
0
        for (i = 0; i < wpc->metacount; ++i)
430
0
            if (wpc->metadata [i].data)
431
0
                free (wpc->metadata [i].data);
432
433
0
        free (wpc->metadata);
434
0
    }
435
436
7.84k
    if (wpc->channel_identities)
437
57
        free (wpc->channel_identities);
438
439
7.84k
    if (wpc->channel_reordering)
440
47
        free (wpc->channel_reordering);
441
442
7.84k
#ifndef NO_TAGS
443
7.84k
    free_tag (&wpc->m_tag);
444
7.84k
#endif
445
446
7.84k
#ifdef ENABLE_DSD
447
7.84k
    if (wpc->decimation_context)
448
1.06k
        decimate_dsd_destroy (wpc->decimation_context);
449
7.84k
#endif
450
451
7.84k
#ifdef ENABLE_THREADS
452
7.84k
    worker_threads_destroy (wpc);
453
7.84k
#endif
454
455
7.84k
    free (wpc);
456
457
7.84k
    return NULL;
458
7.84k
}
459
460
// These routines are used to access (and free) header and trailer data that
461
// was retrieved from the Wavpack file. The header will be available before
462
// the samples are decoded and the trailer will be available after all samples
463
// have been read.
464
465
uint32_t WavpackGetWrapperBytes (WavpackContext *wpc)
466
6.80k
{
467
6.80k
    return wpc ? wpc->wrapper_bytes : 0;
468
6.80k
}
469
470
unsigned char *WavpackGetWrapperData (WavpackContext *wpc)
471
80
{
472
80
    return wpc ? wpc->wrapper_data : NULL;
473
80
}
474
475
void WavpackFreeWrapper (WavpackContext *wpc)
476
7.84k
{
477
7.84k
    if (wpc && wpc->wrapper_data) {
478
121
        free (wpc->wrapper_data);
479
121
        wpc->wrapper_data = NULL;
480
121
        wpc->wrapper_bytes = 0;
481
121
    }
482
7.84k
}
483
484
// Returns the sample rate of the specified WavPack file
485
486
uint32_t WavpackGetSampleRate (WavpackContext *wpc)
487
33.6k
{
488
33.6k
    return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier : wpc->config.sample_rate) : 44100;
489
33.6k
}
490
491
// Returns the native sample rate of the specified WavPack file
492
// (provides the native rate for DSD files rather than the "byte" rate that's used for
493
//   seeking, duration, etc. and would generally be used just for user facing reports)
494
495
uint32_t WavpackGetNativeSampleRate (WavpackContext *wpc)
496
6.80k
{
497
6.80k
    return wpc ? (wpc->dsd_multiplier ? wpc->config.sample_rate * wpc->dsd_multiplier * 8 : wpc->config.sample_rate) : 44100;
498
6.80k
}
499
500
// Returns the number of channels of the specified WavPack file. Note that
501
// this is the actual number of channels contained in the file even if the
502
// OPEN_2CH_MAX flag was specified when the file was opened.
503
504
int WavpackGetNumChannels (WavpackContext *wpc)
505
6.80k
{
506
6.80k
    return wpc ? wpc->config.num_channels : 2;
507
6.80k
}
508
509
// Returns the standard Microsoft channel mask for the specified WavPack
510
// file. A value of zero indicates that there is no speaker assignment
511
// information.
512
513
int WavpackGetChannelMask (WavpackContext *wpc)
514
6.80k
{
515
6.80k
    return wpc ? wpc->config.channel_mask : 0;
516
6.80k
}
517
518
// Return the normalization value for floating point data (valid only
519
// if floating point data is present). A value of 127 indicates that
520
// the floating point range is +/- 1.0. Higher values indicate a
521
// larger floating point range. Note that if the client specified
522
// OPEN_NORMALIZE we return the normalized value (i.e., 127 + offset)
523
// rather than what's in the file (which isn't really relevant).
524
525
int WavpackGetFloatNormExp (WavpackContext *wpc)
526
6.80k
{
527
6.80k
    return (wpc->open_flags & OPEN_NORMALIZE) ? 127 + wpc->norm_offset : wpc->config.float_norm_exp;
528
6.80k
}
529
530
// Returns the actual number of valid bits per sample contained in the
531
// original file, which may or may not be a multiple of 8. Floating data
532
// always has 32 bits, integers may be from 1 to 32 bits each. When this
533
// value is not a multiple of 8, then the "extra" bits are located in the
534
// LSBs of the results. That is, values are right justified when unpacked
535
// into ints, but are left justified in the number of bytes used by the
536
// original data.
537
538
int WavpackGetBitsPerSample (WavpackContext *wpc)
539
6.80k
{
540
6.80k
    return wpc ? wpc->config.bits_per_sample : 16;
541
6.80k
}
542
543
// Returns the number of bytes used for each sample (1 to 4) in the original
544
// file. This is required information for the user of this module because the
545
// audio data is returned in the LOWER bytes of the long buffer and must be
546
// left-shifted 8, 16, or 24 bits if normalized longs are required.
547
548
int WavpackGetBytesPerSample (WavpackContext *wpc)
549
13.6k
{
550
13.6k
    return wpc ? wpc->config.bytes_per_sample : 2;
551
13.6k
}
552
553
// If the OPEN_2CH_MAX flag is specified when opening the file, this function
554
// will return the actual number of channels decoded from the file (which may
555
// or may not be less than the actual number of channels, but will always be
556
// 1 or 2). Normally, this will be the front left and right channels of a
557
// multichannel file.
558
559
int WavpackGetReducedChannels (WavpackContext *wpc)
560
6.80k
{
561
6.80k
    if (wpc)
562
6.80k
        return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels;
563
0
    else
564
0
        return 2;
565
6.80k
}
566
567
// Free all memory allocated for raw WavPack blocks (for all allocated streams)
568
// and free all additional streams. This does not free the default stream ([0])
569
// which is always kept around.
570
571
void free_streams (WavpackContext *wpc)
572
83.4k
{
573
83.4k
    int si = wpc->num_streams;
574
575
205k
    while (si--) {
576
121k
        free_single_stream (wpc->streams [si]);
577
578
121k
        if (si) {
579
38.2k
            wpc->num_streams--;
580
38.2k
            free (wpc->streams [si]);
581
38.2k
            wpc->streams [si] = NULL;
582
38.2k
        }
583
121k
    }
584
83.4k
}
585
586
// Free all resources associated with the specified stream
587
588
void free_single_stream (WavpackStream *wps)
589
124k
{
590
124k
    if (wps->blockbuff) {
591
106k
        free (wps->blockbuff);
592
106k
        wps->blockbuff = NULL;
593
106k
    }
594
595
124k
    if (wps->block2buff) {
596
0
        free (wps->block2buff);
597
0
        wps->block2buff = NULL;
598
0
    }
599
600
124k
    if (wps->sample_buffer) {
601
0
        free (wps->sample_buffer);
602
0
        wps->sample_buffer = NULL;
603
0
    }
604
605
124k
    if (wps->pre_sample_buffer) {
606
0
        free (wps->pre_sample_buffer);
607
0
        wps->pre_sample_buffer = NULL;
608
0
    }
609
610
124k
    if (wps->dc.shaping_data) {
611
0
        free (wps->dc.shaping_data);
612
0
        wps->dc.shaping_data = NULL;
613
0
    }
614
615
124k
#ifdef ENABLE_DSD
616
124k
    free_dsd_tables (wps);
617
124k
#endif
618
124k
}
619
620
// Free all DSD-related resources associated with the specified stream
621
622
void free_dsd_tables (WavpackStream *wps)
623
128k
{
624
128k
    if (wps->dsd.probabilities) {
625
3.71k
        free (wps->dsd.probabilities);
626
3.71k
        wps->dsd.probabilities = NULL;
627
3.71k
    }
628
629
128k
    if (wps->dsd.summed_probabilities) {
630
3.71k
        free (wps->dsd.summed_probabilities);
631
3.71k
        wps->dsd.summed_probabilities = NULL;
632
3.71k
    }
633
634
128k
    if (wps->dsd.lookup_buffer) {
635
3.71k
        free (wps->dsd.lookup_buffer);
636
3.71k
        wps->dsd.lookup_buffer = NULL;
637
3.71k
    }
638
639
128k
    if (wps->dsd.value_lookup) {
640
3.71k
        free (wps->dsd.value_lookup);
641
3.71k
        wps->dsd.value_lookup = NULL;
642
3.71k
    }
643
644
128k
    if (wps->dsd.ptable) {
645
3.18k
        free (wps->dsd.ptable);
646
3.18k
        wps->dsd.ptable = NULL;
647
3.18k
    }
648
128k
}
649
650
void WavpackFloatNormalize (int32_t *values, int32_t num_values, int delta_exp)
651
60.8k
{
652
60.8k
    f32 *fvalues = (f32 *) values;
653
60.8k
    int exp;
654
655
60.8k
    if (!delta_exp)
656
536
        return;
657
658
106M
    while (num_values--) {
659
106M
        if ((exp = get_exponent (*fvalues)) == 0 || exp + delta_exp <= 0)
660
92.3M
            *fvalues = 0;
661
13.8M
        else if (exp == 255 || (exp += delta_exp) >= 255) {
662
726k
            set_exponent (*fvalues, 255);
663
726k
            set_mantissa (*fvalues, 0);
664
726k
        }
665
13.1M
        else
666
13.1M
            set_exponent (*fvalues, exp);
667
668
106M
        fvalues++;
669
106M
    }
670
60.3k
}
671
672
void WavpackLittleEndianToNative (void *data, char *format)
673
199k
{
674
199k
    unsigned char *cp = (unsigned char *) data;
675
199k
    int64_t temp64;
676
199k
    int32_t temp32;
677
199k
    int16_t temp16;
678
679
1.99M
    while (*format) {
680
1.79M
        switch (*format) {
681
0
            case 'D':
682
0
                temp64 = cp [0] + ((int64_t) cp [1] << 8) + ((int64_t) cp [2] << 16) + ((int64_t) cp [3] << 24) +
683
0
                    ((int64_t) cp [4] << 32) + ((int64_t) cp [5] << 40) + ((int64_t) cp [6] << 48) + ((uint64_t) cp [7] << 56);
684
0
                memcpy (cp, &temp64, 8);
685
0
                cp += 8;
686
0
                break;
687
688
1.19M
            case 'L':
689
1.19M
                temp32 = cp [0] + ((int32_t) cp [1] << 8) + ((int32_t) cp [2] << 16) + ((int64_t) cp [3] << 24);
690
1.19M
                memcpy (cp, &temp32, 4);
691
1.19M
                cp += 4;
692
1.19M
                break;
693
694
198k
            case 'S':
695
198k
                temp16 = cp [0] + (cp [1] << 8);
696
198k
                memcpy (cp, &temp16, 2);
697
198k
                cp += 2;
698
198k
                break;
699
700
398k
            default:
701
398k
                if (isdigit (*format))
702
398k
                    cp += *format - '0';
703
704
398k
                break;
705
1.79M
        }
706
707
1.79M
        format++;
708
1.79M
    }
709
199k
}
710
711
void WavpackNativeToLittleEndian (void *data, char *format)
712
168
{
713
168
    unsigned char *cp = (unsigned char *) data;
714
168
    int64_t temp64;
715
168
    int32_t temp32;
716
168
    int16_t temp16;
717
718
1.00k
    while (*format) {
719
840
        switch (*format) {
720
0
            case 'D':
721
0
                memcpy (&temp64, cp, sizeof (temp64));
722
0
                *cp++ = (unsigned char) temp64;
723
0
                *cp++ = (unsigned char) (temp64 >> 8);
724
0
                *cp++ = (unsigned char) (temp64 >> 16);
725
0
                *cp++ = (unsigned char) (temp64 >> 24);
726
0
                *cp++ = (unsigned char) (temp64 >> 32);
727
0
                *cp++ = (unsigned char) (temp64 >> 40);
728
0
                *cp++ = (unsigned char) (temp64 >> 48);
729
0
                *cp++ = (unsigned char) (temp64 >> 56);
730
0
                break;
731
732
672
            case 'L':
733
672
                memcpy (&temp32, cp, sizeof (temp32));
734
672
                *cp++ = (unsigned char) temp32;
735
672
                *cp++ = (unsigned char) (temp32 >> 8);
736
672
                *cp++ = (unsigned char) (temp32 >> 16);
737
672
                *cp++ = (unsigned char) (temp32 >> 24);
738
672
                break;
739
740
0
            case 'S':
741
0
                memcpy (&temp16, cp, sizeof (temp16));
742
0
                *cp++ = (unsigned char) temp16;
743
0
                *cp++ = (unsigned char) (temp16 >> 8);
744
0
                break;
745
746
168
            default:
747
168
                if (isdigit (*format))
748
168
                    cp += *format - '0';
749
750
168
                break;
751
840
        }
752
753
840
        format++;
754
840
    }
755
168
}
756
757
void WavpackBigEndianToNative (void *data, char *format)
758
0
{
759
0
    unsigned char *cp = (unsigned char *) data;
760
0
    int64_t temp64;
761
0
    int32_t temp32;
762
0
    int16_t temp16;
763
764
0
    while (*format) {
765
0
        switch (*format) {
766
0
            case 'D':
767
0
                temp64 = cp [7] + ((int64_t) cp [6] << 8) + ((int64_t) cp [5] << 16) + ((int64_t) cp [4] << 24) +
768
0
                    ((int64_t) cp [3] << 32) + ((int64_t) cp [2] << 40) + ((int64_t) cp [1] << 48) + ((uint64_t) cp [0] << 56);
769
0
                memcpy (cp, &temp64, 8);
770
0
                cp += 8;
771
0
                break;
772
773
0
            case 'L':
774
0
                temp32 = cp [3] + ((int32_t) cp [2] << 8) + ((int32_t) cp [1] << 16) + ((int64_t) cp [0] << 24);
775
0
                memcpy (cp, &temp32, 4);
776
0
                cp += 4;
777
0
                break;
778
779
0
            case 'S':
780
0
                temp16 = cp [1] + (cp [0] << 8);
781
0
                memcpy (cp, &temp16, 2);
782
0
                cp += 2;
783
0
                break;
784
785
0
            default:
786
0
                if (isdigit (*format))
787
0
                    cp += *format - '0';
788
789
0
                break;
790
0
        }
791
792
0
        format++;
793
0
    }
794
0
}
795
796
void WavpackNativeToBigEndian (void *data, char *format)
797
0
{
798
0
    unsigned char *cp = (unsigned char *) data;
799
0
    int64_t temp64;
800
0
    int32_t temp32;
801
0
    int16_t temp16;
802
803
0
    while (*format) {
804
0
        switch (*format) {
805
0
            case 'D':
806
0
                memcpy (&temp64, cp, sizeof (temp64));
807
0
                *cp++ = (unsigned char) (temp64 >> 56);
808
0
                *cp++ = (unsigned char) (temp64 >> 48);
809
0
                *cp++ = (unsigned char) (temp64 >> 40);
810
0
                *cp++ = (unsigned char) (temp64 >> 32);
811
0
                *cp++ = (unsigned char) (temp64 >> 24);
812
0
                *cp++ = (unsigned char) (temp64 >> 16);
813
0
                *cp++ = (unsigned char) (temp64 >> 8);
814
0
                *cp++ = (unsigned char) temp64;
815
0
                break;
816
817
0
            case 'L':
818
0
                memcpy (&temp32, cp, sizeof (temp32));
819
0
                *cp++ = (unsigned char) (temp32 >> 24);
820
0
                *cp++ = (unsigned char) (temp32 >> 16);
821
0
                *cp++ = (unsigned char) (temp32 >> 8);
822
0
                *cp++ = (unsigned char) temp32;
823
0
                break;
824
825
0
            case 'S':
826
0
                memcpy (&temp16, cp, sizeof (temp16));
827
0
                *cp++ = (unsigned char) (temp16 >> 8);
828
0
                *cp++ = (unsigned char) temp16;
829
0
                break;
830
831
0
            default:
832
0
                if (isdigit (*format))
833
0
                    cp += *format - '0';
834
835
0
                break;
836
0
        }
837
838
0
        format++;
839
0
    }
840
0
}
841
842
uint32_t WavpackGetLibraryVersion (void)
843
7.84k
{
844
7.84k
    return (LIBWAVPACK_MAJOR<<16)
845
7.84k
          |(LIBWAVPACK_MINOR<<8)
846
7.84k
          |(LIBWAVPACK_MICRO<<0);
847
7.84k
}
848
849
const char *WavpackGetLibraryVersionString (void)
850
7.84k
{
851
7.84k
    return LIBWAVPACK_VERSION_STRING;
852
7.84k
}
853