formats: clarify setting of reverse_bytes
[sox.git] / src / voc.c
bloba75639e94ea77802ab1676379d829d9fb7681156
1 /* libSoX Sound Blaster VOC handler sources.
2 * Copyright 1991 Lance Norskog And Sundry Contributors
4 * This source code is freely redistributable and may be used for
5 * any purpose. This copyright notice must be maintained.
6 * Lance Norskog And Sundry Contributors are not responsible for
7 * the consequences of using this software.
9 * September 8, 1993
10 * Copyright 1993 T. Allen Grider - for changes to support block type 9
11 * and word sized samples. Same caveats and disclaimer as above.
13 * February 22, 1996
14 * by Chris Bagwell (cbagwell@sprynet.com)
15 * Added support for block type 8 (extended) which allows for 8-bit stereo
16 * files. Added support for saving stereo files and 16-bit files.
17 * Added VOC format info from audio format FAQ so I don't have to keep
18 * looking around for it.
20 * February 5, 2001
21 * For sox-12-17 by Annonymous (see notes ANN)
22 * Added comments and notes for each procedure.
23 * Fixed so this now works with pipes, input does not have to
24 * be seekable anymore (in startread() )
25 * Added support for uLAW and aLaw (aLaw not tested).
26 * Fixed support of multi-part VOC files, and files with
27 * block 9 but no audio in the block....
28 * The following need to be tested: 16-bit, 2 channel, and aLaw.
30 * December 10, 2001
31 * For sox-12-17-3 by Annonymous (see notes ANN)
32 * Patch for sox-12-17 merged with sox-12-17-3-pre3 code.
36 /*------------------------------------------------------------------------
37 The following is taken from the Audio File Formats FAQ dated 2-Jan-1995
38 and submitted by Guido van Rossum <guido@cwi.nl>.
39 --------------------------------------------------------------------------
40 Creative Voice (VOC) file format
41 --------------------------------
43 From: galt@dsd.es.com
45 (byte numbers are hex!)
47 HEADER (bytes 00-19)
48 Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
50 - ---------------------------------------------------------------
52 HEADER:
53 -------
54 byte # Description
55 ------ ------------------------------------------
56 00-12 "Creative Voice File"
57 13 1A (eof to abort printing of file)
58 14-15 Offset of first datablock in .voc file (std 1A 00
59 in Intel Notation)
60 16-17 Version number (minor,major) (VOC-HDR puts 0A 01)
61 18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11)
63 - ---------------------------------------------------------------
65 DATA BLOCK:
66 -----------
68 Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes)
69 NOTE: Terminator Block is an exception -- it has only the TYPE byte.
71 TYPE Description Size (3-byte int) Info
72 ---- ----------- ----------------- -----------------------
73 00 Terminator (NONE) (NONE)
74 01 Sound data 2+length of data *
75 02 Sound continue length of data Voice Data
76 03 Silence 3 **
77 04 Marker 2 Marker# (2 bytes)
78 05 ASCII length of string null terminated string
79 06 Repeat 2 Count# (2 bytes)
80 07 End repeat 0 (NONE)
81 08 Extended 4 ***
82 09 New Header 16 see below
85 *Sound Info Format: **Silence Info Format:
86 --------------------- ----------------------------
87 00 Sample Rate 00-01 Length of silence - 1
88 01 Compression Type 02 Sample Rate
89 02+ Voice Data
91 ***Extended Info Format:
92 ---------------------
93 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate)
94 Stereo: 65536 - (25600000/(2*sample_rate))
95 02 Pack
96 03 Mode: 0 = mono
97 1 = stereo
100 Marker# -- Driver keeps the most recent marker in a status byte
101 Count# -- Number of repetitions + 1
102 Count# may be 1 to FFFE for 0 - FFFD repetitions
103 or FFFF for endless repetitions
104 Sample Rate -- SR byte = 256-(1000000/sample_rate)
105 Length of silence -- in units of sampling cycle
106 Compression Type -- of voice data
107 8-bits = 0
108 4-bits = 1
109 2.6-bits = 2
110 2-bits = 3
111 Multi DAC = 3+(# of channels) [interesting--
112 this isn't in the developer's manual]
114 Detailed description of new data blocks (VOC files version 1.20 and above):
116 (Source is fax from Barry Boone at Creative Labs, 405/742-6622)
118 BLOCK 8 - digitized sound attribute extension, must preceed block 1.
119 Used to define stereo, 8 bit audio
120 BYTE bBlockID; // = 8
121 BYTE nBlockLen[3]; // 3 byte length
122 WORD wTimeConstant; // time constant = same as block 1
123 BYTE bPackMethod; // same as in block 1
124 BYTE bVoiceMode; // 0-mono, 1-stereo
126 Data is stored left, right
128 BLOCK 9 - data block that supersedes blocks 1 and 8.
129 Used for stereo, 16 bit (and uLaw, aLaw).
131 BYTE bBlockID; // = 9
132 BYTE nBlockLen[3]; // length 12 plus length of sound
133 DWORD dwSamplesPerSec; // samples per second, not time const.
134 BYTE bBitsPerSample; // e.g., 8 or 16
135 BYTE bChannels; // 1 for mono, 2 for stereo
136 WORD wFormat; // see below
137 BYTE reserved[4]; // pad to make block w/o data
138 // have a size of 16 bytes
140 Valid values of wFormat are:
142 0x0000 8-bit unsigned PCM
143 0x0001 Creative 8-bit to 4-bit ADPCM
144 0x0002 Creative 8-bit to 3-bit ADPCM
145 0x0003 Creative 8-bit to 2-bit ADPCM
146 0x0004 16-bit signed PCM
147 0x0006 CCITT a-Law
148 0x0007 CCITT u-Law
149 0x02000 Creative 16-bit to 4-bit ADPCM
151 Data is stored left, right
153 ANN: Multi-byte quantities are in Intel byte order (Little Endian).
155 ------------------------------------------------------------------------*/
157 #include "sox_i.h"
158 #include "g711.h"
159 #include "adpcms.h"
160 #include <assert.h>
161 #include <string.h>
163 /* Private data for VOC file */
164 typedef struct {
165 long block_remaining; /* bytes remaining in current block */
166 long rate; /* rate code (byte) of this chunk */
167 int silent; /* sound or silence? */
168 long srate; /* rate code (byte) of silence */
169 size_t blockseek; /* start of current output block */
170 long samples; /* number of samples output */
171 int format; /* VOC audio format */
172 int size; /* word length of data */
173 int channels; /* number of sound channels */
174 long total_size; /* total size of all audio in file */
175 int extended; /* Has an extended block been read? */
176 adpcm_t adpcm;
177 } priv_t;
179 #define VOC_TERM 0
180 #define VOC_DATA 1
181 #define VOC_CONT 2
182 #define VOC_SILENCE 3
183 #define VOC_MARKER 4
184 #define VOC_TEXT 5
185 #define VOC_LOOP 6
186 #define VOC_LOOPEND 7
187 #define VOC_EXTENDED 8
188 #define VOC_DATA_16 9
190 /* ANN: Format encoding types */
191 #define VOC_FMT_LIN8U 0 /* 8 bit unsigned linear PCM */
192 #define VOC_FMT_CRLADPCM4 1 /* Creative 8-bit to 4-bit ADPCM */
193 #define VOC_FMT_CRLADPCM3 2 /* Creative 8-bit to 3-bit ADPCM */
194 #define VOC_FMT_CRLADPCM2 3 /* Creative 8-bit to 2-bit ADPCM */
195 #define VOC_FMT_LIN16 4 /* 16-bit signed PCM */
196 #define VOC_FMT_ALAW 6 /* CCITT a-Law 8-bit PCM */
197 #define VOC_FMT_MU255 7 /* CCITT u-Law 8-bit PCM */
198 #define VOC_FMT_CRLADPCM4A 0x200 /* Creative 16-bit to 4-bit ADPCM */
200 /* Prototypes for internal functions */
201 static int getblock(sox_format_t *);
202 static void blockstart(sox_format_t *);
204 /* Conversion macros (from raw.c) */
205 #define SOX_ALAW_BYTE_TO_SAMPLE(d) ((sox_sample_t)(sox_alaw2linear16(d)) << 16)
206 #define SOX_ULAW_BYTE_TO_SAMPLE(d) ((sox_sample_t)(sox_ulaw2linear16(d)) << 16)
208 /* public VOC functions for SOX */
210 /*-----------------------------------------------------------------
211 * startread() -- start reading a VOC file
212 *-----------------------------------------------------------------*/
213 static int startread(sox_format_t * ft)
215 char header[20];
216 priv_t * v = (priv_t *) ft->priv;
217 unsigned short sbseek;
218 int rc;
219 int ii; /* for getting rid of lseek */
220 unsigned char uc;
222 if (lsx_readbuf(ft, header, (size_t)20) != 20) {
223 lsx_fail_errno(ft, SOX_EHDR, "unexpected EOF in VOC header");
224 return (SOX_EOF);
226 if (strncmp(header, "Creative Voice File\032", (size_t)19)) {
227 lsx_fail_errno(ft, SOX_EHDR, "VOC file header incorrect");
228 return (SOX_EOF);
231 /* read the offset to data, from start of file */
232 /* after this read we have read 20 bytes of header + 2 */
233 lsx_readw(ft, &sbseek);
235 /* ANN: read to skip the header, instead of lseek */
236 /* this should allow use with pipes.... */
237 for (ii = 22; ii < sbseek; ii++)
238 lsx_readb(ft, &uc);
240 v->rate = -1;
241 v->format = -1;
242 v->channels = -1;
243 v->block_remaining = 0;
244 v->total_size = 0; /* ANN added */
245 v->extended = 0;
247 /* read until we get the format information.... */
248 rc = getblock(ft);
249 if (rc)
250 return rc;
252 /* get rate of data */
253 if (v->rate == -1) {
254 lsx_fail_errno(ft, SOX_EOF, "Input .voc file had no sound!");
255 return (SOX_EOF);
258 /* setup word length of data */
260 /* ANN: Check VOC format and map to the proper libSoX format value */
261 switch (v->format) {
262 case VOC_FMT_LIN8U: /* 0 8 bit unsigned linear PCM */
263 ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
264 v->size = 8;
265 break;
266 case VOC_FMT_CRLADPCM4: /* 1 Creative 8-bit to 4-bit ADPCM */
267 ft->encoding.encoding = SOX_ENCODING_CL_ADPCM;
268 v->size = 4;
269 break;
270 case VOC_FMT_CRLADPCM3: /* 2 Creative 8-bit to 3-bit ADPCM */
271 ft->encoding.encoding = SOX_ENCODING_CL_ADPCM;
272 v->size = 3;
273 break;
274 case VOC_FMT_CRLADPCM2: /* 3 Creative 8-bit to 2-bit ADPCM */
275 ft->encoding.encoding = SOX_ENCODING_CL_ADPCM;
276 v->size = 2;
277 break;
278 case VOC_FMT_LIN16: /* 4 16-bit signed PCM */
279 ft->encoding.encoding = SOX_ENCODING_SIGN2;
280 v->size = 16;
281 break;
282 case VOC_FMT_ALAW: /* 6 CCITT a-Law 8-bit PCM */
283 ft->encoding.encoding = SOX_ENCODING_ALAW;
284 v->size = 8;
285 break;
286 case VOC_FMT_MU255: /* 7 CCITT u-Law 8-bit PCM */
287 ft->encoding.encoding = SOX_ENCODING_ULAW;
288 v->size = 8;
289 break;
290 case VOC_FMT_CRLADPCM4A: /*0x200 Creative 16-bit to 4-bit ADPCM */
291 ft->encoding.encoding = SOX_ENCODING_CL_ADPCM16;
292 v->size = 4;
293 break;
294 default:
295 lsx_fail("Unknown VOC format %d", v->format);
296 break;
298 ft->encoding.bits_per_sample = v->size;
300 /* setup number of channels */
301 if (ft->signal.channels == 0)
302 ft->signal.channels = v->channels;
304 return (SOX_SUCCESS);
307 /*-----------------------------------------------------------------
308 * read() -- read data from a VOC file
309 * ANN: Major changes here to support multi-part files and files
310 * that do not have audio in block 9's.
311 *-----------------------------------------------------------------*/
312 static size_t read_samples(sox_format_t * ft, sox_sample_t * buf,
313 size_t len)
315 priv_t * v = (priv_t *) ft->priv;
316 size_t done = 0;
317 int rc = 0;
318 int16_t sw;
319 unsigned char uc;
321 if (v->block_remaining == 0) { /* handle getting another cont. buffer */
322 rc = getblock(ft);
323 if (rc)
324 return 0;
327 if (v->block_remaining == 0) /* if no more data, return 0, i.e., done */
328 return 0;
330 if (v->silent) {
331 for (; v->block_remaining && (done < len); v->block_remaining--, done++)
332 *buf++ = 0; /* Fill in silence */
333 } else { /* not silence; read len samples of audio from the file */
334 size_t per = max(1, 9 / v->size);
336 for (; (done + per <= len); done += per) {
337 if (v->block_remaining == 0) { /* IF no more in this block, get another */
338 while (v->block_remaining == 0) { /* until have either EOF or a block with data */
339 rc = getblock(ft);
340 if (rc)
341 break;
343 if (rc) /* IF EOF, break out, no more data, next will return 0 */
344 break;
347 /* Read the data in the file */
348 if (v->size <= 4) {
349 if (!v->adpcm.setup.sign) {
350 SOX_SAMPLE_LOCALS;
351 if (lsx_readb(ft, &uc) == SOX_EOF) {
352 lsx_warn("VOC input: short file");
353 v->block_remaining = 0;
354 return done;
356 *buf = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,);
357 lsx_adpcm_init(&v->adpcm, 6 - v->size, SOX_SAMPLE_TO_SIGNED_16BIT(*buf, ft->clips));
358 ++buf;
359 --v->block_remaining;
360 ++done;
362 if (lsx_readb(ft, &uc) == SOX_EOF) {
363 lsx_warn("VOC input: short file");
364 v->block_remaining = 0;
365 return done;
367 switch (v->size) {
368 case 2:
369 if (v->format == VOC_FMT_CRLADPCM2) {
370 int u = uc;
372 *buf++ =
373 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 6, &v->adpcm),);
374 *buf++ =
375 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),);
376 *buf++ =
377 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),);
378 *buf++ =
379 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),);
381 break;
382 case 3:
383 if (v->format == VOC_FMT_CRLADPCM3) {
384 int u = uc;
386 *buf++ =
387 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 5, &v->adpcm),);
388 *buf++ =
389 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),);
390 *buf++ = /* A bit from nowhere! */
391 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u << 1, &v->adpcm),);
393 break;
394 case 4:
395 if (v->format == VOC_FMT_CRLADPCM4) {
396 int u = uc;
398 *buf++ =
399 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),);
400 *buf++ =
401 SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),);
403 break;
405 } else
406 switch (v->size) {
407 case 8:
408 if (lsx_readb(ft, &uc) == SOX_EOF) {
409 lsx_warn("VOC input: short file");
410 v->block_remaining = 0;
411 return done;
413 if (v->format == VOC_FMT_MU255) {
414 *buf++ = SOX_ULAW_BYTE_TO_SAMPLE(uc);
415 } else if (v->format == VOC_FMT_ALAW) {
416 *buf++ = SOX_ALAW_BYTE_TO_SAMPLE(uc);
417 } else {
418 *buf++ = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,);
420 break;
421 case 16:
422 lsx_readsw(ft, &sw);
423 if (lsx_eof(ft)) {
424 lsx_warn("VOC input: short file");
425 v->block_remaining = 0;
426 return done;
428 *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(sw,);
429 v->block_remaining--; /* Processed 2 bytes so update */
430 break;
432 /* decrement count of processed bytes */
433 v->block_remaining--;
436 v->total_size += done;
437 return done;
441 /* When saving samples in VOC format the following outline is followed:
442 * If an 8-bit mono sample then use a VOC_DATA header.
443 * If an 8-bit stereo sample then use a VOC_EXTENDED header followed
444 * by a VOC_DATA header.
445 * If a 16-bit sample (either stereo or mono) then save with a
446 * VOC_DATA_16 header.
448 * ANN: Not supported: uLaw and aLaw output VOC files....
450 * This approach will cause the output to be an its most basic format
451 * which will work with the oldest software (eg. an 8-bit mono sample
452 * will be able to be played with a really old SB VOC player.)
454 static int startwrite(sox_format_t * ft)
456 priv_t * v = (priv_t *) ft->priv;
458 if (!ft->seekable) {
459 lsx_fail_errno(ft, SOX_EOF,
460 "Output .voc file must be a file, not a pipe");
461 return (SOX_EOF);
464 v->samples = 0;
466 /* File format name and a ^Z (aborts printing under DOS) */
467 lsx_writes(ft, "Creative Voice File\032");
468 lsx_writew(ft, 26); /* size of header */
469 lsx_writew(ft, 0x10a); /* major/minor version number */
470 lsx_writew(ft, 0x1129); /* checksum of version number */
472 return (SOX_SUCCESS);
475 /*-----------------------------------------------------------------
476 * write() -- write a VOC file
477 *-----------------------------------------------------------------*/
478 static size_t write_samples(sox_format_t * ft, const sox_sample_t * buf,
479 size_t len)
481 priv_t * v = (priv_t *) ft->priv;
482 unsigned char uc;
483 int16_t sw;
484 size_t done = 0;
486 if (len && v->samples == 0) {
487 /* No silence packing yet. */
488 v->silent = 0;
489 blockstart(ft);
491 v->samples += len;
492 while (done < len) {
493 SOX_SAMPLE_LOCALS;
494 if (ft->encoding.bits_per_sample == 8) {
495 uc = SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips);
496 lsx_writeb(ft, uc);
497 } else {
498 sw = (int) SOX_SAMPLE_TO_SIGNED_16BIT(*buf++, ft->clips);
499 lsx_writesw(ft, sw);
501 done++;
503 return done;
506 /*-----------------------------------------------------------------
507 * blockstop() -- stop an output block
508 * End the current data or silence block.
509 *-----------------------------------------------------------------*/
510 static void blockstop(sox_format_t * ft)
512 priv_t * v = (priv_t *) ft->priv;
513 sox_sample_t datum;
515 lsx_writeb(ft, 0); /* End of file block code */
516 lsx_seeki(ft, (off_t) v->blockseek, 0); /* seek back to block length */
517 lsx_seeki(ft, (off_t)1, 1); /* seek forward one */
518 if (v->silent) {
519 lsx_writesw(ft, (signed)v->samples);
520 } else {
521 if (ft->encoding.bits_per_sample == 8) {
522 if (ft->signal.channels > 1) {
523 lsx_seeki(ft, (off_t)8, 1); /* forward 7 + 1 for new block header */
526 v->samples += 2; /* adjustment: SBDK pp. 3-5 */
527 datum = (v->samples * (ft->encoding.bits_per_sample >> 3)) & 0xff;
528 lsx_writesb(ft, datum); /* low byte of length */
529 datum = ((v->samples * (ft->encoding.bits_per_sample >> 3)) >> 8) & 0xff;
530 lsx_writesb(ft, datum); /* middle byte of length */
531 datum = ((v->samples * (ft->encoding.bits_per_sample >> 3)) >> 16) & 0xff;
532 lsx_writesb(ft, datum); /* high byte of length */
536 /*-----------------------------------------------------------------
537 * stopwrite() -- stop writing a VOC file
538 *-----------------------------------------------------------------*/
539 static int stopwrite(sox_format_t * ft)
541 blockstop(ft);
542 return (SOX_SUCCESS);
545 /*-----------------------------------------------------------------
546 * Voc-file handlers (static, private to this module)
547 *-----------------------------------------------------------------*/
549 /*-----------------------------------------------------------------
550 * getblock() -- Read next block header, save info,
551 * leave position at start of dat
552 *-----------------------------------------------------------------*/
553 static int getblock(sox_format_t * ft)
555 priv_t * v = (priv_t *) ft->priv;
556 unsigned char uc, block;
557 uint16_t u16;
558 sox_uint24_t sblen;
559 uint16_t new_rate_16;
560 uint32_t new_rate_32;
562 v->silent = 0;
563 /* DO while we have no audio to read */
564 while (v->block_remaining == 0) {
565 if (lsx_eof(ft))
566 return SOX_EOF;
568 if (lsx_readb(ft, &block) == SOX_EOF)
569 return SOX_EOF;
571 if (block == VOC_TERM)
572 return SOX_EOF;
574 if (lsx_eof(ft))
575 return SOX_EOF;
577 lsx_read3(ft, &sblen);
579 /* Based on VOC block type, process the block */
580 /* audio may be in one or multiple blocks */
581 switch (block) {
582 case VOC_DATA:
583 lsx_readb(ft, &uc);
584 /* When DATA block preceeded by an EXTENDED */
585 /* block, the DATA blocks rate value is invalid */
586 if (!v->extended) {
587 if (uc == 0) {
588 lsx_fail_errno(ft, SOX_EFMT, "Sample rate is zero?");
589 return (SOX_EOF);
591 if ((v->rate != -1) && (uc != v->rate)) {
592 lsx_fail_errno(ft, SOX_EFMT,
593 "sample rate codes differ: %ld != %d", v->rate,
594 uc);
595 return (SOX_EOF);
597 v->rate = uc;
598 ft->signal.rate = 1000000.0 / (256 - v->rate);
599 if (v->channels != -1 && v->channels != 1) {
600 lsx_fail_errno(ft, SOX_EFMT, "channel count changed");
601 return SOX_EOF;
603 v->channels = 1;
605 lsx_readb(ft, &uc);
606 if (v->format != -1 && uc != v->format) {
607 lsx_fail_errno(ft, SOX_EFMT, "format changed");
608 return SOX_EOF;
610 v->format = uc;
611 v->extended = 0;
612 v->block_remaining = sblen - 2;
613 return (SOX_SUCCESS);
614 case VOC_DATA_16:
615 lsx_readdw(ft, &new_rate_32);
616 if (new_rate_32 == 0) {
617 lsx_fail_errno(ft, SOX_EFMT, "Sample rate is zero?");
618 return (SOX_EOF);
620 if ((v->rate != -1) && ((long) new_rate_32 != v->rate)) {
621 lsx_fail_errno(ft, SOX_EFMT, "sample rate codes differ: %ld != %d",
622 v->rate, new_rate_32);
623 return (SOX_EOF);
625 v->rate = new_rate_32;
626 ft->signal.rate = new_rate_32;
627 lsx_readb(ft, &uc);
628 v->size = uc;
629 lsx_readb(ft, &uc);
630 if (v->channels != -1 && uc != v->channels) {
631 lsx_fail_errno(ft, SOX_EFMT, "channel count changed");
632 return SOX_EOF;
634 v->channels = uc;
635 lsx_readw(ft, &u16); /* ANN: added format */
636 if (v->format != -1 && u16 != v->format) {
637 lsx_fail_errno(ft, SOX_EFMT, "format changed");
638 return SOX_EOF;
640 v->format = u16;
641 lsx_skipbytes(ft, (size_t) 4);
642 v->block_remaining = sblen - 12;
643 return (SOX_SUCCESS);
644 case VOC_CONT:
645 v->block_remaining = sblen;
646 return (SOX_SUCCESS);
647 case VOC_SILENCE:
649 unsigned short period;
651 lsx_readw(ft, &period);
652 lsx_readb(ft, &uc);
653 if (uc == 0) {
654 lsx_fail_errno(ft, SOX_EFMT, "Silence sample rate is zero");
655 return (SOX_EOF);
658 * Some silence-packed files have gratuitously
659 * different sample rate codes in silence.
660 * Adjust period.
662 if ((v->rate != -1) && (uc != v->rate))
663 period = (period * (256. - uc)) / (256 - v->rate) + .5;
664 else
665 v->rate = uc;
666 v->block_remaining = period;
667 v->silent = 1;
668 return (SOX_SUCCESS);
670 case VOC_MARKER:
671 lsx_readb(ft, &uc);
672 lsx_readb(ft, &uc);
673 /* Falling! Falling! */
674 case VOC_TEXT:
676 uint32_t i = sblen;
677 int8_t c /*, line_buf[80];
678 * int len = 0 */ ;
680 lsx_warn("VOC TEXT");
681 while (i--) {
682 lsx_readsb(ft, &c);
683 /* FIXME: this needs to be tested but I couldn't
684 * find a voc file with a VOC_TEXT chunk :(
685 if (c != '\0' && c != '\r')
686 line_buf[len++] = c;
687 if (len && (c == '\0' || c == '\r' ||
688 i == 0 || len == sizeof(line_buf) - 1))
690 lsx_report("%s", line_buf);
691 line_buf[len] = '\0';
692 len = 0;
697 continue; /* get next block */
698 case VOC_LOOP:
699 case VOC_LOOPEND:
700 lsx_debug("skipping repeat loop");
701 lsx_skipbytes(ft, (size_t) sblen);
702 break;
703 case VOC_EXTENDED:
704 /* An Extended block is followed by a data block */
705 /* Set this byte so we know to use the rate */
706 /* value from the extended block and not the */
707 /* data block. */
708 v->extended = 1;
709 lsx_readw(ft, &new_rate_16);
710 if (new_rate_16 == 0) {
711 lsx_fail_errno(ft, SOX_EFMT, "Sample rate is zero?");
712 return (SOX_EOF);
714 if ((v->rate != -1) && (new_rate_16 != v->rate)) {
715 lsx_fail_errno(ft, SOX_EFMT, "sample rate codes differ: %ld != %d",
716 v->rate, new_rate_16);
717 return (SOX_EOF);
719 v->rate = new_rate_16;
720 lsx_readb(ft, &uc); /* bits_per_sample */
721 lsx_readb(ft, &uc);
722 if (v->channels != -1 && uc != v->channels) {
723 lsx_fail_errno(ft, SOX_EFMT, "channel count changed");
724 return SOX_EOF;
726 v->channels = uc;
727 ft->signal.channels = uc? 2 : 1; /* Stereo */
728 /* Needed number of channels before finishing
729 * compute for rate */
730 ft->signal.rate = (256e6 / (65536 - v->rate)) / ft->signal.channels;
731 /* An extended block must be followed by a data */
732 /* block to be valid so loop back to top so it */
733 /* can be grabed. */
734 continue;
735 default:
736 lsx_debug("skipping unknown block code %d", block);
737 lsx_skipbytes(ft, (size_t) sblen);
740 return SOX_SUCCESS;
743 /*-----------------------------------------------------------------
744 * vlockstart() -- start an output block
745 *-----------------------------------------------------------------*/
746 static void blockstart(sox_format_t * ft)
748 priv_t * v = (priv_t *) ft->priv;
750 v->blockseek = lsx_tell(ft);
751 if (v->silent) {
752 lsx_writeb(ft, VOC_SILENCE); /* Silence block code */
753 lsx_writeb(ft, 0); /* Period length */
754 lsx_writeb(ft, 0); /* Period length */
755 lsx_writesb(ft, (signed)v->rate); /* Rate code */
756 } else {
757 if (ft->encoding.bits_per_sample == 8) {
758 /* 8-bit sample section. By always setting the correct */
759 /* rate value in the DATA block (even when its preceeded */
760 /* by an EXTENDED block) old software can still play stereo */
761 /* files in mono by just skipping over the EXTENDED block. */
762 /* Prehaps the rate should be doubled though to make up for */
763 /* double amount of samples for a given time???? */
764 if (ft->signal.channels > 1) {
765 lsx_writeb(ft, VOC_EXTENDED); /* Voice Extended block code */
766 lsx_writeb(ft, 4); /* block length = 4 */
767 lsx_writeb(ft, 0); /* block length = 4 */
768 lsx_writeb(ft, 0); /* block length = 4 */
769 v->rate = 65536 - (256000000.0 / (2 * ft->signal.rate)) + .5;
770 lsx_writesw(ft, (signed) v->rate); /* Rate code */
771 lsx_writeb(ft, 0); /* File is not packed */
772 lsx_writeb(ft, 1); /* samples are in stereo */
774 lsx_writeb(ft, VOC_DATA); /* Voice Data block code */
775 lsx_writeb(ft, 0); /* block length (for now) */
776 lsx_writeb(ft, 0); /* block length (for now) */
777 lsx_writeb(ft, 0); /* block length (for now) */
778 v->rate = 256 - (1000000.0 / ft->signal.rate) + .5;
779 lsx_writesb(ft, (signed) v->rate); /* Rate code */
780 lsx_writeb(ft, 0); /* 8-bit raw data */
781 } else {
782 lsx_writeb(ft, VOC_DATA_16); /* Voice Data block code */
783 lsx_writeb(ft, 0); /* block length (for now) */
784 lsx_writeb(ft, 0); /* block length (for now) */
785 lsx_writeb(ft, 0); /* block length (for now) */
786 v->rate = ft->signal.rate + .5;
787 lsx_writedw(ft, (unsigned) v->rate); /* Rate code */
788 lsx_writeb(ft, 16); /* Sample Size */
789 lsx_writeb(ft, ft->signal.channels); /* Sample Size */
790 lsx_writew(ft, 0x0004); /* Encoding */
791 lsx_writeb(ft, 0); /* Unused */
792 lsx_writeb(ft, 0); /* Unused */
793 lsx_writeb(ft, 0); /* Unused */
794 lsx_writeb(ft, 0); /* Unused */
799 LSX_FORMAT_HANDLER(voc)
801 static char const *const names[] = { "voc", NULL };
802 static unsigned const write_encodings[] = {
803 SOX_ENCODING_SIGN2, 16, 0,
804 SOX_ENCODING_UNSIGNED, 8, 0,
807 static sox_format_handler_t const handler = {SOX_LIB_VERSION_CODE,
808 "Creative Technology Sound Blaster format",
809 names, SOX_FILE_LIT_END | SOX_FILE_MONO | SOX_FILE_STEREO,
810 startread, read_samples, NULL,
811 startwrite, write_samples, stopwrite,
812 NULL, write_encodings, NULL, sizeof(priv_t)
814 return &handler;