1 ////////////////////////////////////////////////////////////////////////////
2 // **** WAVPACK **** //
3 // Hybrid Lossless Wavefile Compressor //
4 // Copyright (c) 1998 - 2004 Conifer Software. //
5 // All Rights Reserved. //
6 // Distributed under the BSD Software License (see license.txt) //
7 ////////////////////////////////////////////////////////////////////////////
11 // This module provides a high-level interface for decoding WavPack 4.0 audio
12 // streams and files. WavPack data is read with a stream reading callback. No
13 // direct seeking is provided for, but it is possible to start decoding
14 // anywhere in a WavPack stream. In this case, WavPack will be able to provide
15 // the sample-accurate position when it synchs with the data and begins
22 static void strcpy_loc (char *dst
, char *src
) { while ((*dst
++ = *src
++) != 0); }
24 ///////////////////////////// local table storage ////////////////////////////
26 const uint32_t sample_rates
[] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050,
27 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 };
29 ///////////////////////////// executable code ////////////////////////////////
31 static uint32_t read_next_header (read_stream infile
, WavpackHeader
*wphdr
);
33 // This function reads data from the specified stream in search of a valid
34 // WavPack 4.0 audio block. If this fails in 1 megabyte (or an invalid or
35 // unsupported WavPack block is encountered) then an appropriate message is
36 // copied to "error" and NULL is returned, otherwise a pointer to a
37 // WavpackContext structure is returned (which is used to call all other
38 // functions in this module). This can be initiated at the beginning of a
39 // WavPack file, or anywhere inside a WavPack file. To determine the exact
40 // position within the file use WavpackGetSampleIndex(). For demonstration
41 // purposes this uses a single static copy of the WavpackContext structure,
42 // so obviously it cannot be used for more than one file at a time. Also,
43 // this function will not handle "correction" files, plays only the first
44 // two channels of multi-channel files, and is limited in resolution in some
45 // large integer or floating point files (but always provides at least 24 bits
48 static WavpackContext wpc IBSS_ATTR
;
50 WavpackContext
*WavpackOpenFileInput (read_stream infile
, char *error
)
52 WavpackStream
*wps
= &wpc
.stream
;
57 wpc
.total_samples
= (uint32_t) -1;
61 // open the source file for reading and store the size
63 while (!wps
->wphdr
.block_samples
) {
65 bcount
= read_next_header (wpc
.infile
, &wps
->wphdr
);
67 if (bcount
== (uint32_t) -1) {
68 strcpy_loc (error
, "invalid WavPack file!");
72 if ((wps
->wphdr
.flags
& UNKNOWN_FLAGS
) || wps
->wphdr
.version
< MIN_STREAM_VERS
||
73 wps
->wphdr
.version
> MAX_STREAM_VERS
) {
74 strcpy_loc (error
, "invalid WavPack file!");
78 if (wps
->wphdr
.block_samples
&& wps
->wphdr
.total_samples
!= (uint32_t) -1)
79 wpc
.total_samples
= wps
->wphdr
.total_samples
;
81 if (!unpack_init (&wpc
)) {
82 strcpy_loc (error
, wpc
.error_message
[0] ? wpc
.error_message
:
83 "invalid WavPack file!");
89 wpc
.config
.flags
&= ~0xff;
90 wpc
.config
.flags
|= wps
->wphdr
.flags
& 0xff;
91 wpc
.config
.bytes_per_sample
= (wps
->wphdr
.flags
& BYTES_STORED
) + 1;
92 wpc
.config
.float_norm_exp
= wps
->float_norm_exp
;
94 wpc
.config
.bits_per_sample
= (wpc
.config
.bytes_per_sample
* 8) -
95 ((wps
->wphdr
.flags
& SHIFT_MASK
) >> SHIFT_LSB
);
97 if (!wpc
.config
.sample_rate
) {
98 if (!wps
|| !wps
->wphdr
.block_samples
|| (wps
->wphdr
.flags
& SRATE_MASK
) == SRATE_MASK
)
99 wpc
.config
.sample_rate
= 44100;
101 wpc
.config
.sample_rate
= sample_rates
[(wps
->wphdr
.flags
& SRATE_MASK
) >> SRATE_LSB
];
104 if (!wpc
.config
.num_channels
) {
105 wpc
.config
.num_channels
= (wps
->wphdr
.flags
& MONO_FLAG
) ? 1 : 2;
106 wpc
.config
.channel_mask
= 0x5 - wpc
.config
.num_channels
;
109 if (!(wps
->wphdr
.flags
& FINAL_BLOCK
))
110 wpc
.reduced_channels
= (wps
->wphdr
.flags
& MONO_FLAG
) ? 1 : 2;
115 // This function obtains general information about an open file and returns
116 // a mask with the following bit values:
118 // MODE_LOSSLESS: file is lossless (pure lossless only)
119 // MODE_HYBRID: file is hybrid mode (lossy part only)
120 // MODE_FLOAT: audio data is 32-bit ieee floating point
121 // MODE_HIGH: file was created in "high" mode (information only)
122 // MODE_FAST: file was created in "fast" mode (information only)
124 int WavpackGetMode (WavpackContext
*wpc
)
129 if (wpc
->config
.flags
& CONFIG_HYBRID_FLAG
)
131 else if (!(wpc
->config
.flags
& CONFIG_LOSSY_MODE
))
132 mode
|= MODE_LOSSLESS
;
134 if (wpc
->lossy_blocks
)
135 mode
&= ~MODE_LOSSLESS
;
137 if (wpc
->config
.flags
& CONFIG_FLOAT_DATA
)
140 if (wpc
->config
.flags
& CONFIG_HIGH_FLAG
)
143 if (wpc
->config
.flags
& CONFIG_FAST_FLAG
)
150 // Unpack the specified number of samples from the current file position.
151 // Note that "samples" here refers to "complete" samples, which would be
152 // 2 int32_t's for stereo files. The audio data is returned right-justified in
153 // 32-bit int32_t's in the endian mode native to the executing processor. So,
154 // if the original data was 16-bit, then the values returned would be
155 // +/-32k. Floating point data can also be returned if the source was
156 // floating point data (and this is normalized to +/-1.0). The actual number
157 // of samples unpacked is returned, which should be equal to the number
158 // requested unless the end of fle is encountered or an error occurs.
160 uint32_t WavpackUnpackSamples (WavpackContext
*wpc
, int32_t *buffer
, uint32_t samples
)
162 WavpackStream
*wps
= &wpc
->stream
;
163 uint32_t bcount
, samples_unpacked
= 0, samples_to_unpack
;
164 int num_channels
= wpc
->config
.num_channels
;
167 if (!wps
->wphdr
.block_samples
|| !(wps
->wphdr
.flags
& INITIAL_BLOCK
) ||
168 wps
->sample_index
>= wps
->wphdr
.block_index
+ wps
->wphdr
.block_samples
) {
169 bcount
= read_next_header (wpc
->infile
, &wps
->wphdr
);
171 if (bcount
== (uint32_t) -1)
174 if (wps
->wphdr
.version
< MIN_STREAM_VERS
|| wps
->wphdr
.version
> MAX_STREAM_VERS
) {
175 strcpy_loc (wpc
->error_message
, "invalid WavPack file!");
179 if (!wps
->wphdr
.block_samples
|| wps
->sample_index
== wps
->wphdr
.block_index
)
180 if (!unpack_init (wpc
))
184 if (!wps
->wphdr
.block_samples
|| !(wps
->wphdr
.flags
& INITIAL_BLOCK
) ||
185 wps
->sample_index
>= wps
->wphdr
.block_index
+ wps
->wphdr
.block_samples
)
188 if (wps
->sample_index
< wps
->wphdr
.block_index
) {
189 samples_to_unpack
= wps
->wphdr
.block_index
- wps
->sample_index
;
191 if (samples_to_unpack
> samples
)
192 samples_to_unpack
= samples
;
194 wps
->sample_index
+= samples_to_unpack
;
195 samples_unpacked
+= samples_to_unpack
;
196 samples
-= samples_to_unpack
;
198 if (wpc
->reduced_channels
)
199 samples_to_unpack
*= wpc
->reduced_channels
;
201 samples_to_unpack
*= num_channels
;
203 while (samples_to_unpack
--)
209 samples_to_unpack
= wps
->wphdr
.block_index
+ wps
->wphdr
.block_samples
- wps
->sample_index
;
211 if (samples_to_unpack
> samples
)
212 samples_to_unpack
= samples
;
214 unpack_samples (wpc
, buffer
, samples_to_unpack
);
216 if (wpc
->reduced_channels
)
217 buffer
+= samples_to_unpack
* wpc
->reduced_channels
;
219 buffer
+= samples_to_unpack
* num_channels
;
221 samples_unpacked
+= samples_to_unpack
;
222 samples
-= samples_to_unpack
;
224 if (wps
->sample_index
== wps
->wphdr
.block_index
+ wps
->wphdr
.block_samples
) {
225 if (check_crc_error (wpc
))
229 if (wps
->sample_index
== wpc
->total_samples
)
233 return samples_unpacked
;
236 // Get total number of samples contained in the WavPack file, or -1 if unknown
238 uint32_t WavpackGetNumSamples (WavpackContext
*wpc
)
240 return wpc
? wpc
->total_samples
: (uint32_t) -1;
243 // Get the current sample index position, or -1 if unknown
245 uint32_t WavpackGetSampleIndex (WavpackContext
*wpc
)
248 return wpc
->stream
.sample_index
;
250 return (uint32_t) -1;
253 // Get the number of errors encountered so far
255 int WavpackGetNumErrors (WavpackContext
*wpc
)
257 return wpc
? wpc
->crc_errors
: 0;
260 // return TRUE if any uncorrected lossy blocks were actually written or read
262 int WavpackLossyBlocks (WavpackContext
*wpc
)
264 return wpc
? wpc
->lossy_blocks
: 0;
267 // Returns the sample rate of the specified WavPack file
269 uint32_t WavpackGetSampleRate (WavpackContext
*wpc
)
271 return wpc
? wpc
->config
.sample_rate
: 44100;
274 // Returns the number of channels of the specified WavPack file. Note that
275 // this is the actual number of channels contained in the file, but this
276 // version can only decode the first two.
278 int WavpackGetNumChannels (WavpackContext
*wpc
)
280 return wpc
? wpc
->config
.num_channels
: 2;
283 // Returns the actual number of valid bits per sample contained in the
284 // original file, which may or may not be a multiple of 8. Floating data
285 // always has 32 bits, integers may be from 1 to 32 bits each. When this
286 // value is not a multiple of 8, then the "extra" bits are located in the
287 // LSBs of the results. That is, values are right justified when unpacked
288 // into int32_t's, but are left justified in the number of bytes used by the
291 int WavpackGetBitsPerSample (WavpackContext
*wpc
)
293 return wpc
? wpc
->config
.bits_per_sample
: 16;
296 // Returns the number of bytes used for each sample (1 to 4) in the original
297 // file. This is required information for the user of this module because the
298 // audio data is returned in the LOWER bytes of the int32_t buffer and must be
299 // left-shifted 8, 16, or 24 bits if normalized int32_t's are required.
301 int WavpackGetBytesPerSample (WavpackContext
*wpc
)
303 return wpc
? wpc
->config
.bytes_per_sample
: 2;
306 // This function will return the actual number of channels decoded from the
307 // file (which may or may not be less than the actual number of channels, but
308 // will always be 1 or 2). Normally, this will be the front left and right
309 // channels of a multi-channel file.
311 int WavpackGetReducedChannels (WavpackContext
*wpc
)
314 return wpc
->reduced_channels
? wpc
->reduced_channels
: wpc
->config
.num_channels
;
319 // Read from current file position until a valid 32-byte WavPack 4.0 header is
320 // found and read into the specified pointer. The number of bytes skipped is
321 // returned. If no WavPack header is found within 1 meg, then a -1 is returned
322 // to indicate the error. No additional bytes are read past the header and it
323 // is returned in the processor's native endian mode. Seeking is not required.
325 static uint32_t read_next_header (read_stream infile
, WavpackHeader
*wphdr
)
327 char buffer
[sizeof (*wphdr
)], *sp
= buffer
+ sizeof (*wphdr
), *ep
= sp
;
328 uint32_t bytes_skipped
= 0;
334 memcpy (buffer
, sp
, bleft
);
339 if (infile (buffer
+ bleft
, sizeof (*wphdr
) - bleft
) != (int32_t) sizeof (*wphdr
) - bleft
)
344 if (*sp
++ == 'w' && *sp
== 'v' && *++sp
== 'p' && *++sp
== 'k' &&
345 !(*++sp
& 1) && sp
[2] < 16 && !sp
[3] && sp
[5] == 4 &&
346 sp
[4] >= (MIN_STREAM_VERS
& 0xff) && sp
[4] <= (MAX_STREAM_VERS
& 0xff)) {
347 memcpy (wphdr
, buffer
, sizeof (*wphdr
));
348 little_endian_to_native (wphdr
, WavpackHeaderFormat
);
349 return bytes_skipped
;
352 while (sp
< ep
&& *sp
!= 'w')
355 if ((bytes_skipped
+= sp
- buffer
) > 1024 * 1024)
360 // Open context for writing WavPack files. The returned context pointer is used
361 // in all following calls to the library. A return value of NULL indicates
362 // that memory could not be allocated for the context.
364 WavpackContext
*WavpackOpenFileOutput (void)
370 // Set configuration for writing WavPack files. This must be done before
371 // sending any actual samples, however it is okay to send wrapper or other
372 // metadata before calling this. The "config" structure contains the following
373 // required information:
375 // config->bytes_per_sample see WavpackGetBytesPerSample() for info
376 // config->bits_per_sample see WavpackGetBitsPerSample() for info
377 // config->num_channels self evident
378 // config->sample_rate self evident
380 // In addition, the following fields and flags may be set:
384 // o CONFIG_HYBRID_FLAG select hybrid mode (must set bitrate)
385 // o CONFIG_JOINT_STEREO select joint stereo (must set override also)
386 // o CONFIG_JOINT_OVERRIDE override default joint stereo selection
387 // o CONFIG_HYBRID_SHAPE select hybrid noise shaping (set override &
388 // shaping_weight != 0.0)
389 // o CONFIG_SHAPE_OVERRIDE override default hybrid noise shaping
390 // (set CONFIG_HYBRID_SHAPE and shaping_weight)
391 // o CONFIG_FAST_FLAG "fast" compression mode
392 // o CONFIG_HIGH_FLAG "high" compression mode
393 // o CONFIG_BITRATE_KBPS hybrid bitrate is kbps, not bits / sample
395 // config->bitrate hybrid bitrate in either bits/sample or kbps
396 // config->shaping_weight hybrid noise shaping coefficient override
397 // config->float_norm_exp select floating-point data (127 for +/-1.0)
399 // If the number of samples to be written is known then it should be passed
400 // here. If the duration is not known then pass -1. In the case that the size
401 // is not known (or the writing is terminated early) then it is suggested that
402 // the application retrieve the first block written and let the library update
403 // the total samples indication. A function is provided to do this update and
404 // it should be done to the "correction" file also. If this cannot be done
405 // (because a pipe is being used, for instance) then a valid WavPack will still
406 // be created, but when applications want to access that file they will have
407 // to seek all the way to the end to determine the actual duration. Also, if
408 // a RIFF header has been included then it should be updated as well or the
409 // WavPack file will not be directly unpackable to a valid wav file (although
410 // it will still be usable by itself). A return of FALSE indicates an error.
412 int WavpackSetConfiguration (WavpackContext
*wpc
, WavpackConfig
*config
, uint32_t total_samples
)
414 WavpackStream
*wps
= &wpc
->stream
;
415 uint32_t flags
= (config
->bytes_per_sample
- 1), shift
= 0;
416 int num_chans
= config
->num_channels
;
419 if ((wpc
->config
.flags
& CONFIG_HYBRID_FLAG
) ||
420 wpc
->config
.float_norm_exp
||
421 num_chans
< 1 || num_chans
> 2)
424 wpc
->total_samples
= total_samples
;
425 wpc
->config
.sample_rate
= config
->sample_rate
;
426 wpc
->config
.num_channels
= config
->num_channels
;
427 wpc
->config
.bits_per_sample
= config
->bits_per_sample
;
428 wpc
->config
.bytes_per_sample
= config
->bytes_per_sample
;
429 wpc
->config
.flags
= config
->flags
;
431 shift
= (config
->bytes_per_sample
* 8) - config
->bits_per_sample
;
433 for (i
= 0; i
< 15; ++i
)
434 if (wpc
->config
.sample_rate
== sample_rates
[i
])
437 flags
|= i
<< SRATE_LSB
;
438 flags
|= shift
<< SHIFT_LSB
;
439 flags
|= CROSS_DECORR
;
441 if (!(config
->flags
& CONFIG_JOINT_OVERRIDE
) || (config
->flags
& CONFIG_JOINT_STEREO
))
442 flags
|= JOINT_STEREO
;
444 flags
|= INITIAL_BLOCK
| FINAL_BLOCK
;
446 if (num_chans
== 1) {
447 flags
&= ~(JOINT_STEREO
| CROSS_DECORR
| HYBRID_BALANCE
);
452 flags
+= (1 << MAG_LSB
) * ((flags
& BYTES_STORED
) * 8 + 7);
454 memcpy (wps
->wphdr
.ckID
, "wvpk", 4);
455 wps
->wphdr
.ckSize
= sizeof (WavpackHeader
) - 8;
456 wps
->wphdr
.total_samples
= wpc
->total_samples
;
457 wps
->wphdr
.version
= CUR_STREAM_VERS
;
458 wps
->wphdr
.flags
= flags
;
464 // Add wrapper (currently RIFF only) to WavPack blocks. This should be called
465 // before sending any audio samples. If the exact contents of the RIFF header
466 // are not known because, for example, the file duration is uncertain or
467 // trailing chunks are possible, simply write a "dummy" header of the correct
468 // length. When all data has been written it will be possible to read the
469 // first block written and update the header directly. An example of this can
470 // be found in the Audition filter.
472 void WavpackAddWrapper (WavpackContext
*wpc
, void *data
, uint32_t bcount
)
474 wpc
->wrapper_data
= data
;
475 wpc
->wrapper_bytes
= bcount
;
478 // Start a WavPack block to be stored in the specified buffer. This must be
479 // called before calling WavpackPackSamples(). Note that writing CANNOT wrap
480 // in the buffer; the entire output block must fit in the buffer.
482 int WavpackStartBlock (WavpackContext
*wpc
, uchar
*begin
, uchar
*end
)
484 wpc
->stream
.blockbuff
= begin
;
485 wpc
->stream
.blockend
= end
;
486 return pack_start_block (wpc
);
489 // Pack the specified samples. Samples must be stored in int32_ts in the native
490 // endian format of the executing processor. The number of samples specified
491 // indicates composite samples (sometimes called "frames"). So, the actual
492 // number of data points would be this "sample_count" times the number of
493 // channels. The caller must decide how many samples to place in each
494 // WavPack block (1/2 second is common), but this function may be called as
495 // many times as desired to build the final block (and performs the actual
496 // compression during the call). A return of FALSE indicates an error.
498 int WavpackPackSamples (WavpackContext
*wpc
, int32_t *sample_buffer
, uint32_t sample_count
)
500 if (!sample_count
|| pack_samples (wpc
, sample_buffer
, sample_count
))
503 strcpy_loc (wpc
->error_message
, "output buffer overflowed!");
507 // Finish the WavPack block being built, returning the total size of the
508 // block in bytes. Note that the possible conversion of the WavPack header to
509 // little-endian takes place here.
511 uint32_t WavpackFinishBlock (WavpackContext
*wpc
)
513 WavpackStream
*wps
= &wpc
->stream
;
516 pack_finish_block (wpc
);
517 bcount
= ((WavpackHeader
*) wps
->blockbuff
)->ckSize
+ 8;
518 native_to_little_endian ((WavpackHeader
*) wps
->blockbuff
, WavpackHeaderFormat
);
523 // Given the pointer to the first block written (to either a .wv or .wvc file),
524 // update the block with the actual number of samples written. This should
525 // be done if WavpackSetConfiguration() was called with an incorrect number
526 // of samples (or -1). It is the responsibility of the application to read and
527 // rewrite the block. An example of this can be found in the Audition filter.
529 void WavpackUpdateNumSamples (WavpackContext
*wpc
, void *first_block
)
531 little_endian_to_native (wpc
, WavpackHeaderFormat
);
532 ((WavpackHeader
*) first_block
)->total_samples
= WavpackGetSampleIndex (wpc
);
533 native_to_little_endian (wpc
, WavpackHeaderFormat
);
536 // Given the pointer to the first block written to a WavPack file, this
537 // function returns the location of the stored RIFF header that was originally
538 // written with WavpackAddWrapper(). This would normally be used to update
539 // the wav header to indicate that a different number of samples was actually
540 // written or if additional RIFF chunks are written at the end of the file.
541 // It is the responsibility of the application to read and rewrite the block.
542 // An example of this can be found in the Audition filter.
544 void *WavpackGetWrapperLocation (void *first_block
)
546 if (((uchar
*) first_block
) [32] == ID_RIFF_HEADER
)
547 return ((uchar
*) first_block
) + 34;