static int caf_read_chanmap (SF_PRIVATE * psf, sf_count_t chunk_size) { const AIFF_CAF_CHANNEL_MAP * map_info ; unsigned channel_bitmap, channel_decriptions, bytesread ; int layout_tag ; bytesread = psf_binheader_readf (psf, "E444", &layout_tag, &channel_bitmap, &channel_decriptions) ; map_info = aiff_caf_of_channel_layout_tag (layout_tag) ; psf_log_printf (psf, " Tag : %x\n", layout_tag) ; if (map_info) psf_log_printf (psf, " Layout : %s\n", map_info->name) ; if (bytesread < chunk_size) psf_binheader_readf (psf, "j", chunk_size - bytesread) ; if (map_info && map_info->channel_map != NULL) { size_t chanmap_size = SF_MIN (psf->sf.channels, layout_tag & 0xff) * sizeof (psf->channel_map [0]) ; free (psf->channel_map) ; if ((psf->channel_map = malloc (chanmap_size)) == NULL) return SFE_MALLOC_FAILED ; memcpy (psf->channel_map, map_info->channel_map, chanmap_size) ; } ; return 0 ; } /* caf_read_chanmap */
static int pvf_read_header (SF_PRIVATE *psf) { char buffer [32] ; int marker, channels, samplerate, bitwidth ; psf_binheader_readf (psf, "pmj", 0, &marker, 1) ; psf_log_printf (psf, "%M\n", marker) ; if (marker != PVF1_MARKER) return SFE_PVF_NO_PVF1 ; /* Grab characters up until a newline which is replaced by an EOS. */ psf_binheader_readf (psf, "G", buffer, sizeof (buffer)) ; if (sscanf (buffer, "%d %d %d", &channels, &samplerate, &bitwidth) != 3) return SFE_PVF_BAD_HEADER ; psf_log_printf (psf, " Channels : %d\n Sample rate : %d\n Bit width : %d\n", channels, samplerate, bitwidth) ; psf->sf.channels = channels ; psf->sf.samplerate = samplerate ; switch (bitwidth) { case 8 : psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; break ; case 16 : psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; case 32 : psf->sf.format = SF_FORMAT_PVF | SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; break ; default : return SFE_PVF_BAD_BITWIDTH ; } ; psf->dataoffset = psf_ftell (psf) ; psf_log_printf (psf, " Data Offset : %D\n", psf->dataoffset) ; psf->endian = SF_ENDIAN_BIG ; psf->datalength = psf->filelength - psf->dataoffset ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* pvf_read_header */
static int wve_read_header (SF_PRIVATE *psf) { int marker ; unsigned short version, padding, repeats, trash ; unsigned datalength ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pm", 0, &marker) ; if (marker != ALAW_MARKER) { psf_log_printf (psf, "Could not find '%M'\n", ALAW_MARKER) ; return SFE_WVE_NOT_WVE ; } ; psf_binheader_readf (psf, "m", &marker) ; if (marker != SOUN_MARKER) { psf_log_printf (psf, "Could not find '%M'\n", SOUN_MARKER) ; return SFE_WVE_NOT_WVE ; } ; psf_binheader_readf (psf, "m", &marker) ; if (marker != DFIL_MARKER) { psf_log_printf (psf, "Could not find '%M'\n", DFIL_MARKER) ; return SFE_WVE_NOT_WVE ; } ; psf_binheader_readf (psf, "m", &marker) ; if (marker != ESSN_MARKER) { psf_log_printf (psf, "Could not find '%M'\n", ESSN_MARKER) ; return SFE_WVE_NOT_WVE ; } ; psf_binheader_readf (psf, "E2", &version) ; psf_log_printf (psf, "Psion Palmtop Alaw (.wve)\n" " Sample Rate : 8000\n" " Channels : 1\n" " Encoding : A-law\n") ; if (version != PSION_VERSION) psf_log_printf (psf, "Psion version %d should be %d\n", version, PSION_VERSION) ; psf_binheader_readf (psf, "E4", &datalength) ; psf->dataoffset = PSION_DATAOFFSET ; if (datalength != psf->filelength - psf->dataoffset) { psf->datalength = psf->filelength - psf->dataoffset ; psf_log_printf (psf, "Data length %d should be %D\n", datalength, psf->datalength) ; } else psf->datalength = datalength ; psf_binheader_readf (psf, "E22222", &padding, &repeats, &trash, &trash, &trash) ; psf->sf.format = SF_FORMAT_WVE | SF_FORMAT_ALAW ; psf->sf.samplerate = 8000 ; psf->sf.frames = psf->datalength ; psf->sf.channels = 1 ; return SFE_NO_ERROR ; } /* wve_read_header */
static int htk_read_header (SF_PRIVATE *psf) { int sample_count, sample_period, marker ; psf_binheader_readf (psf, "pE444", 0, &sample_count, &sample_period, &marker) ; if (2 * sample_count + 12 != psf->filelength) return SFE_HTK_BAD_FILE_LEN ; if (marker != 0x20000) return SFE_HTK_NOT_WAVEFORM ; psf->sf.channels = 1 ; if (sample_period > 0) { psf->sf.samplerate = 10000000 / sample_period ; psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d => %d Hz\n", sample_count, sample_period, psf->sf.samplerate) ; } else { psf->sf.samplerate = 16000 ; psf_log_printf (psf, "HTK Waveform file\n Sample Count : %d\n Sample Period : %d (should be > 0) => Guessed sample rate %d Hz\n", sample_count, sample_period, psf->sf.samplerate) ; } ; psf->sf.format = SF_FORMAT_HTK | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; /* HTK always has a 12 byte header. */ psf->dataoffset = 12 ; psf->endian = SF_ENDIAN_BIG ; psf->datalength = psf->filelength - psf->dataoffset ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* htk_read_header */
static int txw_read_header (SF_PRIVATE *psf) { BUF_UNION ubuf ; TXW_HEADER txwh ; const char *strptr ; memset (&txwh, 0, sizeof (txwh)) ; memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ; psf_binheader_readf (psf, "pb", 0, ubuf.cbuf, 16) ; if (memcmp (ubuf.cbuf, "LM8953\0\0\0\0\0\0\0\0\0\0", 16) != 0) return ERROR_666 ; psf_log_printf (psf, "Read only : Yamaha TX-16 Sampler (.txw)\nLM8953\n") ; /* Jump 6 bytes (dummp_aeg), read format, read sample rate. */ psf_binheader_readf (psf, "j11", 6, &txwh.format, &txwh.srate) ; /* 8 bytes (atc_length[3], rpt_length[3], unused[2]). */ psf_binheader_readf (psf, "e33j", &txwh.attacklen, &txwh.repeatlen, 2) ; txwh.sr2 = (txwh.attacklen >> 16) & 0xFE ; txwh.sr3 = (txwh.repeatlen >> 16) & 0xFE ; txwh.attacklen &= 0x1FFFF ; txwh.repeatlen &= 0x1FFFF ; switch (txwh.format) { case TXW_LOOPED : strptr = "looped" ; break ; case TXW_NO_LOOP : strptr = "non-looped" ; break ; default : psf_log_printf (psf, " Format : 0x%02x => ?????\n", txwh.format) ; return ERROR_666 ; } ; psf_log_printf (psf, " Format : 0x%02X => %s\n", txwh.format, strptr) ; strptr = NULL ; switch (txwh.srate) { case 1 : psf->sf.samplerate = 33333 ; break ; case 2 : psf->sf.samplerate = 50000 ; break ; case 3 : psf->sf.samplerate = 16667 ; break ; default : /* This is ugly and braindead. */ txwh.srhash = ((txwh.sr2 & 0xFE) << 8) | (txwh.sr3 & 0xFE) ; switch (txwh.srhash) { case ((0x6 << 8) | 0x52) : psf->sf.samplerate = 33333 ; break ; case ((0x10 << 8) | 0x52) : psf->sf.samplerate = 50000 ; break ; case ((0xF6 << 8) | 0x52) : psf->sf.samplerate = 166667 ; break ; default : strptr = " Sample Rate : Unknown : forcing to 33333\n" ; psf->sf.samplerate = 33333 ; break ; } ; } ; if (strptr) psf_log_printf (psf, strptr) ; else if (txwh.srhash) psf_log_printf (psf, " Sample Rate : %d (0x%X) => %d\n", txwh.srate, txwh.srhash, psf->sf.samplerate) ; else psf_log_printf (psf, " Sample Rate : %d => %d\n", txwh.srate, psf->sf.samplerate) ; if (txwh.format == TXW_LOOPED) { psf_log_printf (psf, " Attack Len : %d\n", txwh.attacklen) ; psf_log_printf (psf, " Repeat Len : %d\n", txwh.repeatlen) ; } ; psf->dataoffset = TXW_DATA_OFFSET ; psf->datalength = psf->filelength - TXW_DATA_OFFSET ; psf->sf.frames = 2 * psf->datalength / 3 ; if (psf->datalength % 3 == 1) psf_log_printf (psf, "*** File seems to be truncated, %d extra bytes.\n", (int) (psf->datalength % 3)) ; if (txwh.attacklen + txwh.repeatlen > psf->sf.frames) psf_log_printf (psf, "*** File has been truncated.\n") ; psf->sf.format = SF_FORMAT_TXW | SF_FORMAT_PCM_16 ; psf->sf.channels = 1 ; psf->sf.sections = 1 ; psf->sf.seekable = SF_TRUE ; return 0 ; } /* txw_read_header */
static int voc_read_header (SF_PRIVATE *psf) { VOC_DATA *pvoc ; char creative [20] ; unsigned char block_type, rate_byte ; short version, checksum, encoding, dataoffset ; int offset ; /* Set position to start of file to begin reading header. */ offset = psf_binheader_readf (psf, "pb", 0, creative, SIGNED_SIZEOF (creative)) ; if (creative [sizeof (creative) - 1] != 0x1A) return SFE_VOC_NO_CREATIVE ; /* Terminate the string. */ creative [sizeof (creative) - 1] = 0 ; if (strcmp ("Creative Voice File", creative)) return SFE_VOC_NO_CREATIVE ; psf_log_printf (psf, "%s\n", creative) ; offset += psf_binheader_readf (psf, "e222", &dataoffset, &version, &checksum) ; psf->dataoffset = dataoffset ; psf_log_printf (psf, "dataoffset : %d\n" "version : 0x%X\n" "checksum : 0x%X\n", psf->dataoffset, version, checksum) ; if (version != 0x010A && version != 0x0114) return SFE_VOC_BAD_VERSION ; if (! (psf->codec_data = malloc (sizeof (VOC_DATA)))) return SFE_MALLOC_FAILED ; pvoc = (VOC_DATA*) psf->codec_data ; memset (pvoc, 0, sizeof (VOC_DATA)) ; /* Set the default encoding now. */ psf->sf.format = SF_FORMAT_VOC ; /* Major format */ encoding = SF_FORMAT_PCM_U8 ; /* Minor format */ psf->endian = SF_ENDIAN_LITTLE ; while (1) { char header [256] ; unsigned size ; short count ; block_type = 0 ; offset += psf_binheader_readf (psf, "1", &block_type) ; switch (block_type) { case VOC_ASCII : offset += psf_binheader_readf (psf, "e3", &size) ; psf_log_printf (psf, " ASCII : %d\n", size) ; if (size < sizeof (header) - 1) { offset += psf_binheader_readf (psf, "b", header, size) ; header [size] = 0 ; psf_log_printf (psf, " text : %s\n", header) ; continue ; } offset += psf_binheader_readf (psf, "j", size) ; continue ; case VOC_REPEAT : offset += psf_binheader_readf (psf, "e32", &size, &count) ; psf_log_printf (psf, " Repeat : %d\n", count) ; continue ; case VOC_SOUND_DATA : case VOC_EXTENDED : case VOC_EXTENDED_II : break ; default : psf_log_printf (psf, "*** Weird block marker (%d)\n", block_type) ; } ; break ; } ; if (block_type == VOC_SOUND_DATA) { unsigned char compression ; int size ; offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ; psf->sf.samplerate = 1000000 / (256 - (rate_byte & 0xFF)) ; psf_log_printf (psf, " Sound Data : %d\n sr : %d => %dHz\n comp : %d\n", size, rate_byte, psf->sf.samplerate, compression) ; if (offset + size - 1 > psf->filelength) { psf_log_printf (psf, "Seems to be a truncated file.\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } else if (psf->filelength - offset - size > 4) { psf_log_printf (psf, "Seems to be a multi-segment file (#1).\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } ; psf->dataoffset = offset ; psf->dataend = psf->filelength - 1 ; psf->sf.channels = 1 ; psf->bytewidth = 1 ; psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; return 0 ; } ; if (block_type == VOC_EXTENDED) { unsigned char pack, stereo, compression ; unsigned short rate_short ; int size ; offset += psf_binheader_readf (psf, "e3211", &size, &rate_short, &pack, &stereo) ; psf_log_printf (psf, " Extended : %d\n", size) ; if (size == 4) psf_log_printf (psf, " size : 4\n") ; else psf_log_printf (psf, " size : %d (should be 4)\n", size) ; psf_log_printf (psf, " pack : %d\n" " stereo : %s\n", pack, (stereo ? "yes" : "no")) ; if (stereo) { psf->sf.channels = 2 ; psf->sf.samplerate = 128000000 / (65536 - rate_short) ; } else { psf->sf.channels = 1 ; psf->sf.samplerate = 256000000 / (65536 - rate_short) ; } ; psf_log_printf (psf, " sr : %d => %dHz\n", (rate_short & 0xFFFF), psf->sf.samplerate) ; offset += psf_binheader_readf (psf, "1", &block_type) ; if (block_type != VOC_SOUND_DATA) { psf_log_printf (psf, "*** Expecting VOC_SOUND_DATA section.\n") ; return SFE_VOC_BAD_FORMAT ; } ; offset += psf_binheader_readf (psf, "e311", &size, &rate_byte, &compression) ; psf_log_printf (psf, " Sound Data : %d\n" " sr : %d\n" " comp : %d\n", size, rate_byte, compression) ; if (offset + size - 1 > psf->filelength) { psf_log_printf (psf, "Seems to be a truncated file.\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } else if (offset + size - 1 < psf->filelength) { psf_log_printf (psf, "Seems to be a multi-segment file (#2).\n") ; psf_log_printf (psf, "offset: %d size: %d sum: %d filelength: %D\n", offset, size, offset + size, psf->filelength) ; return SFE_VOC_BAD_SECTIONS ; } ; psf->dataoffset = offset ; psf->dataend = psf->filelength - 1 ; psf->bytewidth = 1 ; psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; return 0 ; } if (block_type == VOC_EXTENDED_II) { unsigned char bitwidth, channels ; int size, fourbytes ; offset += psf_binheader_readf (psf, "e341124", &size, &psf->sf.samplerate, &bitwidth, &channels, &encoding, &fourbytes) ; if (size * 2 == psf->filelength - 39) { int temp_size = psf->filelength - 31 ; psf_log_printf (psf, " Extended II : %d (SoX bug: should be %d)\n", size, temp_size) ; size = temp_size ; } else psf_log_printf (psf, " Extended II : %d\n", size) ; psf_log_printf (psf, " sample rate : %d\n" " bit width : %d\n" " channels : %d\n", psf->sf.samplerate, bitwidth, channels) ; if (bitwidth == 16 && encoding == 0) { encoding = 4 ; psf_log_printf (psf, " encoding : 0 (SoX bug: should be 4 for 16 bit signed PCM)\n") ; } else psf_log_printf (psf, " encoding : %d => %s\n", encoding, voc_encoding2str (encoding)) ; psf_log_printf (psf, " fourbytes : %X\n", fourbytes) ; psf->sf.channels = channels ; psf->dataoffset = offset ; psf->dataend = psf->filelength - 1 ; if (size + 31 == psf->filelength + 1) { /* Hack for reading files produced using ** sf_command (SFC_UPDATE_HEADER_NOW). */ psf_log_printf (psf, "Missing zero byte at end of file.\n") ; size = psf->filelength - 30 ; psf->dataend = 0 ; } else if (size + 31 > psf->filelength) { psf_log_printf (psf, "Seems to be a truncated file.\n") ; size = psf->filelength - 31 ; } else if (size + 31 < psf->filelength) psf_log_printf (psf, "Seems to be a multi-segment file (#3).\n") ; switch (encoding) { case 0 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_U8 ; psf->bytewidth = 1 ; break ; case 4 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; case 6 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ALAW ; psf->bytewidth = 1 ; break ; case 7 : psf->sf.format = SF_FORMAT_VOC | SF_FORMAT_ULAW ; psf->bytewidth = 1 ; break ; default : /* Unknown */ return SFE_UNKNOWN_FORMAT ; break ; } ; } ; return 0 ; } /* voc_read_header */
static int avr_read_header (SF_PRIVATE *psf) { AVR_HEADER hdr ; memset (&hdr, 0, sizeof (hdr)) ; psf_binheader_readf (psf, "pmb", 0, &hdr.marker, &hdr.name, sizeof (hdr.name)) ; psf_log_printf (psf, "%M\n", hdr.marker) ; if (hdr.marker != TWOBIT_MARKER) return SFE_AVR_X ; psf_log_printf (psf, " Name : %s\n", hdr.name) ; psf_binheader_readf (psf, "E22222", &hdr.mono, &hdr.rez, &hdr.sign, &hdr.loop, &hdr.midi) ; psf->sf.channels = (hdr.mono & 1) + 1 ; psf_log_printf (psf, " Channels : %d\n Bit width : %d\n Signed : %s\n", (hdr.mono & 1) + 1, hdr.rez, hdr.sign ? "yes" : "no") ; switch ((hdr.rez << 16) + (hdr.sign & 1)) { case ((8 << 16) + 0) : psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_U8 ; psf->bytewidth = 1 ; break ; case ((8 << 16) + 1) : psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; break ; case ((16 << 16) + 1) : psf->sf.format = SF_FORMAT_AVR | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; default : psf_log_printf (psf, "Error : bad rez/sign combination.\n") ; return SFE_AVR_X ; } ; psf_binheader_readf (psf, "E4444", &hdr.srate, &hdr.frames, &hdr.lbeg, &hdr.lend) ; psf->sf.frames = hdr.frames ; psf->sf.samplerate = hdr.srate ; psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ; psf_log_printf (psf, " Sample rate : %d\n", psf->sf.samplerate) ; psf_binheader_readf (psf, "E222", &hdr.res1, &hdr.res2, &hdr.res3) ; psf_binheader_readf (psf, "bb", hdr.ext, sizeof (hdr.ext), hdr.user, sizeof (hdr.user)) ; psf_log_printf (psf, " Ext : %s\n User : %s\n", hdr.ext, hdr.user) ; psf->endian = SF_ENDIAN_BIG ; psf->dataoffset = AVR_HDR_SIZE ; psf->datalength = hdr.frames * (hdr.rez / 8) ; if (psf->fileoffset > 0) psf->filelength = AVR_HDR_SIZE + psf->datalength ; if (psf_ftell (psf) != psf->dataoffset) psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (psf->sf.frames == 0 && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* avr_read_header */
static int nist_read_header (SF_PRIVATE *psf) { char *psf_header ; int bitwidth = 0, bytes = 0, count, encoding ; char str [64], *cptr ; long samples ; psf->sf.format = SF_FORMAT_NIST ; psf_header = (char*) psf->header ; if (sizeof (psf->header) <= NIST_HEADER_LENGTH) return SFE_INTERNAL ; /* Go to start of file and read in the whole header. */ psf_binheader_readf (psf, "pb", 0, psf_header, NIST_HEADER_LENGTH) ; /* Header is a string, so make sure it is null terminated. */ psf_header [NIST_HEADER_LENGTH] = 0 ; /* Now trim the header after the end marker. */ if ((cptr = strstr (psf_header, "end_head"))) { cptr += strlen ("end_head") + 1 ; cptr [0] = 0 ; } ; psf_log_printf (psf, psf_header) ; /* Make sure its a NIST file. */ if (strstr (psf_header, "NIST_1A\n 1024\n") != psf_header) { printf ("Not a NIST file.\n") ; puts (psf_header) ; exit (1) ; } ; /* Determine sample encoding, start by assuming PCM. */ encoding = SF_FORMAT_PCM_U8 ; if ((cptr = strstr (psf_header, "sample_coding -s"))) { sscanf (cptr, "sample_coding -s%d %63s", &count, str) ; if (strcmp (str, "pcm") == 0) encoding = SF_FORMAT_PCM_U8 ; else if (strcmp (str, "alaw") == 0) encoding = SF_FORMAT_ALAW ; else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0)) encoding = SF_FORMAT_ULAW ; else { psf_log_printf (psf, "*** Unknown encoding : %s\n", str) ; encoding = 0 ; } ; } ; if ((cptr = strstr (psf_header, "channel_count -i "))) sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ; if ((cptr = strstr (psf_header, "sample_rate -i "))) sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ; if ((cptr = strstr (psf_header, "sample_count -i "))) { sscanf (psf_header, "sample_count -i %ld", &samples) ; psf->sf.frames = samples ; } ; if ((cptr = strstr (psf_header, "sample_n_bytes -i "))) sscanf (cptr, "sample_n_bytes -i %d", &(psf->bytewidth)) ; /* Default endian-ness (for 8 bit, u-law, A-law. */ psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; /* This is where we figure out endian-ness. */ if ((cptr = strstr (psf_header, "sample_byte_format -s"))) { sscanf (cptr, "sample_byte_format -s%d %8s", &bytes, str) ; if (bytes > 1) { if (psf->bytewidth == 0) psf->bytewidth = bytes ; else if (psf->bytewidth != bytes) { psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ; return SFE_NIST_BAD_ENCODING ; } ; if (strstr (str, "01") == str) psf->endian = SF_ENDIAN_LITTLE ; else if (strstr (str, "10")) psf->endian = SF_ENDIAN_BIG ; else { psf_log_printf (psf, "Weird endian-ness : %s\n", str) ; return SFE_NIST_BAD_ENCODING ; } ; } ; psf->sf.format |= psf->endian ; } ; if ((cptr = strstr (psf_header, "sample_sig_bits -i "))) sscanf (cptr, "sample_sig_bits -i %d", &bitwidth) ; if (strstr (psf_header, "channels_interleaved -s5 FALSE")) { psf_log_printf (psf, "Non-interleaved data unsupported.\n", str) ; return SFE_NIST_BAD_ENCODING ; } ; psf->dataoffset = NIST_HEADER_LENGTH ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->datalength = psf->filelength - psf->dataoffset ; psf->close = nist_close ; psf_fseek (psf->filedes, psf->dataoffset, SEEK_SET) ; if (encoding == SF_FORMAT_PCM_U8) { switch (psf->bytewidth) { case 1 : psf->sf.format |= SF_FORMAT_PCM_S8 ; break ; case 2 : psf->sf.format |= SF_FORMAT_PCM_16 ; break ; case 3 : psf->sf.format |= SF_FORMAT_PCM_24 ; break ; case 4 : psf->sf.format |= SF_FORMAT_PCM_32 ; break ; default : break ; } ; } else if (encoding != 0) psf->sf.format |= encoding ; else return SFE_UNIMPLEMENTED ; return 0 ; } /* nist_read_header */
static int w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) { WAV_PRIVATE *wpriv ; WAV_FMT *wav_fmt ; int dword = 0, marker, format = 0 ; sf_count_t chunk_size, bytesread = 0 ; int parsestage = 0, error, done = 0 ; if ((wpriv = psf->container_data) == NULL) return SFE_INTERNAL ; wav_fmt = &wpriv->wav_fmt ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "p", 0) ; while (! done) { /* Each new chunk must start on an 8 byte boundary, so jump if needed. */ if (psf->headindex & 0x7) psf_binheader_readf (psf, "j", 8 - (psf->headindex & 0x7)) ; /* Generate hash of 16 byte marker. */ marker = chunk_size = 0 ; bytesread = psf_binheader_readf (psf, "eh8", &marker, &chunk_size) ; if (bytesread == 0) break ; switch (marker) { case riff_HASH16 : if (parsestage) return SFE_W64_NO_RIFF ; if (psf->filelength != chunk_size) psf_log_printf (psf, "riff : %D (should be %D)\n", chunk_size, psf->filelength) ; else psf_log_printf (psf, "riff : %D\n", chunk_size) ; parsestage |= HAVE_riff ; bytesread += psf_binheader_readf (psf, "h", &marker) ; if (marker == wave_HASH16) { if ((parsestage & HAVE_riff) != HAVE_riff) return SFE_W64_NO_WAVE ; psf_log_printf (psf, "wave\n") ; parsestage |= HAVE_wave ; } ; chunk_size = 0 ; break ; case ACID_HASH16: psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ; return SFE_UNIMPLEMENTED ; case fmt_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave)) return SFE_WAV_NO_FMT ; psf_log_printf (psf, " fmt : %D\n", chunk_size) ; /* size of 16 byte marker and 8 byte chunk_size value. */ chunk_size -= 24 ; if ((error = wav_w64_read_fmt_chunk (psf, (int) chunk_size))) return error ; if (chunk_size % 8) psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ; format = wav_fmt->format ; parsestage |= HAVE_fmt ; chunk_size = 0 ; break ; case fact_HASH16: { sf_count_t frames ; psf_binheader_readf (psf, "e8", &frames) ; psf_log_printf (psf, " fact : %D\n frames : %D\n", chunk_size, frames) ; } ; chunk_size = 0 ; break ; case data_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt)) return SFE_W64_NO_DATA ; psf->dataoffset = psf_ftell (psf) ; psf->datalength = SF_MIN (chunk_size - 24, psf->filelength - psf->dataoffset) ; if (chunk_size % 8) chunk_size += 8 - (chunk_size % 8) ; psf_log_printf (psf, "data : %D\n", chunk_size) ; parsestage |= HAVE_data ; if (! psf->sf.seekable) break ; /* Seek past data and continue reading header. */ psf_fseek (psf, chunk_size, SEEK_CUR) ; chunk_size = 0 ; break ; case levl_HASH16 : psf_log_printf (psf, "levl : %D\n", chunk_size) ; chunk_size -= 24 ; break ; case list_HASH16 : psf_log_printf (psf, "list : %D\n", chunk_size) ; chunk_size -= 24 ; break ; case junk_HASH16 : psf_log_printf (psf, "junk : %D\n", chunk_size) ; chunk_size -= 24 ; break ; case bext_MARKER : psf_log_printf (psf, "bext : %D\n", chunk_size) ; chunk_size -= 24 ; break ; case MARKER_HASH16 : psf_log_printf (psf, "marker : %D\n", chunk_size) ; chunk_size -= 24 ; break ; case SUMLIST_HASH16 : psf_log_printf (psf, "summary list : %D\n", chunk_size) ; chunk_size -= 24 ; break ; default : psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %D. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ; done = SF_TRUE ; break ; } ; /* switch (dword) */ if (chunk_size >= psf->filelength) { psf_log_printf (psf, "*** Chunk size %u > file length %D. Exiting parser.\n", chunk_size, psf->filelength) ; break ; } ; if (psf->sf.seekable == 0 && (parsestage & HAVE_data)) break ; if (psf_ftell (psf) >= (psf->filelength - (2 * SIGNED_SIZEOF (dword)))) break ; if (chunk_size > 0 && chunk_size < 0xffff0000) { dword = chunk_size ; psf_binheader_readf (psf, "j", dword - 24) ; } ; } ; /* while (1) */ if (psf->dataoffset <= 0) return SFE_W64_NO_DATA ; if (psf->sf.channels < 1) return SFE_CHANNEL_COUNT_ZERO ; if (psf->sf.channels >= SF_MAX_CHANNELS) return SFE_CHANNEL_COUNT ; psf->endian = SF_ENDIAN_LITTLE ; /* All W64 files are little endian. */ if (psf_ftell (psf) != psf->dataoffset) psf_fseek (psf, psf->dataoffset, SEEK_SET) ; if (psf->blockwidth) { if (psf->filelength - psf->dataoffset < psf->datalength) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; else psf->sf.frames = psf->datalength / psf->blockwidth ; } ; switch (format) { case WAVE_FORMAT_PCM : case WAVE_FORMAT_EXTENSIBLE : /* extensible might be FLOAT, MULAW, etc as well! */ psf->sf.format = SF_FORMAT_W64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ; break ; case WAVE_FORMAT_MULAW : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ; break ; case WAVE_FORMAT_ALAW : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ; break ; case WAVE_FORMAT_MS_ADPCM : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM) ; *blockalign = wav_fmt->msadpcm.blockalign ; *framesperblock = wav_fmt->msadpcm.samplesperblock ; break ; case WAVE_FORMAT_IMA_ADPCM : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM) ; *blockalign = wav_fmt->ima.blockalign ; *framesperblock = wav_fmt->ima.samplesperblock ; break ; case WAVE_FORMAT_GSM610 : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ; break ; case WAVE_FORMAT_IEEE_FLOAT : psf->sf.format = SF_FORMAT_W64 ; psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; break ; default : return SFE_UNIMPLEMENTED ; } ; return 0 ; } /* w64_read_header */
static int dwd_read_header (SF_PRIVATE *psf) { BUF_UNION ubuf ; DWD_HEADER dwdh ; memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pb", 0, ubuf.cbuf, DWD_IDENTIFIER_LEN) ; if (memcmp (ubuf.cbuf, DWD_IDENTIFIER, DWD_IDENTIFIER_LEN) != 0) return SFE_DWD_NO_DWD ; psf_log_printf (psf, "Read only : DiamondWare Digitized (.dwd)\n", ubuf.cbuf) ; psf_binheader_readf (psf, "11", &dwdh.major, &dwdh.minor) ; psf_binheader_readf (psf, "e4j1", &dwdh.id, 1, &dwdh.compression) ; psf_binheader_readf (psf, "e211", &dwdh.srate, &dwdh.channels, &dwdh.bitwidth) ; psf_binheader_readf (psf, "e24", &dwdh.maxval, &dwdh.datalen) ; psf_binheader_readf (psf, "e44", &dwdh.frames, &dwdh.offset) ; psf_log_printf (psf, " Version Major : %d\n Version Minor : %d\n Unique ID : %08X\n", dwdh.major, dwdh.minor, dwdh.id) ; psf_log_printf (psf, " Compression : %d => ", dwdh.compression) ; if (dwdh.compression != 0) { psf_log_printf (psf, "Unsupported compression\n") ; return SFE_DWD_COMPRESSION ; } else psf_log_printf (psf, "None\n") ; psf_log_printf (psf, " Sample Rate : %d\n Channels : %d\n" " Bit Width : %d\n", dwdh.srate, dwdh.channels, dwdh.bitwidth) ; switch (dwdh.bitwidth) { case 8 : psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; break ; case 16 : psf->sf.format = SF_FORMAT_DWD | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; default : psf_log_printf (psf, "*** Bad bit width %d\n", dwdh.bitwidth) ; return SFE_DWD_BAND_BIT_WIDTH ; } ; if (psf->filelength != dwdh.offset + dwdh.datalen) { psf_log_printf (psf, " Data Length : %d (should be %D)\n", dwdh.datalen, psf->filelength - dwdh.offset) ; dwdh.datalen = (unsigned int) (psf->filelength - dwdh.offset) ; } else psf_log_printf (psf, " Data Length : %d\n", dwdh.datalen) ; psf_log_printf (psf, " Max Value : %d\n", dwdh.maxval) ; psf_log_printf (psf, " Frames : %d\n", dwdh.frames) ; psf_log_printf (psf, " Data Offset : %d\n", dwdh.offset) ; psf->datalength = dwdh.datalen ; psf->dataoffset = dwdh.offset ; psf->endian = SF_ENDIAN_LITTLE ; psf->sf.samplerate = dwdh.srate ; psf->sf.channels = dwdh.channels ; psf->sf.sections = 1 ; return pcm_init (psf) ; } /* dwd_read_header */
static int au_read_header (SF_PRIVATE *psf) { AU_FMT au_fmt ; int marker, dword ; memset (&au_fmt, 0, sizeof (au_fmt)) ; psf_binheader_readf (psf, "pm", 0, &marker) ; psf_log_printf (psf, "%M\n", marker) ; if (marker == DOTSND_MARKER) { psf->endian = SF_ENDIAN_BIG ; psf_binheader_readf (psf, "E44444", &(au_fmt.dataoffset), &(au_fmt.datasize), &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ; } else if (marker == DNSDOT_MARKER) { psf->endian = SF_ENDIAN_LITTLE ; psf_binheader_readf (psf, "e44444", &(au_fmt.dataoffset), &(au_fmt.datasize), &(au_fmt.encoding), &(au_fmt.samplerate), &(au_fmt.channels)) ; } else return SFE_AU_NO_DOTSND ; psf_log_printf (psf, " Data Offset : %d\n", au_fmt.dataoffset) ; if (psf->fileoffset > 0 && au_fmt.datasize == -1) { psf_log_printf (psf, " Data Size : -1\n") ; return SFE_AU_EMBED_BAD_LEN ; } ; if (psf->fileoffset > 0) { psf->filelength = au_fmt.dataoffset + au_fmt.datasize ; psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; } else if (au_fmt.datasize == -1 || au_fmt.dataoffset + au_fmt.datasize == psf->filelength) psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; else if (au_fmt.dataoffset + au_fmt.datasize < psf->filelength) { psf->filelength = au_fmt.dataoffset + au_fmt.datasize ; psf_log_printf (psf, " Data Size : %d\n", au_fmt.datasize) ; } else { dword = psf->filelength - au_fmt.dataoffset ; psf_log_printf (psf, " Data Size : %d (should be %d)\n", au_fmt.datasize, dword) ; au_fmt.datasize = dword ; } ; psf->dataoffset = au_fmt.dataoffset ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf_ftell (psf) < psf->dataoffset) psf_binheader_readf (psf, "j", psf->dataoffset - psf_ftell (psf)) ; psf->sf.samplerate = au_fmt.samplerate ; psf->sf.channels = au_fmt.channels ; /* Only fill in type major. */ if (psf->endian == SF_ENDIAN_BIG) psf->sf.format = SF_FORMAT_AU ; else if (psf->endian == SF_ENDIAN_LITTLE) psf->sf.format = SF_ENDIAN_LITTLE | SF_FORMAT_AU ; psf_log_printf (psf, " Encoding : %d => ", au_fmt.encoding) ; psf->sf.format = SF_ENDIAN (psf->sf.format) ; switch (au_fmt.encoding) { case AU_ENCODING_ULAW_8 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ULAW ; psf->bytewidth = 1 ; /* Before decoding */ psf_log_printf (psf, "8-bit ISDN u-law\n") ; break ; case AU_ENCODING_PCM_8 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_S8 ; psf->bytewidth = 1 ; psf_log_printf (psf, "8-bit linear PCM\n") ; break ; case AU_ENCODING_PCM_16 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; psf_log_printf (psf, "16-bit linear PCM\n") ; break ; case AU_ENCODING_PCM_24 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_24 ; psf->bytewidth = 3 ; psf_log_printf (psf, "24-bit linear PCM\n") ; break ; case AU_ENCODING_PCM_32 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; psf_log_printf (psf, "32-bit linear PCM\n") ; break ; case AU_ENCODING_FLOAT : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_FLOAT ; psf->bytewidth = 4 ; psf_log_printf (psf, "32-bit float\n") ; break ; case AU_ENCODING_DOUBLE : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_DOUBLE ; psf->bytewidth = 8 ; psf_log_printf (psf, "64-bit double precision float\n") ; break ; case AU_ENCODING_ALAW_8 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_ALAW ; psf->bytewidth = 1 ; /* Before decoding */ psf_log_printf (psf, "8-bit ISDN A-law\n") ; break ; case AU_ENCODING_ADPCM_G721_32 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G721_32 ; psf->bytewidth = 0 ; psf_log_printf (psf, "G721 32kbs ADPCM\n") ; break ; case AU_ENCODING_ADPCM_G723_24 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_24 ; psf->bytewidth = 0 ; psf_log_printf (psf, "G723 24kbs ADPCM\n") ; break ; case AU_ENCODING_ADPCM_G723_40 : psf->sf.format |= SF_FORMAT_AU | SF_FORMAT_G723_40 ; psf->bytewidth = 0 ; psf_log_printf (psf, "G723 40kbs ADPCM\n") ; break ; case AU_ENCODING_ADPCM_G722 : psf_log_printf (psf, "G722 64 kbs ADPCM (unsupported)\n") ; break ; case AU_ENCODING_NEXT : psf_log_printf (psf, "Weird NeXT encoding format (unsupported)\n") ; break ; default : psf_log_printf (psf, "Unknown!!\n") ; break ; } ; psf_log_printf (psf, " Sample Rate : %d\n", au_fmt.samplerate) ; if (au_fmt.channels < 1) { psf_log_printf (psf, " Channels : %d **** should be >= 1\n", au_fmt.channels) ; return SFE_CHANNEL_COUNT_ZERO ; } else if (au_fmt.channels > SF_MAX_CHANNELS) { psf_log_printf (psf, " Channels : %d **** should be <= %d\n", au_fmt.channels, SF_MAX_CHANNELS) ; return SFE_CHANNEL_COUNT ; } ; psf_log_printf (psf, " Channels : %d\n", au_fmt.channels) ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; return 0 ; } /* au_read_header */
int rx2_open (SF_PRIVATE *psf) { int error, marker, length, glob_offset, slce_count ; int sdat_length = 0, slce_total = 0 ; /* So far only doing read. */ psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ; if (marker != CAT_MARKER) { psf_log_printf (psf, "length : %d\n", length) ; return -1000 ; } ; if (length != psf->filelength - 8) psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ; else psf_log_printf (psf, "%M : %d\n", marker, length) ; /* 'REX2' marker */ psf_binheader_readf (psf, "m", &marker) ; psf_log_printf (psf, "%M", marker) ; /* 'HEAD' marker */ psf_binheader_readf (psf, "m", &marker) ; psf_log_printf (psf, "%M\n", marker) ; /* Grab 'GLOB' offset. */ psf_binheader_readf (psf, "E4", &glob_offset) ; glob_offset += 0x14 ; /* Add the current file offset. */ /* Jump to offset 0x30 */ psf_binheader_readf (psf, "p", 0x30) ; /* Get name length */ length = 0 ; psf_binheader_readf (psf, "1", &length) ; if (length >= SIGNED_SIZEOF (psf->buffer)) { psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ; return -1001 ; } memset (psf->buffer, 0, SIGNED_SIZEOF (psf->buffer)) ; psf_binheader_readf (psf, "b", psf->buffer, length) ; psf_log_printf (psf, " Text : \"%s\"\n", psf->buffer) ; /* Jump to GLOB offset position. */ if (glob_offset & 1) glob_offset ++ ; psf_binheader_readf (psf, "p", glob_offset) ; slce_count = 0 ; /* GLOB */ while (1) { psf_binheader_readf (psf, "m", &marker) ; if (marker != SLCE_MARKER && slce_count > 0) { psf_log_printf (psf, " SLCE count : %d\n", slce_count) ; slce_count = 0 ; } switch (marker) { case GLOB_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; psf_binheader_readf (psf, "j", length) ; break ; case RECY_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */ break ; case CAT_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; /*-psf_binheader_readf (psf, "j", length) ;-*/ break ; case DEVL_MARKER: psf_binheader_readf (psf, "mE4", &marker, &length) ; psf_log_printf (psf, " DEVL%M : %d\n", marker, length) ; if (length & 1) length ++ ; psf_binheader_readf (psf, "j", length) ; break ; case EQ_MARKER: case COMP_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; /* This is weird!!!! why make this (length - 1) */ if (length & 1) length ++ ; psf_binheader_readf (psf, "j", length) ; break ; case SLCL_MARKER: psf_log_printf (psf, " %M\n", marker) ; slce_count = 0 ; break ; case SLCE_MARKER: /*-psf_log_printf (psf, " %M\n", marker) ;-*/ psf_binheader_readf (psf, "E4", &length) ; /*-psf_log_printf (psf, " ???????? : 0x%X\n", length) ;-*/ psf_binheader_readf (psf, "E4", &length) ; /*-psf_log_printf (psf, " Start ? : %d\n", length) ;-*/ psf_binheader_readf (psf, "E4", &length) ; /*-psf_log_printf (psf, " Length ? : %d\n", length) ;-*/ slce_total += length ; psf_binheader_readf (psf, "E4", &length) ; /*-psf_log_printf (psf, " ???????? : 0x%X\n", length) ;-*/ slce_count ++ ; break ; case SINF_MARKER: psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " %M : %d\n", marker, length) ; psf_binheader_readf (psf, "E2", &length) ; psf_log_printf (psf, " REX Version : %X ?\n", length) ; psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &psf->sf.frames) ; psf_log_printf (psf, " Sample Rate : %d\n", psf->sf.samplerate) ; psf_log_printf (psf, " Frames : %d\n", psf->sf.frames) ; psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " ??????????? : %d\n", length) ; psf_binheader_readf (psf, "E4", &length) ; psf_log_printf (psf, " ??????????? : %d\n", length) ; break ; case SDAT_MARKER: psf_binheader_readf (psf, "E4", &length) ; sdat_length = length ; /* Get the current offset. */ psf->dataoffset = psf_binheader_readf (psf, NULL) ; if (psf->dataoffset + length != psf->filelength) psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ; else psf_log_printf (psf, " %M : %d\n", marker, length) ; break ; default : psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ; return -1003 ; break ; } ; /* SDAT always last marker in file. */ if (marker == SDAT_MARKER) break ; } ; puts (psf->logbuffer) ; puts ("-----------------------------------") ; printf ("SDAT length : %d\n", sdat_length) ; printf ("SLCE samples : %d\n", slce_total) ; /* Two bytes per sample. */ printf ("Comp Ratio : %f:1\n", (2.0 * slce_total) / sdat_length) ; puts (" ") ; psf->logbuffer [0] = 0 ; /* OK, have the header althought not too sure what it all means. */ psf->endian = SF_ENDIAN_BIG ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf_fseek (psf->filedes, psf->dataoffset, SEEK_SET)) return SFE_BAD_SEEK ; psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ; psf->sf.channels = 1 ; psf->bytewidth = 2 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; if ((error = dwvw_init (psf, 16))) return error ; psf->close = rx2_close ; if (! psf->sf.frames && psf->blockwidth) psf->sf.frames = psf->datalength / psf->blockwidth ; /* All done. */ return 0 ; } /* rx2_open */
int sd2_open (SF_PRIVATE *psf) { int marker, software, rsrc_offset, len ; int rsrc_data_offset, rsrc_map_offset, rsrc_data_length, rsrc_map_length ; char slen ; float srate ; /* Read only so far. */ psf_binheader_readf (psf, "Epmmj", 0x41, &marker, &software, 14) ; if (marker != Sd2f_MARKER) { printf ("Whoops!!!\n") ; puts (psf->logbuffer) ; exit (1) ; } ; psf_log_printf (psf, "Marker : %M\n" "Software : %M\n", marker, software) ; /* This seems to be a constant for binhex files. */ psf->dataoffset = 0x80 ; /* All SD2 files are big endian. */ psf->endian= SF_ENDIAN_BIG ; /* ** Resource header info from: ** http://developer.apple.com/techpubs/mac/MoreToolbox/MoreToolbox-99.html */ rsrc_offset = psf->datalength + psf->dataoffset ; if (rsrc_offset & 0x7F) rsrc_offset = rsrc_offset - (rsrc_offset & 0x7F) + psf->dataoffset ; psf_log_printf (psf, "Resource offset : 0x%X\n", rsrc_offset) ; /* Jump to the rsrc_offset fork section. */ psf_binheader_readf (psf, "Ep", rsrc_offset) ; psf_binheader_readf (psf, "E4444", &rsrc_data_offset, &rsrc_map_offset, &rsrc_data_length, &rsrc_map_length) ; rsrc_data_offset += rsrc_offset ; rsrc_map_offset += rsrc_offset ; psf_log_printf (psf, " data offset : 0x%X\n" " map offset : 0x%X\n" " data length : 0x%X\n" " map length : 0x%X\n", rsrc_data_offset, rsrc_map_offset, rsrc_data_length, rsrc_map_length) ; if (rsrc_data_offset + rsrc_data_length > rsrc_map_offset || rsrc_map_offset + rsrc_map_length > psf->filelength) { puts ("##############################") ; puts (psf->logbuffer) ; puts ("##############################") ; exit (1) ; } ; memset (psf->buffer, 0, sizeof (psf->buffer)) ; psf_binheader_readf (psf, "Ep41", rsrc_data_offset, &len, &slen) ; if (slen + 1 == len) { psf_binheader_readf (psf, "Eb", psf->buffer, len - 1) ; ((char*) psf->buffer) [len - 1] = 0 ; if (sscanf ((char*) psf->buffer, "%d", &len) == 1) psf->bytewidth = len ; } ; psf_binheader_readf (psf, "E41", &len, &slen) ; if (slen + 1 == len) { psf_binheader_readf (psf, "Eb", psf->buffer, len - 1) ; ((char*) psf->buffer) [len - 1] = 0 ; if (sscanf ((char*) psf->buffer, "%f", &srate) == 1) psf->sf.samplerate = srate ; } ; psf_binheader_readf (psf, "E41", &len, &slen) ; if (slen + 1 == len) { psf_binheader_readf (psf, "Eb", psf->buffer, len - 1) ; ((char*) psf->buffer) [len - 1] = 0 ; if (sscanf ((char*) psf->buffer, "%d", &len) == 1) psf->sf.channels = len ; } ; psf_log_printf (psf, " byte width : %d\n", psf->bytewidth) ; psf_log_printf (psf, " sample rate : %d\n", psf->sf.samplerate) ; psf_log_printf (psf, " channels : %d\n", psf->sf.channels) ; if (psf->bytewidth == 2) { psf->sf.format = SF_FORMAT_SD2 | SF_FORMAT_PCM_16 ; psf->blockwidth = psf->bytewidth * psf->sf.channels ; psf->sf.frames = psf->datalength / psf->blockwidth ; } ; pcm_init (psf) ; psf_fseek (psf->filedes, psf->dataoffset, SEEK_SET) ; psf->close = sd2_close ; return 0 ; } /* sd2_open */
static int caf_read_header (SF_PRIVATE *psf) { CAF_PRIVATE *pcaf ; BUF_UNION ubuf ; DESC_CHUNK desc ; sf_count_t chunk_size ; double srate ; short version, flags ; int marker, k, have_data = 0, error ; if ((pcaf = psf->container_data) == NULL) return SFE_INTERNAL ; memset (&desc, 0, sizeof (desc)) ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ; psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ; if (marker != caff_MARKER) return SFE_CAF_NOT_CAF ; psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, ubuf.ucbuf, 8) ; srate = double64_be_read (ubuf.ucbuf) ; snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), "%5.3f", srate) ; psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, ubuf.cbuf) ; if (marker != desc_MARKER) return SFE_CAF_NO_DESC ; if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK)) { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ; return SFE_MALFORMED_FILE ; } ; psf->sf.samplerate = lrint (srate) ; psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.frames_per_packet, &desc.channels_per_frame, &desc.bits_per_chan) ; psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n" " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.frames_per_packet, desc.channels_per_frame, desc.bits_per_chan) ; if (desc.channels_per_frame > SF_MAX_CHANNELS) { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ; return SFE_MALFORMED_FILE ; } ; if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK)) psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ; psf->sf.channels = desc.channels_per_frame ; while (1) { marker = 0 ; chunk_size = 0 ; psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ; if (marker == 0) { sf_count_t pos = psf_ftell (psf) ; psf_log_printf (psf, "Have 0 marker at position %D (0x%x).\n", pos, pos) ; break ; } ; if (chunk_size < 0) { psf_log_printf (psf, "%M : %D *** Should be >= 0 ***\n", marker, chunk_size) ; break ; } ; psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ; switch (marker) { case peak_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) { psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; return SFE_CAF_BAD_PEAK ; } ; if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) return SFE_MALLOC_FAILED ; /* read in rest of PEAK chunk. */ psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ; psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ; psf_log_printf (psf, " Ch Position Value\n") ; for (k = 0 ; k < psf->sf.channels ; k++) { sf_count_t position ; float value ; psf_binheader_readf (psf, "Ef8", &value, &position) ; psf->peak_info->peaks [k].value = value ; psf->peak_info->peaks [k].position = position ; snprintf (ubuf.cbuf, sizeof (ubuf.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ; psf_log_printf (psf, ubuf.cbuf) ; } ; psf->peak_info->peak_loc = SF_PEAK_START ; break ; case chan_MARKER : if (chunk_size < 12) { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; break ; } psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; if ((error = caf_read_chanmap (psf, chunk_size))) return error ; break ; case free_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; break ; case data_MARKER : psf_binheader_readf (psf, "E4", &k) ; if (chunk_size == -1) { psf_log_printf (psf, "%M : -1\n") ; chunk_size = psf->filelength - psf->headindex ; } else if (psf->filelength > 0 && chunk_size > psf->filelength - psf->headindex + 10) { psf_log_printf (psf, "%M : %D (should be %D)\n", marker, chunk_size, psf->filelength - psf->headindex - 8) ; psf->datalength = psf->filelength - psf->headindex - 8 ; } else { psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; /* Subtract the 4 bytes of the 'edit' field above. */ psf->datalength = chunk_size - 4 ; } ; psf_log_printf (psf, " edit : %u\n", k) ; psf->dataoffset = psf->headindex ; if (psf->datalength + psf->dataoffset < psf->filelength) psf->dataend = psf->datalength + psf->dataoffset ; psf_binheader_readf (psf, "j", make_size_t (psf->datalength)) ; have_data = 1 ; break ; case kuki_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; pcaf->alac.kuki_offset = psf_ftell (psf) - 12 ; psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; break ; case pakt_MARKER : if (chunk_size < 24) { psf_log_printf (psf, "%M : %D (should be > 24)\n", marker, chunk_size) ; return SFE_MALFORMED_FILE ; } else if (chunk_size > psf->filelength - psf->headindex) { psf_log_printf (psf, "%M : %D (should be < %D)\n", marker, chunk_size, psf->filelength - psf->headindex) ; return SFE_MALFORMED_FILE ; } else psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; psf_binheader_readf (psf, "E8844", &pcaf->alac.packets, &pcaf->alac.valid_frames, &pcaf->alac.priming_frames, &pcaf->alac.remainder_frames) ; psf_log_printf (psf, " Packets : %D\n" " Valid frames : %D\n" " Priming frames : %d\n" " Remainder frames : %d\n", pcaf->alac.packets, pcaf->alac.valid_frames, pcaf->alac.priming_frames, pcaf->alac.remainder_frames ) ; if (pcaf->alac.packets == 0 && pcaf->alac.valid_frames == 0 && pcaf->alac.priming_frames == 0 && pcaf->alac.remainder_frames == 0) psf_log_printf (psf, "*** 'pakt' chunk header is all zero.\n") ; pcaf->alac.pakt_offset = psf_ftell (psf) - 12 ; psf_binheader_readf (psf, "j", make_size_t (chunk_size) - 24) ; break ; case info_MARKER : if (chunk_size < 4) { psf_log_printf (psf, "%M : %D (should be > 4)\n", marker, chunk_size) ; return SFE_MALFORMED_FILE ; } else if (chunk_size > psf->filelength - psf->headindex) { psf_log_printf (psf, "%M : %D (should be < %D)\n", marker, chunk_size, psf->filelength - psf->headindex) ; return SFE_MALFORMED_FILE ; } ; psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; caf_read_strings (psf, chunk_size) ; break ; default : psf_log_printf (psf, "%M : %D (skipped)\n", marker, chunk_size) ; psf_binheader_readf (psf, "j", make_size_t (chunk_size)) ; break ; } ; if (marker != data_MARKER && chunk_size >= 0xffffff00) break ; if (! psf->sf.seekable && have_data) break ; if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (chunk_size)) { psf_log_printf (psf, "End\n") ; break ; } ; } ; if (have_data == 0) { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ; return SFE_MALFORMED_FILE ; } ; psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0) return SFE_UNSUPPORTED_ENCODING ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / psf->bytewidth ; return 0 ; } /* caf_read_header */
static int caf_read_header (SF_PRIVATE *psf) { DESC_CHUNK desc ; sf_count_t chunk_size ; double srate ; short version, flags ; int marker, k, have_data = 0, error ; memset (&desc, 0, sizeof (desc)) ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "pmE2E2", 0, &marker, &version, &flags) ; psf_log_printf (psf, "%M\n Version : %d\n Flags : %x\n", marker, version, flags) ; if (marker != caff_MARKER) return SFE_CAF_NOT_CAF ; psf_binheader_readf (psf, "mE8b", &marker, &chunk_size, psf->u.ucbuf, 8) ; srate = double64_be_read (psf->u.ucbuf) ; snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), "%5.3f", srate) ; psf_log_printf (psf, "%M : %D\n Sample rate : %s\n", marker, chunk_size, psf->u.cbuf) ; if (marker != desc_MARKER) return SFE_CAF_NO_DESC ; if (chunk_size < SIGNED_SIZEOF (DESC_CHUNK)) { psf_log_printf (psf, "**** Chunk size too small. Should be > 32 bytes.\n") ; return SFE_MALFORMED_FILE ; } ; psf->sf.samplerate = lrint (srate) ; psf_binheader_readf (psf, "mE44444", &desc.fmt_id, &desc.fmt_flags, &desc.pkt_bytes, &desc.pkt_frames, &desc.channels_per_frame, &desc.bits_per_chan) ; psf_log_printf (psf, " Format id : %M\n Format flags : %x\n Bytes / packet : %u\n" " Frames / packet : %u\n Channels / frame : %u\n Bits / channel : %u\n", desc.fmt_id, desc.fmt_flags, desc.pkt_bytes, desc.pkt_frames, desc.channels_per_frame, desc.bits_per_chan) ; if (desc.channels_per_frame > SF_MAX_CHANNELS) { psf_log_printf (psf, "**** Bad channels per frame value %u.\n", desc.channels_per_frame) ; return SFE_MALFORMED_FILE ; } ; if (chunk_size > SIGNED_SIZEOF (DESC_CHUNK)) psf_binheader_readf (psf, "j", (int) (chunk_size - sizeof (DESC_CHUNK))) ; psf->sf.channels = desc.channels_per_frame ; while (have_data == 0 && psf_ftell (psf) < psf->filelength - SIGNED_SIZEOF (marker)) { psf_binheader_readf (psf, "mE8", &marker, &chunk_size) ; switch (marker) { case peak_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; if (chunk_size != CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) { psf_binheader_readf (psf, "j", (int) chunk_size) ; psf_log_printf (psf, "*** File PEAK chunk %D should be %d.\n", chunk_size, CAF_PEAK_CHUNK_SIZE (psf->sf.channels)) ; return SFE_CAF_BAD_PEAK ; } ; if ((psf->peak_info = peak_info_calloc (psf->sf.channels)) == NULL) return SFE_MALLOC_FAILED ; /* read in rest of PEAK chunk. */ psf_binheader_readf (psf, "E4", & (psf->peak_info->edit_number)) ; psf_log_printf (psf, " edit count : %d\n", psf->peak_info->edit_number) ; psf_log_printf (psf, " Ch Position Value\n") ; for (k = 0 ; k < psf->sf.channels ; k++) { sf_count_t position ; float value ; psf_binheader_readf (psf, "Ef8", &value, &position) ; psf->peak_info->peaks [k].value = value ; psf->peak_info->peaks [k].position = position ; snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %-12" PRId64 " %g\n", k, position, value) ; psf_log_printf (psf, psf->u.cbuf) ; } ; psf->peak_info->peak_loc = SF_PEAK_START ; break ; case chan_MARKER : if (chunk_size < 12) { psf_log_printf (psf, "%M : %D (should be >= 12)\n", marker, chunk_size) ; psf_binheader_readf (psf, "j", (int) chunk_size) ; break ; } psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; if ((error = caf_read_chanmap (psf, chunk_size))) return error ; break ; case free_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; psf_binheader_readf (psf, "j", (int) chunk_size) ; break ; case data_MARKER : psf_log_printf (psf, "%M : %D\n", marker, chunk_size) ; psf_binheader_readf (psf, "E4", &k) ; psf_log_printf (psf, " edit : %u\n", k) ; have_data = 1 ; break ; default : psf_log_printf (psf, " %M : %D (skipped)\n", marker, chunk_size) ; psf_binheader_readf (psf, "j", (int) chunk_size) ; break ; } ; } ; if (have_data == 0) { psf_log_printf (psf, "**** Error, could not find 'data' chunk.\n") ; return SFE_MALFORMED_FILE ; } ; psf_log_printf (psf, "End\n") ; psf->dataoffset = psf_ftell (psf) ; psf->datalength = psf->filelength - psf->dataoffset ; psf->endian = (desc.fmt_flags & 2) ? SF_ENDIAN_LITTLE : SF_ENDIAN_BIG ; if ((psf->sf.format = decode_desc_chunk (psf, &desc)) == 0) return SFE_UNSUPPORTED_ENCODING ; if (psf->bytewidth > 0) psf->sf.frames = psf->datalength / psf->bytewidth ; return 0 ; } /* caf_read_header */
static int nist_read_header (SF_PRIVATE *psf) { char psf_header [NIST_HEADER_LENGTH + 2] ; int bitwidth = 0, count, encoding ; unsigned bytes = 0 ; char str [64], *cptr ; long samples ; /* Go to start of file and read in the whole header. */ psf_binheader_readf (psf, "pb", 0, psf_header, NIST_HEADER_LENGTH) ; /* Header is a string, so make sure it is null terminated. */ psf_header [NIST_HEADER_LENGTH] = 0 ; /* Now trim the header after the end marker. */ if ((cptr = strstr (psf_header, "end_head"))) { cptr += strlen ("end_head") + 1 ; cptr [0] = 0 ; } ; if (strstr (psf_header, bad_header) == psf_header) return SFE_NIST_CRLF_CONVERISON ; /* Make sure its a NIST file. */ if (strstr (psf_header, "NIST_1A\n") != psf_header) { psf_log_printf (psf, "Not a NIST file.\n") ; return SFE_NIST_BAD_HEADER ; } ; if (sscanf (psf_header, "NIST_1A\n%d\n", &count) == 1) psf->dataoffset = count ; else { psf_log_printf (psf, "*** Suspicious header length.\n") ; psf->dataoffset = NIST_HEADER_LENGTH ; } ; /* Determine sample encoding, start by assuming PCM. */ encoding = SF_FORMAT_PCM_U8 ; if ((cptr = strstr (psf_header, "sample_coding -s"))) { sscanf (cptr, "sample_coding -s%d %63s", &count, str) ; if (strcmp (str, "pcm") == 0) { /* Correct this later when we find out the bitwidth. */ encoding = SF_FORMAT_PCM_U8 ; } else if (strcmp (str, "alaw") == 0) encoding = SF_FORMAT_ALAW ; else if ((strcmp (str, "ulaw") == 0) || (strcmp (str, "mu-law") == 0)) encoding = SF_FORMAT_ULAW ; else { psf_log_printf (psf, "*** Unknown encoding : %s\n", str) ; encoding = 0 ; } ; } ; if ((cptr = strstr (psf_header, "channel_count -i ")) != NULL) sscanf (cptr, "channel_count -i %d", &(psf->sf.channels)) ; if ((cptr = strstr (psf_header, "sample_rate -i ")) != NULL) sscanf (cptr, "sample_rate -i %d", &(psf->sf.samplerate)) ; if ((cptr = strstr (psf_header, "sample_count -i ")) != NULL) { sscanf (cptr, "sample_count -i %ld", &samples) ; psf->sf.frames = samples ; } ; if ((cptr = strstr (psf_header, "sample_n_bytes -i ")) != NULL) sscanf (cptr, "sample_n_bytes -i %d", &(psf->bytewidth)) ; /* Default endian-ness (for 8 bit, u-law, A-law. */ psf->endian = (CPU_IS_BIG_ENDIAN) ? SF_ENDIAN_BIG : SF_ENDIAN_LITTLE ; /* This is where we figure out endian-ness. */ if ((cptr = strstr (psf_header, "sample_byte_format -s")) && sscanf (cptr, "sample_byte_format -s%u %8s", &bytes, str) == 2) { if (bytes != strlen (str)) psf_log_printf (psf, "Weird sample_byte_format : strlen '%s' != %d\n", str, bytes) ; if (bytes > 1) { if (psf->bytewidth == 0) psf->bytewidth = bytes ; else if (psf->bytewidth - bytes != 0) { psf_log_printf (psf, "psf->bytewidth (%d) != bytes (%d)\n", psf->bytewidth, bytes) ; return SFE_NIST_BAD_ENCODING ; } ; if (strcmp (str, "01") == 0) psf->endian = SF_ENDIAN_LITTLE ; else if (strcmp (str, "10") == 0) psf->endian = SF_ENDIAN_BIG ; else { psf_log_printf (psf, "Weird endian-ness : %s\n", str) ; return SFE_NIST_BAD_ENCODING ; } ; } ; psf->sf.format |= psf->endian ; } ; if ((cptr = strstr (psf_header, "sample_sig_bits -i "))) sscanf (cptr, "sample_sig_bits -i %d", &bitwidth) ; if (strstr (psf_header, "channels_interleaved -s5 FALSE")) { psf_log_printf (psf, "Non-interleaved data unsupported.\n", str) ; return SFE_NIST_BAD_ENCODING ; } ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->datalength = psf->filelength - psf->dataoffset ; psf_fseek (psf, psf->dataoffset, SEEK_SET) ; if (encoding == SF_FORMAT_PCM_U8) { switch (psf->bytewidth) { case 1 : psf->sf.format |= SF_FORMAT_PCM_S8 ; break ; case 2 : psf->sf.format |= SF_FORMAT_PCM_16 ; break ; case 3 : psf->sf.format |= SF_FORMAT_PCM_24 ; break ; case 4 : psf->sf.format |= SF_FORMAT_PCM_32 ; break ; default : break ; } ; } else if (encoding != 0) psf->sf.format |= encoding ; else return SFE_UNIMPLEMENTED ; /* Sanitize psf->sf.format. */ switch (SF_CODEC (psf->sf.format)) { case SF_FORMAT_ULAW : case SF_FORMAT_ALAW : case SF_FORMAT_PCM_U8 : /* Blank out endian bits. */ psf->sf.format = SF_FORMAT_NIST | SF_CODEC (psf->sf.format) ; break ; default : break ; } ; return 0 ; } /* nist_read_header */
static int mat5_read_header (SF_PRIVATE *psf) { char name [32] ; short version, endian ; int type, size, flags1, flags2, rows, cols ; psf_binheader_readf (psf, "pb", 0, psf->u.scbuf, 124) ; psf->u.scbuf [125] = 0 ; if (strlen (psf->u.scbuf) >= 124) return SFE_UNIMPLEMENTED ; if (strstr (psf->u.cbuf, "MATLAB 5.0 MAT-file") == psf->u.cbuf) psf_log_printf (psf, "%s\n", psf->u.scbuf) ; psf_binheader_readf (psf, "E22", &version, &endian) ; if (endian == MI_MARKER) { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; if (CPU_IS_LITTLE_ENDIAN) version = ENDSWAP_SHORT (version) ; } else if (endian == IM_MARKER) { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; if (CPU_IS_BIG_ENDIAN) version = ENDSWAP_SHORT (version) ; } else return SFE_MAT5_BAD_ENDIAN ; if ((CPU_IS_LITTLE_ENDIAN && endian == IM_MARKER) || (CPU_IS_BIG_ENDIAN && endian == MI_MARKER)) version = ENDSWAP_SHORT (version) ; psf_log_printf (psf, "Version : 0x%04X\n", version) ; psf_log_printf (psf, "Endian : 0x%04X => %s\n", endian, (psf->endian == SF_ENDIAN_LITTLE) ? "Little" : "Big") ; /*========================================================*/ psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, "Block\n Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_ARRAY) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_UINT32) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &flags1, &flags2) ; psf_log_printf (psf, " Flg1 : %X Flg2 : %d\n", flags1, flags2) ; psf_binheader_readf (psf, "44", &type, &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (type != MAT5_TYPE_INT32) return SFE_MAT5_NO_BLOCK ; psf_binheader_readf (psf, "44", &rows, &cols) ; psf_log_printf (psf, " Rows : %X Cols : %d\n", rows, cols) ; if (rows != 1 || cols != 1) return SFE_MAT5_SAMPLE_RATE ; psf_binheader_readf (psf, "4", &type) ; if (type == MAT5_TYPE_SCHAR) { psf_binheader_readf (psf, "4", &size) ; psf_log_printf (psf, " Type : %X Size : %d\n", type, size) ; if (size > SIGNED_SIZEOF (name) - 1) { psf_log_printf (psf, "Error : Bad name length.\n") ; return SFE_MAT5_NO_BLOCK ; } ; psf_binheader_readf (psf, "bj", name, size, (8 - (size % 8)) % 8) ; name [size] = 0 ; } else if ((type & 0xFFFF) == MAT5_TYPE_SCHAR) { size = type >> 16 ; if (size > 4) { psf_log_printf (psf, "Error : Bad name length.\n") ; return SFE_MAT5_NO_BLOCK ; } ; psf_log_printf (psf, " Type : %X\n", type) ; psf_binheader_readf (psf, "4", &name) ; name [size] = 0 ; }
static int w64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) { WAV_FMT wav_fmt ; int dword = 0, marker, format = 0 ; sf_count_t chunk_size, bytesread = 0 ; int parsestage = 0, error, done = 0 ; /* Set position to start of file to begin reading header. */ psf_binheader_readf (psf, "p", 0) ; while (! done) { /* Read the 4 byte marker and jump 12 bytes. */ bytesread += psf_binheader_readf (psf, "h", &marker) ; chunk_size = 0 ; switch (marker) { case riff_HASH16 : if (parsestage) return SFE_W64_NO_RIFF ; bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; if (psf->filelength < chunk_size) psf_log_printf (psf, "riff : %d (should be %d)\n", chunk_size, psf->filelength) ; else psf_log_printf (psf, "riff : %d\n", chunk_size) ; parsestage |= HAVE_riff ; break ; case ACID_HASH16: psf_log_printf (psf, "Looks like an ACID file. Exiting.\n") ; return SFE_UNIMPLEMENTED ; case wave_HASH16 : if ((parsestage & HAVE_riff) != HAVE_riff) return SFE_W64_NO_WAVE ; psf_log_printf (psf, "wave\n") ; parsestage |= HAVE_wave ; break ; case fmt_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave)) != (HAVE_riff | HAVE_wave)) return SFE_W64_NO_FMT ; bytesread += psf_binheader_readf (psf, "e8", &chunk_size) ; psf_log_printf (psf, " fmt : %d (0x%X)\n", chunk_size, chunk_size) ; /* size of 16 byte marker and 8 byte chunk_size value. */ chunk_size -= 24 ; if ((error = wav_w64_read_fmt_chunk (psf, &wav_fmt, (int) chunk_size))) return error ; if (chunk_size % 8) psf_binheader_readf (psf, "j", 8 - (chunk_size % 8)) ; format = wav_fmt.format ; parsestage |= HAVE_fmt ; break ; case fact_HASH16: { sf_count_t frames ; psf_binheader_readf (psf, "e88", &chunk_size, &frames) ; psf_log_printf (psf, " fact : 0x%X\n" " frames : %d\n", chunk_size, frames) ; } ; break ; case data_HASH16 : if ((parsestage & (HAVE_riff | HAVE_wave | HAVE_fmt)) != (HAVE_riff | HAVE_wave | HAVE_fmt)) return SFE_W64_NO_DATA ; psf_binheader_readf (psf, "e8", &chunk_size) ; psf->dataoffset = psf_ftell (psf->filedes) ; psf->datalength = chunk_size - 24 ; if (chunk_size % 8) chunk_size += 8 - (chunk_size % 8) ; psf_log_printf (psf, "data : %d (0x%X)\n", chunk_size, psf->datalength) ; parsestage |= HAVE_data ; if (! psf->sf.seekable) break ; /* Seek past data and continue reading header. */ psf_fseek (psf->filedes, chunk_size, SEEK_CUR) ; break ; default : if (psf_ftell (psf->filedes) & 0x0F) { psf_log_printf (psf, " Unknown chunk marker at position %d. Resynching.\n", dword - 4) ; psf_binheader_readf (psf, "j", -3) ; break ; } ; psf_log_printf (psf, "*** Unknown chunk marker : %X. Exiting parser.\n", marker) ; done = SF_TRUE ; break ; } ; /* switch (dword) */ if (! psf->sf.seekable && (parsestage & HAVE_data)) break ; if (psf_ferror (psf->filedes)) { psf_log_printf (psf, "*** Error on file handle. ***\n", marker) ; psf_fclearerr (psf->filedes) ; break ; } ; if (psf_ftell (psf->filedes) >= (int) (psf->filelength - (2 * sizeof (dword)))) break ; if (psf->logindex >= sizeof (psf->logbuffer) - 2) return SFE_LOG_OVERRUN ; } ; /* while (1) */ if (! psf->dataoffset) return SFE_W64_NO_DATA ; psf->endian = SF_ENDIAN_LITTLE ; /* All WAV files are little endian. */ psf_fseek (psf->filedes, psf->dataoffset, SEEK_SET) ; psf->close = w64_close ; if (psf->blockwidth) { if (psf->filelength - psf->dataoffset < psf->datalength) psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; else psf->sf.frames = psf->datalength / psf->blockwidth ; } ; switch (format) { case WAVE_FORMAT_PCM : case WAVE_FORMAT_EXTENSIBLE : psf->sf.format = SF_FORMAT_W64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ; break ; case WAVE_FORMAT_MULAW : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ULAW) ; break ; case WAVE_FORMAT_ALAW : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_ALAW) ; break ; case WAVE_FORMAT_MS_ADPCM : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_MS_ADPCM) ; *blockalign = wav_fmt.msadpcm.blockalign ; *framesperblock = wav_fmt.msadpcm.samplesperblock ; break ; case WAVE_FORMAT_IMA_ADPCM : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_IMA_ADPCM) ; *blockalign = wav_fmt.ima.blockalign ; *framesperblock = wav_fmt.ima.samplesperblock ; break ; case WAVE_FORMAT_GSM610 : psf->sf.format = (SF_FORMAT_W64 | SF_FORMAT_GSM610) ; break ; case WAVE_FORMAT_IEEE_FLOAT : psf->sf.format = SF_FORMAT_W64 ; psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; break ; default : return SFE_UNIMPLEMENTED ; } ; return 0 ; } /* w64_read_header */
static int ircam_read_header (SF_PRIVATE *psf) { unsigned int marker, encoding ; float samplerate ; int error = SFE_NO_ERROR ; psf_binheader_readf (psf, "epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ; if (((marker & IRCAM_BE_MASK) != IRCAM_BE_MARKER) && ((marker & IRCAM_LE_MASK) != IRCAM_LE_MARKER)) { psf_log_printf (psf, "marker: 0x%X\n", marker) ; return SFE_IRCAM_NO_MARKER ; } ; psf->endian = SF_ENDIAN_LITTLE ; if (psf->sf.channels > SF_MAX_CHANNELS) { psf_binheader_readf (psf, "Epmf44", 0, &marker, &samplerate, &(psf->sf.channels), &encoding) ; /* Sanity checking for endian-ness detection. */ if (psf->sf.channels > SF_MAX_CHANNELS) { psf_log_printf (psf, "marker: 0x%X\n", marker) ; return SFE_IRCAM_BAD_CHANNELS ; } ; psf->endian = SF_ENDIAN_BIG ; } ; psf_log_printf (psf, "marker: 0x%X\n", marker) ; psf->sf.samplerate = (int) samplerate ; psf_log_printf (psf, " Sample Rate : %d\n" " Channels : %d\n" " Encoding : %X => %s\n", psf->sf.samplerate, psf->sf.channels, encoding, get_encoding_str (encoding)) ; switch (encoding) { case IRCAM_PCM_16 : psf->bytewidth = 2 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_16 ; break ; case IRCAM_PCM_32 : psf->bytewidth = 4 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_PCM_32 ; break ; case IRCAM_FLOAT : psf->bytewidth = 4 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_FLOAT ; break ; case IRCAM_ALAW : psf->bytewidth = 1 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ALAW ; break ; case IRCAM_ULAW : psf->bytewidth = 1 ; psf->blockwidth = psf->sf.channels * psf->bytewidth ; psf->sf.format = SF_FORMAT_IRCAM | SF_FORMAT_ULAW ; break ; default : error = SFE_IRCAM_UNKNOWN_FORMAT ; break ; } ; if (psf->endian == SF_ENDIAN_BIG) psf->sf.format |= SF_ENDIAN_BIG ; else psf->sf.format |= SF_ENDIAN_LITTLE ; if (error) return error ; psf->dataoffset = IRCAM_DATA_OFFSET ; psf->datalength = psf->filelength - psf->dataoffset ; if (psf->sf.frames == 0 && psf->blockwidth) psf->sf.frames = psf->datalength / psf->blockwidth ; psf_log_printf (psf, " Samples : %d\n", psf->sf.frames) ; psf_binheader_readf (psf, "p", IRCAM_DATA_OFFSET) ; return 0 ; } /* ircam_read_header */
static int mat4_read_header (SF_PRIVATE *psf) { int marker, rows, cols, imag ; unsigned namesize ; double value ; const char *marker_str ; char name [64] ; psf_binheader_readf (psf, "pm", 0, &marker) ; /* MAT4 file must start with a double for the samplerate. */ if (marker == MAT4_BE_DOUBLE) { psf->endian = psf->rwf_endian = SF_ENDIAN_BIG ; marker_str = "big endian double" ; } else if (marker == MAT4_LE_DOUBLE) { psf->endian = psf->rwf_endian = SF_ENDIAN_LITTLE ; marker_str = "little endian double" ; } else return SFE_UNIMPLEMENTED ; psf_log_printf (psf, "GNU Octave 2.0 / MATLAB v4.2 format\nMarker : %s\n", marker_str) ; psf_binheader_readf (psf, "444", &rows, &cols, &imag) ; psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ; psf_binheader_readf (psf, "4", &namesize) ; if (namesize >= SIGNED_SIZEOF (name)) return SFE_MAT4_BAD_NAME ; psf_binheader_readf (psf, "b", name, namesize) ; name [namesize] = 0 ; psf_log_printf (psf, " Name : %s\n", name) ; psf_binheader_readf (psf, "d", &value) ; snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " Value : %f\n", value) ; psf_log_printf (psf, psf->u.cbuf) ; if ((rows != 1) || (cols != 1)) return SFE_MAT4_NO_SAMPLERATE ; psf->sf.samplerate = (int)lrint(value); // kengo: /* Now write out the audio data. */ psf_binheader_readf (psf, "m", &marker) ; psf_log_printf (psf, "Marker : %s\n", mat4_marker_to_str (marker)) ; psf_binheader_readf (psf, "444", &rows, &cols, &imag) ; psf_log_printf (psf, " Rows : %d\n Cols : %d\n Imag : %s\n", rows, cols, imag ? "True" : "False") ; psf_binheader_readf (psf, "4", &namesize) ; if (namesize >= SIGNED_SIZEOF (name)) return SFE_MAT4_BAD_NAME ; psf_binheader_readf (psf, "b", name, namesize) ; name [namesize] = 0 ; psf_log_printf (psf, " Name : %s\n", name) ; psf->dataoffset = psf_ftell (psf) ; if (rows == 0 && cols == 0) { psf_log_printf (psf, "*** Error : zero channel count.\n") ; return SFE_CHANNEL_COUNT_ZERO ; } ; psf->sf.channels = rows ; psf->sf.frames = cols ; psf->sf.format = psf->endian | SF_FORMAT_MAT4 ; switch (marker) { case MAT4_BE_DOUBLE : case MAT4_LE_DOUBLE : psf->sf.format |= SF_FORMAT_DOUBLE ; psf->bytewidth = 8 ; break ; case MAT4_BE_FLOAT : case MAT4_LE_FLOAT : psf->sf.format |= SF_FORMAT_FLOAT ; psf->bytewidth = 4 ; break ; case MAT4_BE_PCM_32 : case MAT4_LE_PCM_32 : psf->sf.format |= SF_FORMAT_PCM_32 ; psf->bytewidth = 4 ; break ; case MAT4_BE_PCM_16 : case MAT4_LE_PCM_16 : psf->sf.format |= SF_FORMAT_PCM_16 ; psf->bytewidth = 2 ; break ; default : psf_log_printf (psf, "*** Error : Bad marker %08X\n", marker) ; return SFE_UNIMPLEMENTED ; } ; if ((psf->filelength - psf->dataoffset) < psf->sf.channels * psf->sf.frames * psf->bytewidth) { psf_log_printf (psf, "*** File seems to be truncated. %D <--> %D\n", psf->filelength - psf->dataoffset, psf->sf.channels * psf->sf.frames * psf->bytewidth) ; } else if ((psf->filelength - psf->dataoffset) > psf->sf.channels * psf->sf.frames * psf->bytewidth) psf->dataend = psf->dataoffset + rows * cols * psf->bytewidth ; psf->datalength = psf->filelength - psf->dataoffset - psf->dataend ; psf->sf.sections = 1 ; return 0 ; } /* mat4_read_header */
static int caf_read_strings (SF_PRIVATE * psf, sf_count_t chunk_size) { //char buf [chunk_size - 4] ; char *buf = (char*)malloc(chunk_size-4); char *key, *value ; uint32_t count, hash ; psf_binheader_readf (psf, "E4b", &count, buf, make_size_t (chunk_size - 4)) ; psf_log_printf (psf, " count: %u\n", count) ; /* Force terminate `buf` to make sure. */ buf [chunk_size-4 - 1] = 0 ; for (key = buf ; key < buf + chunk_size-4 ; ) { value = key + strlen (key) + 1 ; if (value > buf + chunk_size-4) break ; psf_log_printf (psf, " %-12s : %s\n", key, value) ; hash = string_hash32 (key) ; switch (hash) { case 0xC4861943 : /* 'title' */ psf_store_string (psf, SF_STR_TITLE, value) ; break ; case 0xAD47A394 : /* 'software' */ psf_store_string (psf, SF_STR_SOFTWARE, value) ; break ; case 0x5D178E2A : /* 'copyright' */ psf_store_string (psf, SF_STR_COPYRIGHT, value) ; break ; case 0x60E4D0C8 : /* 'artist' */ psf_store_string (psf, SF_STR_ARTIST, value) ; break ; case 0x83B5D16A : /* 'genre' */ psf_store_string (psf, SF_STR_GENRE, value) ; break ; case 0x15E5FC88 : /* 'comment' */ case 0x7C297D5B : /* 'comments' */ psf_store_string (psf, SF_STR_COMMENT, value) ; break ; case 0x24A7C347 : /* 'tracknumber' */ psf_store_string (psf, SF_STR_TRACKNUMBER, value) ; break ; case 0x50A31EB7 : /* 'date' */ psf_store_string (psf, SF_STR_DATE, value) ; break ; case 0x6583545A : /* 'album' */ psf_store_string (psf, SF_STR_ALBUM, value) ; break ; case 0xE7C64B6C : /* 'license' */ psf_store_string (psf, SF_STR_LICENSE, value) ; break ; default : psf_log_printf (psf, " Unhandled hash 0x%x : /* '%s' */\n", hash, key) ; break ; } ; key = value + strlen (value) + 1 ; } ; free(buf); return 0 ; }
int wav_w64_read_fmt_chunk (SF_PRIVATE *psf, int fmtsize) { WAV_PRIVATE * wpriv ; WAV_FMT *wav_fmt ; int bytesread, k, bytespersec = 0 ; if ((wpriv = psf->container_data) == NULL) return SFE_INTERNAL ; wav_fmt = &wpriv->wav_fmt ; memset (wav_fmt, 0, sizeof (WAV_FMT)) ; if (fmtsize < 16) return SFE_WAV_FMT_SHORT ; /* assume psf->rwf_endian is already properly set */ /* Read the minimal WAV file header here. */ bytesread = psf_binheader_readf (psf, "224422", &(wav_fmt->format), &(wav_fmt->min.channels), &(wav_fmt->min.samplerate), &(wav_fmt->min.bytespersec), &(wav_fmt->min.blockalign), &(wav_fmt->min.bitwidth)) ; psf_log_printf (psf, " Format : 0x%X => %s\n", wav_fmt->format, wav_w64_format_str (wav_fmt->format)) ; psf_log_printf (psf, " Channels : %d\n", wav_fmt->min.channels) ; psf_log_printf (psf, " Sample Rate : %d\n", wav_fmt->min.samplerate) ; psf_log_printf (psf, " Block Align : %d\n", wav_fmt->min.blockalign) ; if (wav_fmt->min.blockalign == 0) { psf_log_printf (psf, "*** Error : wav_fmt->min.blockalign should not be zero.\n") ; return SFE_INTERNAL ; } ; if (wav_fmt->format == WAVE_FORMAT_PCM && wav_fmt->min.bitwidth == 24 && wav_fmt->min.blockalign == 4 * wav_fmt->min.channels) { psf_log_printf (psf, " Bit Width : 24\n") ; psf_log_printf (psf, "\n" " Ambiguous information in 'fmt ' chunk. Possibile file types:\n" " 0) Invalid IEEE float file generated by Syntrillium's Cooledit!\n" " 1) File generated by ALSA's arecord containing 24 bit samples in 32 bit containers.\n" " 2) 24 bit file with incorrect Block Align value.\n" "\n") ; wpriv->fmt_is_broken = 1 ; } else if (wav_fmt->min.bitwidth == 0) { switch (wav_fmt->format) { case WAVE_FORMAT_GSM610 : case WAVE_FORMAT_IPP_ITU_G_723_1 : psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; break ; default : psf_log_printf (psf, " Bit Width : %d (should not be 0)\n", wav_fmt->min.bitwidth) ; } } else { switch (wav_fmt->format) { case WAVE_FORMAT_GSM610 : case WAVE_FORMAT_IPP_ITU_G_723_1 : psf_log_printf (psf, " Bit Width : %d (should be 0)\n", wav_fmt->min.bitwidth) ; break ; default : psf_log_printf (psf, " Bit Width : %d\n", wav_fmt->min.bitwidth) ; } } ; psf->sf.samplerate = wav_fmt->min.samplerate ; psf->sf.frames = 0 ; /* Correct this when reading data chunk. */ psf->sf.channels = wav_fmt->min.channels ; switch (wav_fmt->format) { case WAVE_FORMAT_PCM : case WAVE_FORMAT_IEEE_FLOAT : bytespersec = wav_fmt->min.samplerate * wav_fmt->min.blockalign ; if (wav_fmt->min.bytespersec != (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; psf->bytewidth = BITWIDTH2BYTES (wav_fmt->min.bitwidth) ; break ; case WAVE_FORMAT_ALAW : case WAVE_FORMAT_MULAW : if (wav_fmt->min.bytespersec / wav_fmt->min.blockalign != wav_fmt->min.samplerate) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, wav_fmt->min.samplerate * wav_fmt->min.blockalign) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; psf->bytewidth = 1 ; if (fmtsize >= 18) { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->size20.extrabytes)) ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->size20.extrabytes) ; } ; break ; case WAVE_FORMAT_IMA_ADPCM : if (wav_fmt->min.bitwidth != 4) return SFE_WAV_ADPCM_NOT4BIT ; if (wav_fmt->min.channels < 1 || wav_fmt->min.channels > 2) return SFE_WAV_ADPCM_CHANNELS ; bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->ima.extrabytes), &(wav_fmt->ima.samplesperblock)) ; bytespersec = (wav_fmt->ima.samplerate * wav_fmt->ima.blockalign) / wav_fmt->ima.samplesperblock ; if (wav_fmt->ima.bytespersec != (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ima.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ima.bytespersec) ; psf->bytewidth = 2 ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->ima.extrabytes) ; psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->ima.samplesperblock) ; break ; case WAVE_FORMAT_MS_ADPCM : if (wav_fmt->msadpcm.bitwidth != 4) return SFE_WAV_ADPCM_NOT4BIT ; if (wav_fmt->msadpcm.channels < 1 || wav_fmt->msadpcm.channels > 2) return SFE_WAV_ADPCM_CHANNELS ; bytesread += psf_binheader_readf (psf, "222", &(wav_fmt->msadpcm.extrabytes), &(wav_fmt->msadpcm.samplesperblock), &(wav_fmt->msadpcm.numcoeffs)) ; bytespersec = (wav_fmt->min.samplerate * wav_fmt->min.blockalign) / wav_fmt->msadpcm.samplesperblock ; if (wav_fmt->min.bytespersec == (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->min.bytespersec) ; else if (wav_fmt->min.bytespersec == (wav_fmt->min.samplerate / wav_fmt->msadpcm.samplesperblock) * wav_fmt->min.blockalign) psf_log_printf (psf, " Bytes/sec : %d (should be %d (MS BUG!))\n", wav_fmt->min.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->min.bytespersec, bytespersec) ; psf->bytewidth = 2 ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->msadpcm.extrabytes) ; psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->msadpcm.samplesperblock) ; if (wav_fmt->msadpcm.numcoeffs > ARRAY_LEN (wav_fmt->msadpcm.coeffs)) { psf_log_printf (psf, " No. of Coeffs : %d (should be <= %d)\n", wav_fmt->msadpcm.numcoeffs, ARRAY_LEN (wav_fmt->msadpcm.coeffs)) ; wav_fmt->msadpcm.numcoeffs = ARRAY_LEN (wav_fmt->msadpcm.coeffs) ; } else psf_log_printf (psf, " No. of Coeffs : %d\n", wav_fmt->msadpcm.numcoeffs) ; psf_log_printf (psf, " Index Coeffs1 Coeffs2\n") ; for (k = 0 ; k < wav_fmt->msadpcm.numcoeffs ; k++) { bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->msadpcm.coeffs [k].coeff1), &(wav_fmt->msadpcm.coeffs [k].coeff2)) ; snprintf (psf->u.cbuf, sizeof (psf->u.cbuf), " %2d %7d %7d\n", k, wav_fmt->msadpcm.coeffs [k].coeff1, wav_fmt->msadpcm.coeffs [k].coeff2) ; psf_log_printf (psf, psf->u.cbuf) ; } ; break ; case WAVE_FORMAT_GSM610 : if (wav_fmt->gsm610.channels != 1 || wav_fmt->gsm610.blockalign != 65) return SFE_WAV_GSM610_FORMAT ; bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->gsm610.extrabytes), &(wav_fmt->gsm610.samplesperblock)) ; if (wav_fmt->gsm610.samplesperblock != 320) return SFE_WAV_GSM610_FORMAT ; bytespersec = (wav_fmt->gsm610.samplerate * wav_fmt->gsm610.blockalign) / wav_fmt->gsm610.samplesperblock ; if (wav_fmt->gsm610.bytespersec != (unsigned) bytespersec) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->gsm610.bytespersec, bytespersec) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->gsm610.bytespersec) ; psf->bytewidth = 2 ; psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->gsm610.extrabytes) ; psf_log_printf (psf, " Samples/Block : %d\n", wav_fmt->gsm610.samplesperblock) ; break ; case WAVE_FORMAT_EXTENSIBLE : if (wav_fmt->ext.bytespersec / wav_fmt->ext.blockalign != wav_fmt->ext.samplerate) psf_log_printf (psf, " Bytes/sec : %d (should be %d)\n", wav_fmt->ext.bytespersec, wav_fmt->ext.samplerate * wav_fmt->ext.blockalign) ; else psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->ext.bytespersec) ; bytesread += psf_binheader_readf (psf, "224", &(wav_fmt->ext.extrabytes), &(wav_fmt->ext.validbits), &(wav_fmt->ext.channelmask)) ; psf_log_printf (psf, " Valid Bits : %d\n", wav_fmt->ext.validbits) ; psf_log_printf (psf, " Channel Mask : 0x%X\n", wav_fmt->ext.channelmask) ; bytesread += psf_binheader_readf (psf, "422", &(wav_fmt->ext.esf.esf_field1), &(wav_fmt->ext.esf.esf_field2), &(wav_fmt->ext.esf.esf_field3)) ; /* compare the esf_fields with each known GUID? and print? */ psf_log_printf (psf, " Subformat\n") ; psf_log_printf (psf, " esf_field1 : 0x%X\n", wav_fmt->ext.esf.esf_field1) ; psf_log_printf (psf, " esf_field2 : 0x%X\n", wav_fmt->ext.esf.esf_field2) ; psf_log_printf (psf, " esf_field3 : 0x%X\n", wav_fmt->ext.esf.esf_field3) ; psf_log_printf (psf, " esf_field4 : ") ; for (k = 0 ; k < 8 ; k++) { bytesread += psf_binheader_readf (psf, "1", &(wav_fmt->ext.esf.esf_field4 [k])) ; psf_log_printf (psf, "0x%X ", wav_fmt->ext.esf.esf_field4 [k] & 0xFF) ; } ; psf_log_printf (psf, "\n") ; psf->bytewidth = BITWIDTH2BYTES (wav_fmt->ext.bitwidth) ; /* Compare GUIDs for known ones. */ if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_PCM)) { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ; psf_log_printf (psf, " format : pcm\n") ; } else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MS_ADPCM)) { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM) ; psf_log_printf (psf, " format : ms adpcm\n") ; } else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_IEEE_FLOAT)) { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ; psf_log_printf (psf, " format : IEEE float\n") ; } else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_ALAW)) { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ALAW) ; psf_log_printf (psf, " format : A-law\n") ; } else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_MULAW)) { psf->sf.format = (SF_FORMAT_WAVEX | SF_FORMAT_ULAW) ; psf_log_printf (psf, " format : u-law\n") ; } else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM)) { psf->sf.format = SF_FORMAT_WAVEX | u_bitwidth_to_subformat (psf->bytewidth * 8) ; psf_log_printf (psf, " format : pcm (Ambisonic B)\n") ; wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ; } else if (wavex_guid_equal (&wav_fmt->ext.esf, &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT)) { psf->sf.format = SF_FORMAT_WAVEX | ((psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT) ; psf_log_printf (psf, " format : IEEE float (Ambisonic B)\n") ; wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ; } else return SFE_UNIMPLEMENTED ; break ; case WAVE_FORMAT_G721_ADPCM : psf_log_printf (psf, " Bytes/sec : %d\n", wav_fmt->g72x.bytespersec) ; if (fmtsize >= 20) { bytesread += psf_binheader_readf (psf, "22", &(wav_fmt->g72x.extrabytes), &(wav_fmt->g72x.auxblocksize)) ; if (wav_fmt->g72x.extrabytes == 0) psf_log_printf (psf, " Extra Bytes : %d (should be 2)\n", wav_fmt->g72x.extrabytes) ; else psf_log_printf (psf, " Extra Bytes : %d\n", wav_fmt->g72x.extrabytes) ; psf_log_printf (psf, " Aux Blk Size : %d\n", wav_fmt->g72x.auxblocksize) ; } else if (fmtsize == 18) { bytesread += psf_binheader_readf (psf, "2", &(wav_fmt->g72x.extrabytes)) ; psf_log_printf (psf, " Extra Bytes : %d%s\n", wav_fmt->g72x.extrabytes, wav_fmt->g72x.extrabytes != 0 ? " (should be 0)" : "") ; } else psf_log_printf (psf, "*** 'fmt ' chunk should be bigger than this!\n") ; break ; default : psf_log_printf (psf, "*** No 'fmt ' chunk dumper for this format!\n") ; return SFE_WAV_BAD_FMT ; } ; if (bytesread > fmtsize) { psf_log_printf (psf, "*** wav_w64_read_fmt_chunk (bytesread > fmtsize)\n") ; return SFE_WAV_BAD_FMT ; } else psf_binheader_readf (psf, "j", fmtsize - bytesread) ; psf->blockwidth = wav_fmt->min.channels * psf->bytewidth ; return 0 ; } /* wav_w64_read_fmt_chunk */