1 /* libSoX Sound Blaster VOC handler sources.
2  * Copyright 1991 Lance Norskog And Sundry Contributors
3  *
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.
8  *
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.
12  *
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.
19  *
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.
29  *
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.
33  *
34  */
35 
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 --------------------------------
42 
43 From: galt@dsd.es.com
44 
45 (byte numbers are hex!)
46 
47     HEADER (bytes 00-19)
48     Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
49 
50 - ---------------------------------------------------------------
51 
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)
62 
63 - ---------------------------------------------------------------
64 
65 DATA BLOCK:
66 -----------
67 
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.
70 
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
83 
84 
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
90 
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
98 
99 
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]
113 
114 Detailed description of new data blocks (VOC files version 1.20 and above):
115 
116         (Source is fax from Barry Boone at Creative Labs, 405/742-6622)
117 
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
125 
126         Data is stored left, right
127 
128 BLOCK 9 - data block that supersedes blocks 1 and 8.
129           Used for stereo, 16 bit (and uLaw, aLaw).
130 
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
139 
140         Valid values of wFormat are:
141 
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
150 
151         Data is stored left, right
152 
153         ANN:  Multi-byte quantities are in Intel byte order (Little Endian).
154 
155 ------------------------------------------------------------------------*/
156 
157 #include "sox_i.h"
158 #include "g711.h"
159 #include "adpcms.h"
160 #include <assert.h>
161 #include <string.h>
162 
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;
178 
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
189 
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 */
199 
200 /* Prototypes for internal functions */
201 static int getblock(sox_format_t *);
202 static void blockstart(sox_format_t *);
203 
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)
207 
208 /* public VOC functions for SOX */
209 
210 /*-----------------------------------------------------------------
211  * startread() -- start reading a VOC file
212  *-----------------------------------------------------------------*/
startread(sox_format_t * ft)213 static int startread(sox_format_t * ft)
214 {
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;
221 
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);
225   }
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);
229   }
230 
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);
234 
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);
239 
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;
246 
247   /* read until we get the format information.... */
248   rc = getblock(ft);
249   if (rc)
250     return rc;
251 
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);
256   }
257 
258   /* setup word length of data */
259 
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;
297   }
298   ft->encoding.bits_per_sample = v->size;
299 
300   /* setup number of channels */
301   if (ft->signal.channels == 0)
302     ft->signal.channels = v->channels;
303 
304   return (SOX_SUCCESS);
305 }
306 
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  *-----------------------------------------------------------------*/
read_samples(sox_format_t * ft,sox_sample_t * buf,size_t len)312 static size_t read_samples(sox_format_t * ft, sox_sample_t * buf,
313                                size_t len)
314 {
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;
320 
321   if (v->block_remaining == 0) {        /* handle getting another cont. buffer */
322     rc = getblock(ft);
323     if (rc)
324       return 0;
325   }
326 
327   if (v->block_remaining == 0)  /* if no more data, return 0, i.e., done */
328     return 0;
329 
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);
335 
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;
342         }
343         if (rc) /* IF EOF, break out, no more data, next will return 0 */
344           break;
345       }
346 
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;
355           }
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;
361         }
362         if (lsx_readb(ft, &uc) == SOX_EOF) {
363           lsx_warn("VOC input: short file");
364           v->block_remaining = 0;
365           return done;
366         }
367         switch (v->size) {
368           case 2:
369             if (v->format == VOC_FMT_CRLADPCM2) {
370               int u = uc;
371 
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),);
380             }
381             break;
382           case 3:
383             if (v->format == VOC_FMT_CRLADPCM3) {
384               int u = uc;
385 
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),);
392             }
393             break;
394           case 4:
395             if (v->format == VOC_FMT_CRLADPCM4) {
396               int u = uc;
397 
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),);
402             }
403             break;
404         }
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;
412             }
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,);
419             }
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;
427             }
428             *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(sw,);
429             v->block_remaining--;       /* Processed 2 bytes so update */
430             break;
431         }
432       /* decrement count of processed bytes */
433       v->block_remaining--;
434     }
435   }
436   v->total_size += done;
437   return done;
438 }
439 
440 
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.
447  *
448  * ANN:  Not supported:  uLaw and aLaw output VOC files....
449  *
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.)
453  */
startwrite(sox_format_t * ft)454 static int startwrite(sox_format_t * ft)
455 {
456   priv_t * v = (priv_t *) ft->priv;
457 
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);
462   }
463 
464   v->samples = 0;
465 
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 */
471 
472   return (SOX_SUCCESS);
473 }
474 
475 /*-----------------------------------------------------------------
476  * write() -- write a VOC file
477  *-----------------------------------------------------------------*/
write_samples(sox_format_t * ft,const sox_sample_t * buf,size_t len)478 static size_t write_samples(sox_format_t * ft, const sox_sample_t * buf,
479                                 size_t len)
480 {
481   priv_t * v = (priv_t *) ft->priv;
482   unsigned char uc;
483   int16_t sw;
484   size_t done = 0;
485 
486   if (len && v->samples == 0) {
487     /* No silence packing yet. */
488     v->silent = 0;
489     blockstart(ft);
490   }
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);
500     }
501     done++;
502   }
503   return done;
504 }
505 
506 /*-----------------------------------------------------------------
507  * blockstop() -- stop an output block
508  * End the current data or silence block.
509  *-----------------------------------------------------------------*/
blockstop(sox_format_t * ft)510 static void blockstop(sox_format_t * ft)
511 {
512   priv_t * v = (priv_t *) ft->priv;
513   sox_sample_t datum;
514 
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 */
524       }
525     }
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 */
533   }
534 }
535 
536 /*-----------------------------------------------------------------
537  * stopwrite() -- stop writing a VOC file
538  *-----------------------------------------------------------------*/
stopwrite(sox_format_t * ft)539 static int stopwrite(sox_format_t * ft)
540 {
541   blockstop(ft);
542   return (SOX_SUCCESS);
543 }
544 
545 /*-----------------------------------------------------------------
546  * Voc-file handlers (static, private to this module)
547  *-----------------------------------------------------------------*/
548 
549 /*-----------------------------------------------------------------
550  * getblock() -- Read next block header, save info,
551  *               leave position at start of dat
552  *-----------------------------------------------------------------*/
getblock(sox_format_t * ft)553 static int getblock(sox_format_t * ft)
554 {
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;
561 
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;
567 
568     if (lsx_readb(ft, &block) == SOX_EOF)
569       return SOX_EOF;
570 
571     if (block == VOC_TERM)
572       return SOX_EOF;
573 
574     if (lsx_eof(ft))
575       return SOX_EOF;
576 
577     lsx_read3(ft, &sblen);
578 
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);
590           }
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);
596           }
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;
602           }
603           v->channels = 1;
604         }
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;
609         }
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);
619         }
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);
624         }
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;
633         }
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;
639         }
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:
648         {
649           unsigned short period;
650 
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);
656           }
657           /*
658            * Some silence-packed files have gratuitously
659            * different sample rate codes in silence.
660            * Adjust period.
661            */
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);
669         }
670       case VOC_MARKER:
671         lsx_readb(ft, &uc);
672         lsx_readb(ft, &uc);
673         /* Falling! Falling! */
674       case VOC_TEXT:
675         {
676           uint32_t i = sblen;
677           int8_t c                /*, line_buf[80];
678                                  * int len = 0 */ ;
679 
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))
689              {
690              lsx_report("%s", line_buf);
691              line_buf[len] = '\0';
692              len = 0;
693              }
694              */
695           }
696         }
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);
713         }
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);
718         }
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;
725         }
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);
738     }
739   }
740   return SOX_SUCCESS;
741 }
742 
743 /*-----------------------------------------------------------------
744  * vlockstart() -- start an output block
745  *-----------------------------------------------------------------*/
blockstart(sox_format_t * ft)746 static void blockstart(sox_format_t * ft)
747 {
748   priv_t * v = (priv_t *) ft->priv;
749 
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 */
773       }
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 */
795     }
796   }
797 }
798 
LSX_FORMAT_HANDLER(voc)799 LSX_FORMAT_HANDLER(voc)
800 {
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,
805     0
806   };
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)
813   };
814   return &handler;
815 }
816