/* libSoX Sound Blaster VOC handler sources. * Copyright 1991 Lance Norskog And Sundry Contributors * * This source code is freely redistributable and may be used for * any purpose. This copyright notice must be maintained. * Lance Norskog And Sundry Contributors are not responsible for * the consequences of using this software. * * September 8, 1993 * Copyright 1993 T. Allen Grider - for changes to support block type 9 * and word sized samples. Same caveats and disclaimer as above. * * February 22, 1996 * by Chris Bagwell (cbagwell@sprynet.com) * Added support for block type 8 (extended) which allows for 8-bit stereo * files. Added support for saving stereo files and 16-bit files. * Added VOC format info from audio format FAQ so I don't have to keep * looking around for it. * * February 5, 2001 * For sox-12-17 by Annonymous (see notes ANN) * Added comments and notes for each procedure. * Fixed so this now works with pipes, input does not have to * be seekable anymore (in startread() ) * Added support for uLAW and aLaw (aLaw not tested). * Fixed support of multi-part VOC files, and files with * block 9 but no audio in the block.... * The following need to be tested: 16-bit, 2 channel, and aLaw. * * December 10, 2001 * For sox-12-17-3 by Annonymous (see notes ANN) * Patch for sox-12-17 merged with sox-12-17-3-pre3 code. * */ /*------------------------------------------------------------------------The following is taken from the Audio File Formats FAQ dated 2-Jan-1995and submitted by Guido van Rossum <guido@cwi.nl>.--------------------------------------------------------------------------Creative Voice (VOC) file format-------------------------------- From: galt@dsd.es.com (byte numbers are hex!) HEADER (bytes 00-19) Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block] - --------------------------------------------------------------- HEADER:------- byte # Description ------ ------------------------------------------ 00-12 "Creative Voice File" 13 1A (eof to abort printing of file) 14-15 Offset of first datablock in .voc file (std 1A 00 in Intel Notation) 16-17 Version number (minor,major) (VOC-HDR puts 0A 01) 18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11) - --------------------------------------------------------------- DATA BLOCK:----------- Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes) NOTE: Terminator Block is an exception -- it has only the TYPE byte. TYPE Description Size (3-byte int) Info ---- ----------- ----------------- ----------------------- 00 Terminator (NONE) (NONE) 01 Sound data 2+length of data * 02 Sound continue length of data Voice Data 03 Silence 3 ** 04 Marker 2 Marker# (2 bytes) 05 ASCII length of string null terminated string 06 Repeat 2 Count# (2 bytes) 07 End repeat 0 (NONE) 08 Extended 4 *** 09 New Header 16 see below *Sound Info Format: **Silence Info Format: --------------------- ---------------------------- 00 Sample Rate 00-01 Length of silence - 1 01 Compression Type 02 Sample Rate 02+ Voice Data ***Extended Info Format: --------------------- 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate) Stereo: 65536 - (25600000/(2*sample_rate)) 02 Pack 03 Mode: 0 = mono 1 = stereo Marker# -- Driver keeps the most recent marker in a status byte Count# -- Number of repetitions + 1 Count# may be 1 to FFFE for 0 - FFFD repetitions or FFFF for endless repetitions Sample Rate -- SR byte = 256-(1000000/sample_rate) Length of silence -- in units of sampling cycle Compression Type -- of voice data 8-bits = 0 4-bits = 1 2.6-bits = 2 2-bits = 3 Multi DAC = 3+(# of channels) [interesting-- this isn't in the developer's manual] Detailed description of new data blocks (VOC files version 1.20 and above): (Source is fax from Barry Boone at Creative Labs, 405/742-6622) BLOCK 8 - digitized sound attribute extension, must preceed block 1. Used to define stereo, 8 bit audio BYTE bBlockID; // = 8 BYTE nBlockLen[3]; // 3 byte length WORD wTimeConstant; // time constant = same as block 1 BYTE bPackMethod; // same as in block 1 BYTE bVoiceMode; // 0-mono, 1-stereo Data is stored left, right BLOCK 9 - data block that supersedes blocks 1 and 8. Used for stereo, 16 bit (and uLaw, aLaw). BYTE bBlockID; // = 9 BYTE nBlockLen[3]; // length 12 plus length of sound DWORD dwSamplesPerSec; // samples per second, not time const. BYTE bBitsPerSample; // e.g., 8 or 16 BYTE bChannels; // 1 for mono, 2 for stereo WORD wFormat; // see below BYTE reserved[4]; // pad to make block w/o data // have a size of 16 bytes Valid values of wFormat are: 0x0000 8-bit unsigned PCM 0x0001 Creative 8-bit to 4-bit ADPCM 0x0002 Creative 8-bit to 3-bit ADPCM 0x0003 Creative 8-bit to 2-bit ADPCM 0x0004 16-bit signed PCM 0x0006 CCITT a-Law 0x0007 CCITT u-Law 0x02000 Creative 16-bit to 4-bit ADPCM Data is stored left, right ANN: Multi-byte quantities are in Intel byte order (Little Endian). ------------------------------------------------------------------------*/ #include "sox_i.h"#include "g711.h"#include "adpcms.h"#include <assert.h>#include <string.h> /* Private data for VOC file */typedef struct { long block_remaining; /* bytes remaining in current block */ long rate; /* rate code (byte) of this chunk */ int silent; /* sound or silence? */ long srate; /* rate code (byte) of silence */ size_t blockseek; /* start of current output block */ long samples; /* number of samples output */ int format; /* VOC audio format */ int size; /* word length of data */ int channels; /* number of sound channels */ long total_size; /* total size of all audio in file */ int extended; /* Has an extended block been read? */ adpcm_t adpcm;} priv_t; #define VOC_TERM 0#define VOC_DATA 1#define VOC_CONT 2#define VOC_SILENCE 3#define VOC_MARKER 4#define VOC_TEXT 5#define VOC_LOOP 6#define VOC_LOOPEND 7#define VOC_EXTENDED 8#define VOC_DATA_16 9 /* ANN: Format encoding types */#define VOC_FMT_LIN8U 0 /* 8 bit unsigned linear PCM */#define VOC_FMT_CRLADPCM4 1 /* Creative 8-bit to 4-bit ADPCM */#define VOC_FMT_CRLADPCM3 2 /* Creative 8-bit to 3-bit ADPCM */#define VOC_FMT_CRLADPCM2 3 /* Creative 8-bit to 2-bit ADPCM */#define VOC_FMT_LIN16 4 /* 16-bit signed PCM */#define VOC_FMT_ALAW 6 /* CCITT a-Law 8-bit PCM */#define VOC_FMT_MU255 7 /* CCITT u-Law 8-bit PCM */#define VOC_FMT_CRLADPCM4A 0x200 /* Creative 16-bit to 4-bit ADPCM */ /* Prototypes for internal functions */static int getblock(sox_format_t *);static void blockstart(sox_format_t *); /* Conversion macros (from raw.c) */#define SOX_ALAW_BYTE_TO_SAMPLE(d) ((sox_sample_t)(sox_alaw2linear16(d)) << 16)#define SOX_ULAW_BYTE_TO_SAMPLE(d) ((sox_sample_t)(sox_ulaw2linear16(d)) << 16) /* public VOC functions for SOX */ /*----------------------------------------------------------------- * startread() -- start reading a VOC file *-----------------------------------------------------------------*/static int startread(sox_format_t * ft){ char header[20]; priv_t * v = (priv_t *) ft->priv; unsigned short sbseek; int rc; int ii; /* for getting rid of lseek */ unsigned char uc; if (lsx_readbuf(ft, header, (size_t)20) != 20) { lsx_fail_errno(ft, SOX_EHDR, "unexpected EOF in VOC header"); return (SOX_EOF); } if (strncmp(header, "Creative Voice File\032", (size_t)19)) { lsx_fail_errno(ft, SOX_EHDR, "VOC file header incorrect"); return (SOX_EOF); } /* read the offset to data, from start of file */ /* after this read we have read 20 bytes of header + 2 */ lsx_readw(ft, &sbseek); /* ANN: read to skip the header, instead of lseek */ /* this should allow use with pipes.... */ for (ii = 22; ii < sbseek; ii++) lsx_readb(ft, &uc); v->rate = -1; v->format = -1; v->channels = -1; v->block_remaining = 0; v->total_size = 0; /* ANN added */ v->extended = 0; /* read until we get the format information.... */ rc = getblock(ft); if (rc) return rc; /* get rate of data */ if (v->rate == -1) { lsx_fail_errno(ft, SOX_EOF, "Input .voc file had no sound!"); return (SOX_EOF); } /* setup word length of data */ /* ANN: Check VOC format and map to the proper libSoX format value */ switch (v->format) { case VOC_FMT_LIN8U: /* 0 8 bit unsigned linear PCM */ ft->encoding.encoding = SOX_ENCODING_UNSIGNED; v->size = 8; break; case VOC_FMT_CRLADPCM4: /* 1 Creative 8-bit to 4-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM; v->size = 4; break; case VOC_FMT_CRLADPCM3: /* 2 Creative 8-bit to 3-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM; v->size = 3; break; case VOC_FMT_CRLADPCM2: /* 3 Creative 8-bit to 2-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM; v->size = 2; break; case VOC_FMT_LIN16: /* 4 16-bit signed PCM */ ft->encoding.encoding = SOX_ENCODING_SIGN2; v->size = 16; break; case VOC_FMT_ALAW: /* 6 CCITT a-Law 8-bit PCM */ ft->encoding.encoding = SOX_ENCODING_ALAW; v->size = 8; break; case VOC_FMT_MU255: /* 7 CCITT u-Law 8-bit PCM */ ft->encoding.encoding = SOX_ENCODING_ULAW; v->size = 8; break; case VOC_FMT_CRLADPCM4A: /*0x200 Creative 16-bit to 4-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM16; v->size = 4; break; default: lsx_fail("Unknown VOC format %d", v->format); break; } ft->encoding.bits_per_sample = v->size; /* setup number of channels */ if (ft->signal.channels == 0) ft->signal.channels = v->channels; return (SOX_SUCCESS);} /*----------------------------------------------------------------- * read() -- read data from a VOC file * ANN: Major changes here to support multi-part files and files * that do not have audio in block 9's. *-----------------------------------------------------------------*/static size_t read_samples(sox_format_t * ft, sox_sample_t * buf, size_t len){ priv_t * v = (priv_t *) ft->priv; size_t done = 0; int rc = 0; int16_t sw; unsigned char uc; if (v->block_remaining == 0) { /* handle getting another cont. buffer */ rc = getblock(ft); if (rc) return 0; } if (v->block_remaining == 0) /* if no more data, return 0, i.e., done */ return 0; if (v->silent) { for (; v->block_remaining && (done < len); v->block_remaining--, done++) *buf++ = 0; /* Fill in silence */ } else { /* not silence; read len samples of audio from the file */ size_t per = max(1, 9 / v->size); for (; (done + per <= len); done += per) { if (v->block_remaining == 0) { /* IF no more in this block, get another */ while (v->block_remaining == 0) { /* until have either EOF or a block with data */ rc = getblock(ft); if (rc) break; } if (rc) /* IF EOF, break out, no more data, next will return 0 */ break; } /* Read the data in the file */ if (v->size <= 4) { if (!v->adpcm.setup.sign) { SOX_SAMPLE_LOCALS; if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } if(uc == 0) { lsx_fail_errno(ft, EINVAL, "invalid rate value"); v->block_remaining = 0; return done; } *buf = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,); lsx_adpcm_init(&v->adpcm, 6 - v->size, SOX_SAMPLE_TO_SIGNED_16BIT(*buf, ft->clips)); ++buf; --v->block_remaining; ++done; } if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } switch (v->size) { case 2: if (v->format == VOC_FMT_CRLADPCM2) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 6, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),); } break; case 3: if (v->format == VOC_FMT_CRLADPCM3) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 5, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),); *buf++ = /* A bit from nowhere! */ SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u << 1, &v->adpcm),); } break; case 4: if (v->format == VOC_FMT_CRLADPCM4) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),); } break; } } else switch (v->size) { case 8: if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } if (v->format == VOC_FMT_MU255) { *buf++ = SOX_ULAW_BYTE_TO_SAMPLE(uc); } else if (v->format == VOC_FMT_ALAW) { *buf++ = SOX_ALAW_BYTE_TO_SAMPLE(uc); } else { *buf++ = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,); } break; case 16: lsx_readsw(ft, &sw); if (lsx_eof(ft)) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(sw,); v->block_remaining--; /* Processed 2 bytes so update */ break; } /* decrement count of processed bytes */ v->block_remaining--; } } v->total_size += done; return done;} /* When saving samples in VOC format the following outline is followed: * If an 8-bit mono sample then use a VOC_DATA header. * If an 8-bit stereo sample then use a VOC_EXTENDED header followed * by a VOC_DATA header. * If a 16-bit sample (either stereo or mono) then save with a * VOC_DATA_16 header. * * ANN: Not supported: uLaw and aLaw output VOC files.... * * This approach will cause the output to be an its most basic format * which will work with the oldest software (eg. an 8-bit mono sample * will be able to be played with a really old SB VOC player.) */static int startwrite(sox_format_t * ft){ priv_t * v = (priv_t *) ft->priv; if (!ft->seekable) { lsx_fail_errno(ft, SOX_EOF, "Output .voc file must be a file, not a pipe"); return (SOX_EOF); } v->samples = 0; /* File format name and a ^Z (aborts printing under DOS) */ lsx_writes(ft, "Creative Voice File\032"); lsx_writew(ft, 26); /* size of header */ lsx_writew(ft, 0x10a); /* major/minor version number */ lsx_writew(ft, 0x1129); /* checksum of version number */ return (SOX_SUCCESS);} /*----------------------------------------------------------------- * write() -- write a VOC file *-----------------------------------------------------------------*/static size_t write_samples(sox_format_t * ft, const sox_sample_t * buf, size_t len){ priv_t * v = (priv_t *) ft->priv; unsigned char uc; int16_t sw; size_t done = 0; if (len && v->samples == 0) { /* No silence packing yet. */ v->silent = 0; blockstart(ft); } v->samples += len; while (done < len) { SOX_SAMPLE_LOCALS; if (ft->encoding.bits_per_sample == 8) { uc = SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips);Lines 1–500 of 820. Load more
/* libSoX Sound Blaster VOC handler sources. * Copyright 1991 Lance Norskog And Sundry Contributors * * This source code is freely redistributable and may be used for * any purpose. This copyright notice must be maintained. * Lance Norskog And Sundry Contributors are not responsible for * the consequences of using this software. * * September 8, 1993 * Copyright 1993 T. Allen Grider - for changes to support block type 9 * and word sized samples. Same caveats and disclaimer as above. * * February 22, 1996 * by Chris Bagwell (cbagwell@sprynet.com) * Added support for block type 8 (extended) which allows for 8-bit stereo * files. Added support for saving stereo files and 16-bit files. * Added VOC format info from audio format FAQ so I don't have to keep * looking around for it. * * February 5, 2001 * For sox-12-17 by Annonymous (see notes ANN) * Added comments and notes for each procedure. * Fixed so this now works with pipes, input does not have to * be seekable anymore (in startread() ) * Added support for uLAW and aLaw (aLaw not tested). * Fixed support of multi-part VOC files, and files with * block 9 but no audio in the block.... * The following need to be tested: 16-bit, 2 channel, and aLaw. * * December 10, 2001 * For sox-12-17-3 by Annonymous (see notes ANN) * Patch for sox-12-17 merged with sox-12-17-3-pre3 code. * */ /*------------------------------------------------------------------------ The following is taken from the Audio File Formats FAQ dated 2-Jan-1995 and submitted by Guido van Rossum <guido@cwi.nl>. -------------------------------------------------------------------------- Creative Voice (VOC) file format -------------------------------- From: galt@dsd.es.com (byte numbers are hex!) HEADER (bytes 00-19) Series of DATA BLOCKS (bytes 1A+) [Must end w/ Terminator Block] - --------------------------------------------------------------- HEADER: ------- byte # Description ------ ------------------------------------------ 00-12 "Creative Voice File" 13 1A (eof to abort printing of file) 14-15 Offset of first datablock in .voc file (std 1A 00 in Intel Notation) 16-17 Version number (minor,major) (VOC-HDR puts 0A 01) 18-19 2's Comp of Ver. # + 1234h (VOC-HDR puts 29 11) - --------------------------------------------------------------- DATA BLOCK: ----------- Data Block: TYPE(1-byte), SIZE(3-bytes), INFO(0+ bytes) NOTE: Terminator Block is an exception -- it has only the TYPE byte. TYPE Description Size (3-byte int) Info ---- ----------- ----------------- ----------------------- 00 Terminator (NONE) (NONE) 01 Sound data 2+length of data * 02 Sound continue length of data Voice Data 03 Silence 3 ** 04 Marker 2 Marker# (2 bytes) 05 ASCII length of string null terminated string 06 Repeat 2 Count# (2 bytes) 07 End repeat 0 (NONE) 08 Extended 4 *** 09 New Header 16 see below *Sound Info Format: **Silence Info Format: --------------------- ---------------------------- 00 Sample Rate 00-01 Length of silence - 1 01 Compression Type 02 Sample Rate 02+ Voice Data ***Extended Info Format: --------------------- 00-01 Time Constant: Mono: 65536 - (256000000/sample_rate) Stereo: 65536 - (25600000/(2*sample_rate)) 02 Pack 03 Mode: 0 = mono 1 = stereo Marker# -- Driver keeps the most recent marker in a status byte Count# -- Number of repetitions + 1 Count# may be 1 to FFFE for 0 - FFFD repetitions or FFFF for endless repetitions Sample Rate -- SR byte = 256-(1000000/sample_rate) Length of silence -- in units of sampling cycle Compression Type -- of voice data 8-bits = 0 4-bits = 1 2.6-bits = 2 2-bits = 3 Multi DAC = 3+(# of channels) [interesting-- this isn't in the developer's manual] Detailed description of new data blocks (VOC files version 1.20 and above): (Source is fax from Barry Boone at Creative Labs, 405/742-6622) BLOCK 8 - digitized sound attribute extension, must preceed block 1. Used to define stereo, 8 bit audio BYTE bBlockID; // = 8 BYTE nBlockLen[3]; // 3 byte length WORD wTimeConstant; // time constant = same as block 1 BYTE bPackMethod; // same as in block 1 BYTE bVoiceMode; // 0-mono, 1-stereo Data is stored left, right BLOCK 9 - data block that supersedes blocks 1 and 8. Used for stereo, 16 bit (and uLaw, aLaw). BYTE bBlockID; // = 9 BYTE nBlockLen[3]; // length 12 plus length of sound DWORD dwSamplesPerSec; // samples per second, not time const. BYTE bBitsPerSample; // e.g., 8 or 16 BYTE bChannels; // 1 for mono, 2 for stereo WORD wFormat; // see below BYTE reserved[4]; // pad to make block w/o data // have a size of 16 bytes Valid values of wFormat are: 0x0000 8-bit unsigned PCM 0x0001 Creative 8-bit to 4-bit ADPCM 0x0002 Creative 8-bit to 3-bit ADPCM 0x0003 Creative 8-bit to 2-bit ADPCM 0x0004 16-bit signed PCM 0x0006 CCITT a-Law 0x0007 CCITT u-Law 0x02000 Creative 16-bit to 4-bit ADPCM Data is stored left, right ANN: Multi-byte quantities are in Intel byte order (Little Endian). ------------------------------------------------------------------------*/ #include "sox_i.h" #include "g711.h" #include "adpcms.h" #include <assert.h> #include <string.h> /* Private data for VOC file */ typedef struct { long block_remaining; /* bytes remaining in current block */ long rate; /* rate code (byte) of this chunk */ int silent; /* sound or silence? */ long srate; /* rate code (byte) of silence */ size_t blockseek; /* start of current output block */ long samples; /* number of samples output */ int format; /* VOC audio format */ int size; /* word length of data */ int channels; /* number of sound channels */ long total_size; /* total size of all audio in file */ int extended; /* Has an extended block been read? */ adpcm_t adpcm; } priv_t; #define VOC_TERM 0 #define VOC_DATA 1 #define VOC_CONT 2 #define VOC_SILENCE 3 #define VOC_MARKER 4 #define VOC_TEXT 5 #define VOC_LOOP 6 #define VOC_LOOPEND 7 #define VOC_EXTENDED 8 #define VOC_DATA_16 9 /* ANN: Format encoding types */ #define VOC_FMT_LIN8U 0 /* 8 bit unsigned linear PCM */ #define VOC_FMT_CRLADPCM4 1 /* Creative 8-bit to 4-bit ADPCM */ #define VOC_FMT_CRLADPCM3 2 /* Creative 8-bit to 3-bit ADPCM */ #define VOC_FMT_CRLADPCM2 3 /* Creative 8-bit to 2-bit ADPCM */ #define VOC_FMT_LIN16 4 /* 16-bit signed PCM */ #define VOC_FMT_ALAW 6 /* CCITT a-Law 8-bit PCM */ #define VOC_FMT_MU255 7 /* CCITT u-Law 8-bit PCM */ #define VOC_FMT_CRLADPCM4A 0x200 /* Creative 16-bit to 4-bit ADPCM */ /* Prototypes for internal functions */ static int getblock(sox_format_t *); static void blockstart(sox_format_t *); /* Conversion macros (from raw.c) */ #define SOX_ALAW_BYTE_TO_SAMPLE(d) ((sox_sample_t)(sox_alaw2linear16(d)) << 16) #define SOX_ULAW_BYTE_TO_SAMPLE(d) ((sox_sample_t)(sox_ulaw2linear16(d)) << 16) /* public VOC functions for SOX */ /*----------------------------------------------------------------- * startread() -- start reading a VOC file *-----------------------------------------------------------------*/ static int startread(sox_format_t * ft) { char header[20]; priv_t * v = (priv_t *) ft->priv; unsigned short sbseek; int rc; int ii; /* for getting rid of lseek */ unsigned char uc; if (lsx_readbuf(ft, header, (size_t)20) != 20) { lsx_fail_errno(ft, SOX_EHDR, "unexpected EOF in VOC header"); return (SOX_EOF); } if (strncmp(header, "Creative Voice File\032", (size_t)19)) { lsx_fail_errno(ft, SOX_EHDR, "VOC file header incorrect"); return (SOX_EOF); } /* read the offset to data, from start of file */ /* after this read we have read 20 bytes of header + 2 */ lsx_readw(ft, &sbseek); /* ANN: read to skip the header, instead of lseek */ /* this should allow use with pipes.... */ for (ii = 22; ii < sbseek; ii++) lsx_readb(ft, &uc); v->rate = -1; v->format = -1; v->channels = -1; v->block_remaining = 0; v->total_size = 0; /* ANN added */ v->extended = 0; /* read until we get the format information.... */ rc = getblock(ft); if (rc) return rc; /* get rate of data */ if (v->rate == -1) { lsx_fail_errno(ft, SOX_EOF, "Input .voc file had no sound!"); return (SOX_EOF); } /* setup word length of data */ /* ANN: Check VOC format and map to the proper libSoX format value */ switch (v->format) { case VOC_FMT_LIN8U: /* 0 8 bit unsigned linear PCM */ ft->encoding.encoding = SOX_ENCODING_UNSIGNED; v->size = 8; break; case VOC_FMT_CRLADPCM4: /* 1 Creative 8-bit to 4-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM; v->size = 4; break; case VOC_FMT_CRLADPCM3: /* 2 Creative 8-bit to 3-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM; v->size = 3; break; case VOC_FMT_CRLADPCM2: /* 3 Creative 8-bit to 2-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM; v->size = 2; break; case VOC_FMT_LIN16: /* 4 16-bit signed PCM */ ft->encoding.encoding = SOX_ENCODING_SIGN2; v->size = 16; break; case VOC_FMT_ALAW: /* 6 CCITT a-Law 8-bit PCM */ ft->encoding.encoding = SOX_ENCODING_ALAW; v->size = 8; break; case VOC_FMT_MU255: /* 7 CCITT u-Law 8-bit PCM */ ft->encoding.encoding = SOX_ENCODING_ULAW; v->size = 8; break; case VOC_FMT_CRLADPCM4A: /*0x200 Creative 16-bit to 4-bit ADPCM */ ft->encoding.encoding = SOX_ENCODING_CL_ADPCM16; v->size = 4; break; default: lsx_fail("Unknown VOC format %d", v->format); break; } ft->encoding.bits_per_sample = v->size; /* setup number of channels */ if (ft->signal.channels == 0) ft->signal.channels = v->channels; return (SOX_SUCCESS); } /*----------------------------------------------------------------- * read() -- read data from a VOC file * ANN: Major changes here to support multi-part files and files * that do not have audio in block 9's. *-----------------------------------------------------------------*/ static size_t read_samples(sox_format_t * ft, sox_sample_t * buf, size_t len) { priv_t * v = (priv_t *) ft->priv; size_t done = 0; int rc = 0; int16_t sw; unsigned char uc; if (v->block_remaining == 0) { /* handle getting another cont. buffer */ rc = getblock(ft); if (rc) return 0; } if (v->block_remaining == 0) /* if no more data, return 0, i.e., done */ return 0; if (v->silent) { for (; v->block_remaining && (done < len); v->block_remaining--, done++) *buf++ = 0; /* Fill in silence */ } else { /* not silence; read len samples of audio from the file */ size_t per = max(1, 9 / v->size); for (; (done + per <= len); done += per) { if (v->block_remaining == 0) { /* IF no more in this block, get another */ while (v->block_remaining == 0) { /* until have either EOF or a block with data */ rc = getblock(ft); if (rc) break; } if (rc) /* IF EOF, break out, no more data, next will return 0 */ break; } /* Read the data in the file */ if (v->size <= 4) { if (!v->adpcm.setup.sign) { SOX_SAMPLE_LOCALS; if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } if(uc == 0) { lsx_fail_errno(ft, EINVAL, "invalid rate value"); v->block_remaining = 0; return done; } *buf = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,); lsx_adpcm_init(&v->adpcm, 6 - v->size, SOX_SAMPLE_TO_SIGNED_16BIT(*buf, ft->clips)); ++buf; --v->block_remaining; ++done; } if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } switch (v->size) { case 2: if (v->format == VOC_FMT_CRLADPCM2) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 6, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),); } break; case 3: if (v->format == VOC_FMT_CRLADPCM3) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 5, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 2, &v->adpcm),); *buf++ = /* A bit from nowhere! */ SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u << 1, &v->adpcm),); } break; case 4: if (v->format == VOC_FMT_CRLADPCM4) { int u = uc; *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u >> 4, &v->adpcm),); *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(lsx_adpcm_decode (u , &v->adpcm),); } break; } } else switch (v->size) { case 8: if (lsx_readb(ft, &uc) == SOX_EOF) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } if (v->format == VOC_FMT_MU255) { *buf++ = SOX_ULAW_BYTE_TO_SAMPLE(uc); } else if (v->format == VOC_FMT_ALAW) { *buf++ = SOX_ALAW_BYTE_TO_SAMPLE(uc); } else { *buf++ = SOX_UNSIGNED_8BIT_TO_SAMPLE(uc,); } break; case 16: lsx_readsw(ft, &sw); if (lsx_eof(ft)) { lsx_warn("VOC input: short file"); v->block_remaining = 0; return done; } *buf++ = SOX_SIGNED_16BIT_TO_SAMPLE(sw,); v->block_remaining--; /* Processed 2 bytes so update */ break; } /* decrement count of processed bytes */ v->block_remaining--; } } v->total_size += done; return done; } /* When saving samples in VOC format the following outline is followed: * If an 8-bit mono sample then use a VOC_DATA header. * If an 8-bit stereo sample then use a VOC_EXTENDED header followed * by a VOC_DATA header. * If a 16-bit sample (either stereo or mono) then save with a * VOC_DATA_16 header. * * ANN: Not supported: uLaw and aLaw output VOC files.... * * This approach will cause the output to be an its most basic format * which will work with the oldest software (eg. an 8-bit mono sample * will be able to be played with a really old SB VOC player.) */ static int startwrite(sox_format_t * ft) { priv_t * v = (priv_t *) ft->priv; if (!ft->seekable) { lsx_fail_errno(ft, SOX_EOF, "Output .voc file must be a file, not a pipe"); return (SOX_EOF); } v->samples = 0; /* File format name and a ^Z (aborts printing under DOS) */ lsx_writes(ft, "Creative Voice File\032"); lsx_writew(ft, 26); /* size of header */ lsx_writew(ft, 0x10a); /* major/minor version number */ lsx_writew(ft, 0x1129); /* checksum of version number */ return (SOX_SUCCESS); } /*----------------------------------------------------------------- * write() -- write a VOC file *-----------------------------------------------------------------*/ static size_t write_samples(sox_format_t * ft, const sox_sample_t * buf, size_t len) { priv_t * v = (priv_t *) ft->priv; unsigned char uc; int16_t sw; size_t done = 0; if (len && v->samples == 0) { /* No silence packing yet. */ v->silent = 0; blockstart(ft); } v->samples += len; while (done < len) { SOX_SAMPLE_LOCALS; if (ft->encoding.bits_per_sample == 8) { uc = SOX_SAMPLE_TO_UNSIGNED_8BIT(*buf++, ft->clips);