2 ** Copyright (C) 2001-2004 Erik de Castro Lopo <erikd@mega-nerd.com>
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 ** GNU Lesser General Public License for more details.
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20 ** The VOC file format is the most brain damaged format I have yet had to deal
21 ** with. No one programmer could have bee stupid enough to put this together.
22 ** Instead it looks like a series of manic, dyslexic assembly language programmers
23 ** hacked it to fit their needs.
38 /*------------------------------------------------------------------------------
39 * Typedefs for file chunks.
42 #define VOC_MAX_SECTIONS 200
47 VOC_SOUND_CONTINUE = 2,
59 int offset ; /* Offset of zero => silence. */
63 { unsigned int sections, section_types ;
64 int samplerate, channels, bitwidth ;
65 SND_DATA_BLOCKS blocks [VOC_MAX_SECTIONS] ;
68 /*------------------------------------------------------------------------------
69 * Private static functions.
72 static int voc_close (SF_PRIVATE *psf) ;
73 static int voc_write_header (SF_PRIVATE *psf, int calc_length) ;
74 static int voc_read_header (SF_PRIVATE *psf) ;
76 static const char* voc_encoding2str (int encoding) ;
80 /* These functions would be required for files with more than one VOC_SOUND_DATA
81 ** segment. Not sure whether to bother implementing this.
84 static int voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc) ;
86 static int voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len) ;
87 static int voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len) ;
89 static int voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len) ;
90 static int voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len) ;
92 static int voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len) ;
93 static int voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len) ;
95 static int voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len) ;
96 static int voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len) ;
99 /*------------------------------------------------------------------------------
104 voc_open (SF_PRIVATE *psf)
105 { int subformat, error = 0 ;
108 return SFE_VOC_NO_PIPE ;
110 if (psf->mode == SFM_READ || (psf->mode == SFM_RDWR && psf->filelength > 0))
111 { if ((error = voc_read_header (psf)))
115 subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
117 if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
118 { if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_VOC)
119 return SFE_BAD_OPEN_FORMAT ;
121 psf->endian = SF_ENDIAN_LITTLE ;
123 if ((error = voc_write_header (psf, SF_FALSE)))
126 psf->write_header = voc_write_header ;
129 psf->blockwidth = psf->bytewidth * psf->sf.channels ;
131 psf->container_close = voc_close ;
134 { case SF_FORMAT_PCM_U8 :
135 case SF_FORMAT_PCM_16 :
136 error = pcm_init (psf) ;
139 case SF_FORMAT_ALAW :
140 error = alaw_init (psf) ;
143 case SF_FORMAT_ULAW :
144 error = ulaw_init (psf) ;
147 default : return SFE_UNIMPLEMENTED ;
153 /*------------------------------------------------------------------------------
157 voc_read_header (SF_PRIVATE *psf)
160 unsigned char block_type, rate_byte ;
161 short version, checksum, encoding, dataoffset ;
164 /* Set position to start of file to begin reading header. */
165 offset = psf_binheader_readf (psf, "pb", 0, creative, SIGNED_SIZEOF (creative)) ;
167 if (creative [sizeof (creative) - 1] != 0x1A)
168 return SFE_VOC_NO_CREATIVE ;
170 /* Terminate the string. */
171 creative [sizeof (creative) - 1] = 0 ;
173 if (strcmp ("Creative Voice File", creative))
174 return SFE_VOC_NO_CREATIVE ;
176 psf_log_printf (psf, "%s\n", creative) ;
178 offset += psf_binheader_readf (psf, "e222", &dataoffset, &version, &checksum) ;
180 psf->dataoffset = dataoffset ;
182 psf_log_printf (psf, "dataoffset : %d\n"
184 "checksum : 0x%X\n", psf->dataoffset, version, checksum) ;
186 if (version != 0x010A && version != 0x0114)
187 return SFE_VOC_BAD_VERSION ;
189 if (! (psf->fdata = malloc (sizeof (VOC_DATA))))
190 return SFE_MALLOC_FAILED ;
192 pvoc = (VOC_DATA*) psf->fdata ;
194 memset (pvoc, 0, sizeof (VOC_DATA)) ;
196 /* Set the default encoding now. */
197 psf->sf.format = SF_FORMAT_VOC ; /* Major format */
198 encoding = SF_FORMAT_PCM_U8 ; /* Minor format */
199 psf->endian = SF_ENDIAN_LITTLE ;
202 { offset += psf_binheader_readf (psf, "1", &block_type) ;
208 offset += psf_binheader_readf (psf, "e3", &size) ;
210 psf_log_printf (psf, " ASCII : %d\n", size) ;
212 offset += psf_binheader_readf (psf, "b", psf->header, size) ;
213 psf->header [size] = 0 ;
214 psf_log_printf (psf, " text : %s\n", psf->header) ;
218 case VOC_SOUND_DATA :
220 case VOC_EXTENDED_II :
223 default : psf_log_printf (psf, "*** Weird block marker (%d)\n", block_type) ;
229 if (block_type == VOC_SOUND_DATA)
230 { unsigned char compression ;
233 offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ;
235 psf->sf.samplerate = 1000000 / (256 - (rate_byte & 0xFF)) ;
237 psf_log_printf (psf, " Sound Data : %d\n sr : %d => %dHz\n comp : %d\n",
238 size, rate_byte, psf->sf.samplerate, compression) ;
240 if (offset + size - 1 > psf->filelength)
241 { psf_log_printf (psf, "Seems to be a truncated file.\n") ;
242 psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
243 return SFE_VOC_BAD_SECTIONS ;
245 else if (offset + size - 1 < psf->filelength)
246 { psf_log_printf (psf, "Seems to be a multi-segment file (#1).\n") ;
247 psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
248 return SFE_VOC_BAD_SECTIONS ;
251 psf->dataoffset = offset ;
252 psf->dataend = psf->filelength - 1 ;
254 psf->sf.channels = 1 ;
257 psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;
262 if (block_type == VOC_EXTENDED)
263 { unsigned char pack, stereo, compression ;
264 unsigned short rate_short ;
267 offset += psf_binheader_readf (psf, "e3211", &size, &rate_short, &pack, &stereo) ;
269 psf_log_printf (psf, " Extended : %d\n", size) ;
271 psf_log_printf (psf, " size : 4\n") ;
273 psf_log_printf (psf, " size : %d (should be 4)\n", size) ;
275 psf_log_printf (psf, " pack : %d\n"
276 " stereo : %s\n", pack, (stereo ? "yes" : "no")) ;
279 { psf->sf.channels = 2 ;
280 psf->sf.samplerate = 128000000 / (65536 - rate_short) ;
283 { psf->sf.channels = 1 ;
284 psf->sf.samplerate = 256000000 / (65536 - rate_short) ;
287 psf_log_printf (psf, " sr : %d => %dHz\n", (rate_short & 0xFFFF), psf->sf.samplerate) ;
289 offset += psf_binheader_readf (psf, "1", &block_type) ;
291 if (block_type != VOC_SOUND_DATA)
292 { psf_log_printf (psf, "*** Expecting VOC_SOUND_DATA section.\n") ;
293 return SFE_VOC_BAD_FORMAT ;
296 offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ;
298 psf_log_printf (psf, " Sound Data : %d\n"
300 " comp : %d\n", size, rate_byte, compression) ;
303 if (offset + size - 1 > psf->filelength)
304 { psf_log_printf (psf, "Seems to be a truncated file.\n") ;
305 psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
306 return SFE_VOC_BAD_SECTIONS ;
308 else if (offset + size - 1 < psf->filelength)
309 { psf_log_printf (psf, "Seems to be a multi-segment file (#2).\n") ;
310 psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ;
311 return SFE_VOC_BAD_SECTIONS ;
314 psf->dataoffset = offset ;
315 psf->dataend = psf->filelength - 1 ;
319 psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;
324 if (block_type == VOC_EXTENDED_II)
325 { unsigned char bitwidth, channels ;
326 int size, fourbytes ;
328 offset += psf_binheader_readf (psf, "e341124", &size, &psf->sf.samplerate,
329 &bitwidth, &channels, &encoding, &fourbytes) ;
331 if (size * 2 == psf->filelength - 39)
332 { int temp_size = psf->filelength - 31 ;
334 psf_log_printf (psf, " Extended II : %d (SoX bug: should be %d)\n", size, temp_size) ;
338 psf_log_printf (psf, " Extended II : %d\n", size) ;
340 psf_log_printf (psf, " sample rate : %d\n"
342 " channels : %d\n", psf->sf.samplerate, bitwidth, channels) ;
344 if (bitwidth == 16 && encoding == 0)
346 psf_log_printf (psf, " encoding : 0 (SoX bug: should be 4 for 16 bit signed PCM)\n") ;
349 psf_log_printf (psf, " encoding : %d => %s\n", encoding, voc_encoding2str (encoding)) ;
352 psf_log_printf (psf, " fourbytes : %X\n", fourbytes) ;
354 psf->sf.channels = channels ;
356 psf->dataoffset = offset ;
357 psf->dataend = psf->filelength - 1 ;
359 if (size + 31 == psf->filelength + 1)
360 { /* Hack for reading files produced using
361 ** sf_command (SFC_UPDATE_HEADER_NOW).
363 psf_log_printf (psf, "Missing zero byte at end of file.\n") ;
364 size = psf->filelength - 30 ;
367 else if (size + 31 > psf->filelength)
368 { psf_log_printf (psf, "Seems to be a truncated file.\n") ;
369 size = psf->filelength - 31 ;
371 else if (size + 31 < psf->filelength)
372 psf_log_printf (psf, "Seems to be a multi-segment file (#3).\n") ;
376 psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ;
381 psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_16 ;
386 psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ALAW ;
391 psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ULAW ;
395 default : /* Unknown */
396 return SFE_UNKNOWN_FORMAT ;
403 } /* voc_read_header */
405 /*====================================================================================
409 voc_write_header (SF_PRIVATE *psf, int calc_length)
410 { sf_count_t current ;
411 int rate_const, subformat ;
413 current = psf_ftell (psf) ;
416 { psf->filelength = psf_get_filelen (psf) ;
418 psf->datalength = psf->filelength - psf->dataoffset ;
420 psf->datalength -= psf->filelength - psf->dataend ;
422 psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ;
425 subformat = psf->sf.format & SF_FORMAT_SUBMASK ;
426 /* Reset the current header length to zero. */
427 psf->header [0] = 0 ;
429 psf_fseek (psf, 0, SEEK_SET) ;
431 /* VOC marker and 0x1A byte. */
432 psf_binheader_writef (psf, "eb1", "Creative Voice File", 19, 0x1A) ;
434 /* Data offset, version and other. */
435 psf_binheader_writef (psf, "e222", 26, 0x0114, 0x111F) ;
437 /* Use same logic as SOX.
438 ** If the file is mono 8 bit data, use VOC_SOUND_DATA.
439 ** If the file is mono 16 bit data, use VOC_EXTENED.
440 ** Otherwise use VOC_EXTENED_2.
443 if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 1)
444 { /* samplerate = 1000000 / (256 - rate_const) ; */
445 rate_const = 256 - 1000000 / psf->sf.samplerate ;
447 /* First type marker, length, rate_const and compression */
448 psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ;
450 else if (subformat == SF_FORMAT_PCM_U8 && psf->sf.channels == 2)
451 { /* sample_rate = 128000000 / (65536 - rate_short) ; */
452 rate_const = 65536 - 128000000 / psf->sf.samplerate ;
454 /* First write the VOC_EXTENDED section
455 ** marker, length, rate_const and compression
457 psf_binheader_writef (psf, "e13211", VOC_EXTENDED, 4, rate_const, 0, 1) ;
459 /* samplerate = 1000000 / (256 - rate_const) ; */
460 rate_const = 256 - 1000000 / psf->sf.samplerate ;
462 /* Now write the VOC_SOUND_DATA section
463 ** marker, length, rate_const and compression
465 psf_binheader_writef (psf, "e1311", VOC_SOUND_DATA, (int) (psf->datalength + 1), rate_const, 0) ;
470 if (psf->sf.channels < 1 || psf->sf.channels > 2)
471 return SFE_CHANNEL_COUNT ;
474 { case SF_FORMAT_PCM_U8 :
476 length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
477 /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */
478 psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ;
481 case SF_FORMAT_PCM_16 :
483 length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
484 /* Marker, length, sample rate, bitwidth, stereo flag, encoding and fourt zero bytes. */
485 psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 16, psf->sf.channels, 4, 0) ;
488 case SF_FORMAT_ALAW :
490 length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
491 psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 6, 0) ;
494 case SF_FORMAT_ULAW :
496 length = psf->sf.frames * psf->sf.channels * psf->bytewidth + 12 ;
497 psf_binheader_writef (psf, "e1341124", VOC_EXTENDED_II, length, psf->sf.samplerate, 8, psf->sf.channels, 7, 0) ;
500 default : return SFE_UNIMPLEMENTED ;
504 psf_fwrite (psf->header, psf->headindex, 1, psf) ;
509 psf->dataoffset = psf->headindex ;
512 psf_fseek (psf, current, SEEK_SET) ;
515 } /* voc_write_header */
518 voc_close (SF_PRIVATE *psf)
520 if (psf->mode == SFM_WRITE || psf->mode == SFM_RDWR)
521 { /* Now we know for certain the length of the file we can re-write
522 ** correct values for the FORM, 8SVX and BODY chunks.
524 unsigned byte = VOC_TERMINATOR ;
527 psf_fseek (psf, 0, SEEK_END) ;
529 /* Write terminator */
530 psf_fwrite (&byte, 1, 1, psf) ;
532 voc_write_header (psf, SF_TRUE) ;
539 voc_encoding2str (int encoding)
542 { case 0 : return "8 bit unsigned PCM" ;
543 case 4 : return "16 bit signed PCM" ;
544 case 6 : return "A-law" ;
545 case 7 : return "u-law" ;
548 return "*** Unknown ***" ;
549 } /* voc_encoding2str */
551 /*====================================================================================
556 voc_multi_init (SF_PRIVATE *psf, VOC_DATA *pvoc)
560 if (pvoc->bitwidth == 8)
561 { psf->read_short = voc_multi_read_uc2s ;
562 psf->read_int = voc_multi_read_uc2i ;
563 psf->read_float = voc_multi_read_uc2f ;
564 psf->read_double = voc_multi_read_uc2d ;
568 if (pvoc->bitwidth == 16)
569 { psf->read_short = voc_multi_read_les2s ;
570 psf->read_int = voc_multi_read_les2i ;
571 psf->read_float = voc_multi_read_les2f ;
572 psf->read_double = voc_multi_read_les2d ;
576 psf_log_printf (psf, "Error : bitwith != 8 && bitwidth != 16.\n") ;
578 return SFE_UNIMPLEMENTED ;
579 } /* voc_multi_read_int */
581 /*------------------------------------------------------------------------------------
585 voc_multi_read_uc2s (SF_PRIVATE *psf, short *ptr, int len)
589 } /* voc_multi_read_uc2s */
592 voc_multi_read_les2s (SF_PRIVATE *psf, short *ptr, int len)
596 } /* voc_multi_read_les2s */
600 voc_multi_read_uc2i (SF_PRIVATE *psf, int *ptr, int len)
604 } /* voc_multi_read_uc2i */
607 voc_multi_read_les2i (SF_PRIVATE *psf, int *ptr, int len)
611 } /* voc_multi_read_les2i */
615 voc_multi_read_uc2f (SF_PRIVATE *psf, float *ptr, int len)
619 } /* voc_multi_read_uc2f */
622 voc_multi_read_les2f (SF_PRIVATE *psf, float *ptr, int len)
626 } /* voc_multi_read_les2f */
630 voc_multi_read_uc2d (SF_PRIVATE *psf, double *ptr, int len)
634 } /* voc_multi_read_uc2d */
637 voc_multi_read_les2d (SF_PRIVATE *psf, double *ptr, int len)
641 } /* voc_multi_read_les2d */
645 /*------------------------------------------------------------------------------------
647 Creative Voice (VOC) file format
648 --------------------------------
650 ~From: galt@dsd.es.com
652 (byte numbers are hex!)
655 Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
657 - ---------------------------------------------------------------
662 ------ ------------------------------------------
663 00-12 "Creative Voice File"
664 13 1A (eof to abort printing of file)
665 14-15 Offset of first datablock in .voc file (std 1A 00
667 16-17 Version number (minor,major) (VOC-HDR puts 0A 01)
668 18-19 1's Comp of Ver. # + 1234h (VOC-HDR puts 29 11)
670 - ---------------------------------------------------------------
675 Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes)
676 NOTE: Terminator Block is an exception -- it has only the TYPE byte.
678 TYPE Description Size (3-byte int) Info
679 ---- ----------- ----------------- -----------------------
680 00 Terminator (NONE) (NONE)
681 01 Sound data 2+length of data *
682 02 Sound continue length of data Voice Data
684 04 Marker 2 Marker# (2 bytes)
685 05 ASCII length of string null terminated string
686 06 Repeat 2 Count# (2 bytes)
687 07 End repeat 0 (NONE)
691 ---------------------
696 **Silence Info Format:
697 ----------------------------
698 00-01 Length of silence - 1
702 ***Extended Info Format:
703 ---------------------
704 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate)
705 Stereo: 65536 - (25600000/(2*sample_rate))
711 Marker# -- Driver keeps the most recent marker in a status byte
712 Count# -- Number of repetitions + 1
713 Count# may be 1 to FFFE for 0 - FFFD repetitions
714 or FFFF for endless repetitions
715 Sample Rate -- SR byte = 256-(1000000/sample_rate)
716 Length of silence -- in units of sampling cycle
717 Compression Type -- of voice data
722 Multi DAC = 3+(# of channels) [interesting--
723 this isn't in the developer's manual]
726 ---------------------------------------------------------------------------------
727 Addendum submitted by Votis Kokavessis:
729 After some experimenting with .VOC files I found out that there is a Data Block
730 Type 9, which is not covered in the VOC.TXT file. Here is what I was able to discover
731 about this block type:
735 SIZE: 12 + length of data
736 INFO: 12 (twelve) bytes
740 Bytes 0-1: (Word) Sample Rate (e.g. 44100)
741 Bytes 2-3: zero (could be that bytes 0-3 are a DWord for Sample Rate)
742 Byte 4: Sample Size in bits (e.g. 16)
743 Byte 5: Number of channels (e.g. 1 for mono, 2 for stereo)
744 Byte 6: Unknown (equal to 4 in all files I examined)
748 -------------------------------------------------------------------------------------*/
750 /*=====================================================================================
751 **=====================================================================================
752 **=====================================================================================
753 **=====================================================================================
756 /*------------------------------------------------------------------------
757 The following is taken from the Audio File Formats FAQ dated 2-Jan-1995
758 and submitted by Guido van Rossum <guido@cwi.nl>.
759 --------------------------------------------------------------------------
760 Creative Voice (VOC) file format
761 --------------------------------
763 From: galt@dsd.es.com
765 (byte numbers are hex!)
768 Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block]
770 - ---------------------------------------------------------------
775 ------ ------------------------------------------
776 00-12 "Creative Voice File"
777 13 1A (eof to abort printing of file)
778 14-15 Offset of first datablock in .voc file (std 1A 00
780 16-17 Version number (minor,major) (VOC-HDR puts 0A 01)
781 18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11)
783 - ---------------------------------------------------------------
788 Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes)
789 NOTE: Terminator Block is an exception -- it has only the TYPE byte.
791 TYPE Description Size (3-byte int) Info
792 ---- ----------- ----------------- -----------------------
793 00 Terminator (NONE) (NONE)
794 01 Sound data 2+length of data *
795 02 Sound continue length of data Voice Data
797 04 Marker 2 Marker# (2 bytes)
798 05 ASCII length of string null terminated string
799 06 Repeat 2 Count# (2 bytes)
800 07 End repeat 0 (NONE)
803 *Sound Info Format: **Silence Info Format:
804 --------------------- ----------------------------
805 00 Sample Rate 00-01 Length of silence - 1
806 01 Compression Type 02 Sample Rate
809 ***Extended Info Format:
810 ---------------------
811 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate)
812 Stereo: 65536 - (25600000/(2*sample_rate))
818 Marker# -- Driver keeps the most recent marker in a status byte
819 Count# -- Number of repetitions + 1
820 Count# may be 1 to FFFE for 0 - FFFD repetitions
821 or FFFF for endless repetitions
822 Sample Rate -- SR byte = 256-(1000000/sample_rate)
823 Length of silence -- in units of sampling cycle
824 Compression Type -- of voice data
829 Multi DAC = 3+(# of channels) [interesting--
830 this isn't in the developer's manual]
832 Detailed description of new data blocks (VOC files version 1.20 and above):
834 (Source is fax from Barry Boone at Creative Labs, 405/742-6622)
836 BLOCK 8 - digitized sound attribute extension, must preceed block 1.
837 Used to define stereo, 8 bit audio
838 BYTE bBlockID; // = 8
839 BYTE nBlockLen[3]; // 3 byte length
840 WORD wTimeConstant; // time constant = same as block 1
841 BYTE bPackMethod; // same as in block 1
842 BYTE bVoiceMode; // 0-mono, 1-stereo
844 Data is stored left, right
846 BLOCK 9 - data block that supersedes blocks 1 and 8.
847 Used for stereo, 16 bit.
849 BYTE bBlockID; // = 9
850 BYTE nBlockLen[3]; // length 12 plus length of sound
851 DWORD dwSamplesPerSec; // samples per second, not time const.
852 BYTE bBitsPerSample; // e.g., 8 or 16
853 BYTE bChannels; // 1 for mono, 2 for stereo
854 WORD wFormat; // see below
855 BYTE reserved[4]; // pad to make block w/o data
856 // have a size of 16 bytes
858 Valid values of wFormat are:
860 0x0000 8-bit unsigned PCM
861 0x0001 Creative 8-bit to 4-bit ADPCM
862 0x0002 Creative 8-bit to 3-bit ADPCM
863 0x0003 Creative 8-bit to 2-bit ADPCM
864 0x0004 16-bit signed PCM
867 0x02000 Creative 16-bit to 4-bit ADPCM
869 Data is stored left, right
871 ------------------------------------------------------------------------*/
873 ** Do not edit or modify anything in this comment block.
874 ** The arch-tag line is a file identity tag for the GNU Arch
875 ** revision control system.
877 ** arch-tag: 40a50167-a81c-463a-9e1d-3282ff84e09d