diff options
Diffstat (limited to 'lib/rbcodec/codecs/libwavpack/wputils.c')
-rw-r--r-- | lib/rbcodec/codecs/libwavpack/wputils.c | 555 |
1 files changed, 555 insertions, 0 deletions
diff --git a/lib/rbcodec/codecs/libwavpack/wputils.c b/lib/rbcodec/codecs/libwavpack/wputils.c new file mode 100644 index 0000000000..b0ccd3ba83 --- /dev/null +++ b/lib/rbcodec/codecs/libwavpack/wputils.c | |||
@@ -0,0 +1,555 @@ | |||
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 | //////////////////////////////////////////////////////////////////////////// | ||
8 | |||
9 | // wputils.c | ||
10 | |||
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 | ||
16 | // decoding. | ||
17 | |||
18 | #include "wavpack.h" | ||
19 | |||
20 | #include <string.h> | ||
21 | |||
22 | static void strcpy_loc (char *dst, char *src) { while ((*dst++ = *src++) != 0); } | ||
23 | |||
24 | ///////////////////////////// local table storage //////////////////////////// | ||
25 | |||
26 | const uint32_t sample_rates [] = { 6000, 8000, 9600, 11025, 12000, 16000, 22050, | ||
27 | 24000, 32000, 44100, 48000, 64000, 88200, 96000, 192000 }; | ||
28 | |||
29 | ///////////////////////////// executable code //////////////////////////////// | ||
30 | |||
31 | static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr); | ||
32 | |||
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 | ||
46 | // of resolution). | ||
47 | |||
48 | static WavpackContext wpc IBSS_ATTR; | ||
49 | |||
50 | WavpackContext *WavpackOpenFileInput (read_stream infile, char *error) | ||
51 | { | ||
52 | WavpackStream *wps = &wpc.stream; | ||
53 | uint32_t bcount; | ||
54 | |||
55 | CLEAR (wpc); | ||
56 | wpc.infile = infile; | ||
57 | wpc.total_samples = (uint32_t) -1; | ||
58 | wpc.norm_offset = 0; | ||
59 | wpc.open_flags = 0; | ||
60 | |||
61 | // open the source file for reading and store the size | ||
62 | |||
63 | while (!wps->wphdr.block_samples) { | ||
64 | |||
65 | bcount = read_next_header (wpc.infile, &wps->wphdr); | ||
66 | |||
67 | if (bcount == (uint32_t) -1) { | ||
68 | strcpy_loc (error, "invalid WavPack file!"); | ||
69 | return NULL; | ||
70 | } | ||
71 | |||
72 | wps->block_bytes_left = wps->wphdr.ckSize - 24; | ||
73 | |||
74 | if ((wps->wphdr.flags & UNKNOWN_FLAGS) || wps->wphdr.version < MIN_STREAM_VERS || | ||
75 | wps->wphdr.version > MAX_STREAM_VERS) { | ||
76 | strcpy_loc (error, "invalid WavPack file!"); | ||
77 | return NULL; | ||
78 | } | ||
79 | |||
80 | if (wps->wphdr.block_samples && wps->wphdr.total_samples != (uint32_t) -1) | ||
81 | wpc.total_samples = wps->wphdr.total_samples; | ||
82 | |||
83 | if (!unpack_init (&wpc)) { | ||
84 | strcpy_loc (error, wpc.error_message [0] ? wpc.error_message : | ||
85 | "invalid WavPack file!"); | ||
86 | |||
87 | return NULL; | ||
88 | } | ||
89 | } | ||
90 | |||
91 | wpc.config.flags &= ~0xff; | ||
92 | wpc.config.flags |= wps->wphdr.flags & 0xff; | ||
93 | wpc.config.bytes_per_sample = (wps->wphdr.flags & BYTES_STORED) + 1; | ||
94 | wpc.config.float_norm_exp = wps->float_norm_exp; | ||
95 | |||
96 | wpc.config.bits_per_sample = (wpc.config.bytes_per_sample * 8) - | ||
97 | ((wps->wphdr.flags & SHIFT_MASK) >> SHIFT_LSB); | ||
98 | |||
99 | if (!wpc.config.sample_rate) { | ||
100 | if (!wps || !wps->wphdr.block_samples || (wps->wphdr.flags & SRATE_MASK) == SRATE_MASK) | ||
101 | wpc.config.sample_rate = 44100; | ||
102 | else | ||
103 | wpc.config.sample_rate = sample_rates [(wps->wphdr.flags & SRATE_MASK) >> SRATE_LSB]; | ||
104 | } | ||
105 | |||
106 | if (!wpc.config.num_channels) { | ||
107 | wpc.config.num_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2; | ||
108 | wpc.config.channel_mask = 0x5 - wpc.config.num_channels; | ||
109 | } | ||
110 | |||
111 | if (!(wps->wphdr.flags & FINAL_BLOCK)) | ||
112 | wpc.reduced_channels = (wps->wphdr.flags & MONO_FLAG) ? 1 : 2; | ||
113 | |||
114 | return &wpc; | ||
115 | } | ||
116 | |||
117 | // This function obtains general information about an open file and returns | ||
118 | // a mask with the following bit values: | ||
119 | |||
120 | // MODE_LOSSLESS: file is lossless (pure lossless only) | ||
121 | // MODE_HYBRID: file is hybrid mode (lossy part only) | ||
122 | // MODE_FLOAT: audio data is 32-bit ieee floating point | ||
123 | // MODE_HIGH: file was created in "high" mode (information only) | ||
124 | // MODE_FAST: file was created in "fast" mode (information only) | ||
125 | |||
126 | int WavpackGetMode (WavpackContext *wpc) | ||
127 | { | ||
128 | int mode = 0; | ||
129 | |||
130 | if (wpc) { | ||
131 | if (wpc->config.flags & CONFIG_HYBRID_FLAG) | ||
132 | mode |= MODE_HYBRID; | ||
133 | else if (!(wpc->config.flags & CONFIG_LOSSY_MODE)) | ||
134 | mode |= MODE_LOSSLESS; | ||
135 | |||
136 | if (wpc->lossy_blocks) | ||
137 | mode &= ~MODE_LOSSLESS; | ||
138 | |||
139 | if (wpc->config.flags & CONFIG_FLOAT_DATA) | ||
140 | mode |= MODE_FLOAT; | ||
141 | |||
142 | if (wpc->config.flags & CONFIG_HIGH_FLAG) | ||
143 | mode |= MODE_HIGH; | ||
144 | |||
145 | if (wpc->config.flags & CONFIG_FAST_FLAG) | ||
146 | mode |= MODE_FAST; | ||
147 | } | ||
148 | |||
149 | return mode; | ||
150 | } | ||
151 | |||
152 | // Unpack the specified number of samples from the current file position. | ||
153 | // Note that "samples" here refers to "complete" samples, which would be | ||
154 | // 2 int32_t's for stereo files. The audio data is returned right-justified in | ||
155 | // 32-bit int32_t's in the endian mode native to the executing processor. So, | ||
156 | // if the original data was 16-bit, then the values returned would be | ||
157 | // +/-32k. Floating point data can also be returned if the source was | ||
158 | // floating point data (and this is normalized to +/-1.0). The actual number | ||
159 | // of samples unpacked is returned, which should be equal to the number | ||
160 | // requested unless the end of fle is encountered or an error occurs. | ||
161 | |||
162 | uint32_t WavpackUnpackSamples (WavpackContext *wpc, int32_t *buffer, uint32_t samples) | ||
163 | { | ||
164 | WavpackStream *wps = &wpc->stream; | ||
165 | uint32_t bcount, samples_unpacked = 0, samples_to_unpack; | ||
166 | int num_channels = wpc->config.num_channels; | ||
167 | |||
168 | while (samples) { | ||
169 | if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || | ||
170 | wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) { | ||
171 | bcount = read_next_header (wpc->infile, &wps->wphdr); | ||
172 | |||
173 | if (bcount == (uint32_t) -1) | ||
174 | break; | ||
175 | |||
176 | wps->block_bytes_left = wps->wphdr.ckSize - 24; | ||
177 | |||
178 | if (wps->wphdr.version < MIN_STREAM_VERS || wps->wphdr.version > MAX_STREAM_VERS) { | ||
179 | strcpy_loc (wpc->error_message, "invalid WavPack file!"); | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | if (!wps->wphdr.block_samples || wps->sample_index == wps->wphdr.block_index) | ||
184 | if (!unpack_init (wpc)) | ||
185 | break; | ||
186 | } | ||
187 | |||
188 | if (!wps->wphdr.block_samples || !(wps->wphdr.flags & INITIAL_BLOCK) || | ||
189 | wps->sample_index >= wps->wphdr.block_index + wps->wphdr.block_samples) | ||
190 | continue; | ||
191 | |||
192 | if (wps->sample_index < wps->wphdr.block_index) { | ||
193 | samples_to_unpack = wps->wphdr.block_index - wps->sample_index; | ||
194 | |||
195 | if (samples_to_unpack > samples) | ||
196 | samples_to_unpack = samples; | ||
197 | |||
198 | wps->sample_index += samples_to_unpack; | ||
199 | samples_unpacked += samples_to_unpack; | ||
200 | samples -= samples_to_unpack; | ||
201 | |||
202 | if (wpc->reduced_channels) | ||
203 | samples_to_unpack *= wpc->reduced_channels; | ||
204 | else | ||
205 | samples_to_unpack *= num_channels; | ||
206 | |||
207 | while (samples_to_unpack--) | ||
208 | *buffer++ = 0; | ||
209 | |||
210 | continue; | ||
211 | } | ||
212 | |||
213 | samples_to_unpack = wps->wphdr.block_index + wps->wphdr.block_samples - wps->sample_index; | ||
214 | |||
215 | if (samples_to_unpack > samples) | ||
216 | samples_to_unpack = samples; | ||
217 | |||
218 | unpack_samples (wpc, buffer, samples_to_unpack); | ||
219 | |||
220 | if (wpc->reduced_channels) | ||
221 | buffer += samples_to_unpack * wpc->reduced_channels; | ||
222 | else | ||
223 | buffer += samples_to_unpack * num_channels; | ||
224 | |||
225 | samples_unpacked += samples_to_unpack; | ||
226 | samples -= samples_to_unpack; | ||
227 | |||
228 | if (wps->sample_index == wps->wphdr.block_index + wps->wphdr.block_samples) { | ||
229 | if (check_crc_error (wpc)) | ||
230 | wpc->crc_errors++; | ||
231 | } | ||
232 | |||
233 | if (wps->sample_index == wpc->total_samples) | ||
234 | break; | ||
235 | } | ||
236 | |||
237 | return samples_unpacked; | ||
238 | } | ||
239 | |||
240 | // Get total number of samples contained in the WavPack file, or -1 if unknown | ||
241 | |||
242 | uint32_t WavpackGetNumSamples (WavpackContext *wpc) | ||
243 | { | ||
244 | return wpc ? wpc->total_samples : (uint32_t) -1; | ||
245 | } | ||
246 | |||
247 | // Get the current sample index position, or -1 if unknown | ||
248 | |||
249 | uint32_t WavpackGetSampleIndex (WavpackContext *wpc) | ||
250 | { | ||
251 | if (wpc) | ||
252 | return wpc->stream.sample_index; | ||
253 | |||
254 | return (uint32_t) -1; | ||
255 | } | ||
256 | |||
257 | // Get the number of errors encountered so far | ||
258 | |||
259 | int WavpackGetNumErrors (WavpackContext *wpc) | ||
260 | { | ||
261 | return wpc ? wpc->crc_errors : 0; | ||
262 | } | ||
263 | |||
264 | // return TRUE if any uncorrected lossy blocks were actually written or read | ||
265 | |||
266 | int WavpackLossyBlocks (WavpackContext *wpc) | ||
267 | { | ||
268 | return wpc ? wpc->lossy_blocks : 0; | ||
269 | } | ||
270 | |||
271 | // Returns the sample rate of the specified WavPack file | ||
272 | |||
273 | uint32_t WavpackGetSampleRate (WavpackContext *wpc) | ||
274 | { | ||
275 | return wpc ? wpc->config.sample_rate : 44100; | ||
276 | } | ||
277 | |||
278 | // Returns the number of channels of the specified WavPack file. Note that | ||
279 | // this is the actual number of channels contained in the file, but this | ||
280 | // version can only decode the first two. | ||
281 | |||
282 | int WavpackGetNumChannels (WavpackContext *wpc) | ||
283 | { | ||
284 | return wpc ? wpc->config.num_channels : 2; | ||
285 | } | ||
286 | |||
287 | // Returns the actual number of valid bits per sample contained in the | ||
288 | // original file, which may or may not be a multiple of 8. Floating data | ||
289 | // always has 32 bits, integers may be from 1 to 32 bits each. When this | ||
290 | // value is not a multiple of 8, then the "extra" bits are located in the | ||
291 | // LSBs of the results. That is, values are right justified when unpacked | ||
292 | // into int32_t's, but are left justified in the number of bytes used by the | ||
293 | // original data. | ||
294 | |||
295 | int WavpackGetBitsPerSample (WavpackContext *wpc) | ||
296 | { | ||
297 | return wpc ? wpc->config.bits_per_sample : 16; | ||
298 | } | ||
299 | |||
300 | // Returns the number of bytes used for each sample (1 to 4) in the original | ||
301 | // file. This is required information for the user of this module because the | ||
302 | // audio data is returned in the LOWER bytes of the int32_t buffer and must be | ||
303 | // left-shifted 8, 16, or 24 bits if normalized int32_t's are required. | ||
304 | |||
305 | int WavpackGetBytesPerSample (WavpackContext *wpc) | ||
306 | { | ||
307 | return wpc ? wpc->config.bytes_per_sample : 2; | ||
308 | } | ||
309 | |||
310 | // This function will return the actual number of channels decoded from the | ||
311 | // file (which may or may not be less than the actual number of channels, but | ||
312 | // will always be 1 or 2). Normally, this will be the front left and right | ||
313 | // channels of a multi-channel file. | ||
314 | |||
315 | int WavpackGetReducedChannels (WavpackContext *wpc) | ||
316 | { | ||
317 | if (wpc) | ||
318 | return wpc->reduced_channels ? wpc->reduced_channels : wpc->config.num_channels; | ||
319 | else | ||
320 | return 2; | ||
321 | } | ||
322 | |||
323 | // Read from current file position until a valid 32-byte WavPack 4.0 header is | ||
324 | // found and read into the specified pointer. The number of bytes skipped is | ||
325 | // returned. If no WavPack header is found within 1 meg, then a -1 is returned | ||
326 | // to indicate the error. No additional bytes are read past the header and it | ||
327 | // is returned in the processor's native endian mode. Seeking is not required. | ||
328 | |||
329 | static uint32_t read_next_header (read_stream infile, WavpackHeader *wphdr) | ||
330 | { | ||
331 | char buffer [sizeof (*wphdr)], *sp = buffer + sizeof (*wphdr), *ep = sp; | ||
332 | uint32_t bytes_skipped = 0; | ||
333 | int bleft; | ||
334 | |||
335 | while (1) { | ||
336 | if (sp < ep) { | ||
337 | bleft = ep - sp; | ||
338 | memcpy (buffer, sp, bleft); | ||
339 | } | ||
340 | else | ||
341 | bleft = 0; | ||
342 | |||
343 | if (infile (buffer + bleft, sizeof (*wphdr) - bleft) != (int32_t) sizeof (*wphdr) - bleft) | ||
344 | return -1; | ||
345 | |||
346 | sp = buffer; | ||
347 | |||
348 | if (*sp++ == 'w' && *sp == 'v' && *++sp == 'p' && *++sp == 'k' && | ||
349 | !(*++sp & 1) && sp [2] < 16 && !sp [3] && sp [5] == 4 && | ||
350 | sp [4] >= (MIN_STREAM_VERS & 0xff) && sp [4] <= (MAX_STREAM_VERS & 0xff)) { | ||
351 | memcpy (wphdr, buffer, sizeof (*wphdr)); | ||
352 | little_endian_to_native (wphdr, WavpackHeaderFormat); | ||
353 | return bytes_skipped; | ||
354 | } | ||
355 | |||
356 | while (sp < ep && *sp != 'w') | ||
357 | sp++; | ||
358 | |||
359 | if ((bytes_skipped += sp - buffer) > 1024 * 1024) | ||
360 | return -1; | ||
361 | } | ||
362 | } | ||
363 | |||
364 | // Open context for writing WavPack files. The returned context pointer is used | ||
365 | // in all following calls to the library. A return value of NULL indicates | ||
366 | // that memory could not be allocated for the context. | ||
367 | |||
368 | WavpackContext *WavpackOpenFileOutput (void) | ||
369 | { | ||
370 | CLEAR (wpc); | ||
371 | return &wpc; | ||
372 | } | ||
373 | |||
374 | // Set configuration for writing WavPack files. This must be done before | ||
375 | // sending any actual samples, however it is okay to send wrapper or other | ||
376 | // metadata before calling this. The "config" structure contains the following | ||
377 | // required information: | ||
378 | |||
379 | // config->bytes_per_sample see WavpackGetBytesPerSample() for info | ||
380 | // config->bits_per_sample see WavpackGetBitsPerSample() for info | ||
381 | // config->num_channels self evident | ||
382 | // config->sample_rate self evident | ||
383 | |||
384 | // In addition, the following fields and flags may be set: | ||
385 | |||
386 | // config->flags: | ||
387 | // -------------- | ||
388 | // o CONFIG_HYBRID_FLAG select hybrid mode (must set bitrate) | ||
389 | // o CONFIG_JOINT_STEREO select joint stereo (must set override also) | ||
390 | // o CONFIG_JOINT_OVERRIDE override default joint stereo selection | ||
391 | // o CONFIG_HYBRID_SHAPE select hybrid noise shaping (set override & | ||
392 | // shaping_weight != 0.0) | ||
393 | // o CONFIG_SHAPE_OVERRIDE override default hybrid noise shaping | ||
394 | // (set CONFIG_HYBRID_SHAPE and shaping_weight) | ||
395 | // o CONFIG_FAST_FLAG "fast" compression mode | ||
396 | // o CONFIG_HIGH_FLAG "high" compression mode | ||
397 | // o CONFIG_BITRATE_KBPS hybrid bitrate is kbps, not bits / sample | ||
398 | |||
399 | // config->bitrate hybrid bitrate in either bits/sample or kbps | ||
400 | // config->shaping_weight hybrid noise shaping coefficient override | ||
401 | // config->float_norm_exp select floating-point data (127 for +/-1.0) | ||
402 | |||
403 | // If the number of samples to be written is known then it should be passed | ||
404 | // here. If the duration is not known then pass -1. In the case that the size | ||
405 | // is not known (or the writing is terminated early) then it is suggested that | ||
406 | // the application retrieve the first block written and let the library update | ||
407 | // the total samples indication. A function is provided to do this update and | ||
408 | // it should be done to the "correction" file also. If this cannot be done | ||
409 | // (because a pipe is being used, for instance) then a valid WavPack will still | ||
410 | // be created, but when applications want to access that file they will have | ||
411 | // to seek all the way to the end to determine the actual duration. Also, if | ||
412 | // a RIFF header has been included then it should be updated as well or the | ||
413 | // WavPack file will not be directly unpackable to a valid wav file (although | ||
414 | // it will still be usable by itself). A return of FALSE indicates an error. | ||
415 | |||
416 | int WavpackSetConfiguration (WavpackContext *wpc, WavpackConfig *config, uint32_t total_samples) | ||
417 | { | ||
418 | WavpackStream *wps = &wpc->stream; | ||
419 | uint32_t flags = (config->bytes_per_sample - 1), shift = 0; | ||
420 | int num_chans = config->num_channels; | ||
421 | int i; | ||
422 | |||
423 | if ((wpc->config.flags & CONFIG_HYBRID_FLAG) || | ||
424 | wpc->config.float_norm_exp || | ||
425 | num_chans < 1 || num_chans > 2) | ||
426 | return FALSE; | ||
427 | |||
428 | wpc->total_samples = total_samples; | ||
429 | wpc->config.sample_rate = config->sample_rate; | ||
430 | wpc->config.num_channels = config->num_channels; | ||
431 | wpc->config.bits_per_sample = config->bits_per_sample; | ||
432 | wpc->config.bytes_per_sample = config->bytes_per_sample; | ||
433 | wpc->config.flags = config->flags; | ||
434 | |||
435 | shift = (config->bytes_per_sample * 8) - config->bits_per_sample; | ||
436 | |||
437 | for (i = 0; i < 15; ++i) | ||
438 | if (wpc->config.sample_rate == sample_rates [i]) | ||
439 | break; | ||
440 | |||
441 | flags |= i << SRATE_LSB; | ||
442 | flags |= shift << SHIFT_LSB; | ||
443 | flags |= CROSS_DECORR; | ||
444 | |||
445 | if (!(config->flags & CONFIG_JOINT_OVERRIDE) || (config->flags & CONFIG_JOINT_STEREO)) | ||
446 | flags |= JOINT_STEREO; | ||
447 | |||
448 | flags |= INITIAL_BLOCK | FINAL_BLOCK; | ||
449 | |||
450 | if (num_chans == 1) { | ||
451 | flags &= ~(JOINT_STEREO | CROSS_DECORR | HYBRID_BALANCE); | ||
452 | flags |= MONO_FLAG; | ||
453 | } | ||
454 | |||
455 | flags &= ~MAG_MASK; | ||
456 | flags += (1 << MAG_LSB) * ((flags & BYTES_STORED) * 8 + 7); | ||
457 | |||
458 | memcpy (wps->wphdr.ckID, "wvpk", 4); | ||
459 | wps->wphdr.ckSize = sizeof (WavpackHeader) - 8; | ||
460 | wps->wphdr.total_samples = wpc->total_samples; | ||
461 | wps->wphdr.version = CUR_STREAM_VERS; | ||
462 | wps->wphdr.flags = flags; | ||
463 | |||
464 | pack_init (wpc); | ||
465 | return TRUE; | ||
466 | } | ||
467 | |||
468 | // Add wrapper (currently RIFF only) to WavPack blocks. This should be called | ||
469 | // before sending any audio samples. If the exact contents of the RIFF header | ||
470 | // are not known because, for example, the file duration is uncertain or | ||
471 | // trailing chunks are possible, simply write a "dummy" header of the correct | ||
472 | // length. When all data has been written it will be possible to read the | ||
473 | // first block written and update the header directly. An example of this can | ||
474 | // be found in the Audition filter. | ||
475 | |||
476 | void WavpackAddWrapper (WavpackContext *wpc, void *data, uint32_t bcount) | ||
477 | { | ||
478 | wpc->wrapper_data = data; | ||
479 | wpc->wrapper_bytes = bcount; | ||
480 | } | ||
481 | |||
482 | // Start a WavPack block to be stored in the specified buffer. This must be | ||
483 | // called before calling WavpackPackSamples(). Note that writing CANNOT wrap | ||
484 | // in the buffer; the entire output block must fit in the buffer. | ||
485 | |||
486 | int WavpackStartBlock (WavpackContext *wpc, uchar *begin, uchar *end) | ||
487 | { | ||
488 | wpc->stream.blockbuff = begin; | ||
489 | wpc->stream.blockend = end; | ||
490 | return pack_start_block (wpc); | ||
491 | } | ||
492 | |||
493 | // Pack the specified samples. Samples must be stored in int32_ts in the native | ||
494 | // endian format of the executing processor. The number of samples specified | ||
495 | // indicates composite samples (sometimes called "frames"). So, the actual | ||
496 | // number of data points would be this "sample_count" times the number of | ||
497 | // channels. The caller must decide how many samples to place in each | ||
498 | // WavPack block (1/2 second is common), but this function may be called as | ||
499 | // many times as desired to build the final block (and performs the actual | ||
500 | // compression during the call). A return of FALSE indicates an error. | ||
501 | |||
502 | int WavpackPackSamples (WavpackContext *wpc, int32_t *sample_buffer, uint32_t sample_count) | ||
503 | { | ||
504 | if (!sample_count || pack_samples (wpc, sample_buffer, sample_count)) | ||
505 | return TRUE; | ||
506 | |||
507 | strcpy_loc (wpc->error_message, "output buffer overflowed!"); | ||
508 | return FALSE; | ||
509 | } | ||
510 | |||
511 | // Finish the WavPack block being built, returning the total size of the | ||
512 | // block in bytes. Note that the possible conversion of the WavPack header to | ||
513 | // little-endian takes place here. | ||
514 | |||
515 | uint32_t WavpackFinishBlock (WavpackContext *wpc) | ||
516 | { | ||
517 | WavpackStream *wps = &wpc->stream; | ||
518 | uint32_t bcount; | ||
519 | |||
520 | pack_finish_block (wpc); | ||
521 | bcount = ((WavpackHeader *) wps->blockbuff)->ckSize + 8; | ||
522 | native_to_little_endian ((WavpackHeader *) wps->blockbuff, WavpackHeaderFormat); | ||
523 | |||
524 | return bcount; | ||
525 | } | ||
526 | |||
527 | // Given the pointer to the first block written (to either a .wv or .wvc file), | ||
528 | // update the block with the actual number of samples written. This should | ||
529 | // be done if WavpackSetConfiguration() was called with an incorrect number | ||
530 | // of samples (or -1). It is the responsibility of the application to read and | ||
531 | // rewrite the block. An example of this can be found in the Audition filter. | ||
532 | |||
533 | void WavpackUpdateNumSamples (WavpackContext *wpc, void *first_block) | ||
534 | { | ||
535 | little_endian_to_native (wpc, WavpackHeaderFormat); | ||
536 | ((WavpackHeader *) first_block)->total_samples = WavpackGetSampleIndex (wpc); | ||
537 | native_to_little_endian (wpc, WavpackHeaderFormat); | ||
538 | } | ||
539 | |||
540 | // Given the pointer to the first block written to a WavPack file, this | ||
541 | // function returns the location of the stored RIFF header that was originally | ||
542 | // written with WavpackAddWrapper(). This would normally be used to update | ||
543 | // the wav header to indicate that a different number of samples was actually | ||
544 | // written or if additional RIFF chunks are written at the end of the file. | ||
545 | // It is the responsibility of the application to read and rewrite the block. | ||
546 | // An example of this can be found in the Audition filter. | ||
547 | |||
548 | void *WavpackGetWrapperLocation (void *first_block) | ||
549 | { | ||
550 | if (((uchar *) first_block) [32] == ID_RIFF_HEADER) | ||
551 | return ((uchar *) first_block) + 34; | ||
552 | else | ||
553 | return NULL; | ||
554 | } | ||
555 | |||