/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 | | |