Torque3D/Engine/lib/libsndfile/src/txw.c
marauder2k7 a745fc3757 Initial commit
added libraries:
opus
flac
libsndfile

updated:
libvorbis
libogg
openal

- Everything works as expected for now. Bare in mind libsndfile needed the check for whether or not it could find the xiph libraries removed in order for this to work.
2024-03-21 17:33:47 +00:00

377 lines
9.6 KiB
C

/*
** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
**
** This program is free software; you can redistribute it and/or modify
** it under the terms of the GNU Lesser General Public License as published by
** the Free Software Foundation; either version 2.1 of the License, or
** (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU Lesser General Public License for more details.
**
** You should have received a copy of the GNU Lesser General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/*===========================================================================
** Yamaha TX16 Sampler Files.
**
** This header parser was written using information from the SoX source code
** and trial and error experimentation. The code here however is all original.
*/
#include "sfconfig.h"
#include <stdio.h>
#include <fcntl.h>
#include <string.h>
#include <ctype.h>
#include "sndfile.h"
#include "sfendian.h"
#include "common.h"
#if (ENABLE_EXPERIMENTAL_CODE == 0)
int
txw_open (SF_PRIVATE *psf)
{ if (psf)
return SFE_UNIMPLEMENTED ;
return 0 ;
} /* txw_open */
#else
/*------------------------------------------------------------------------------
** Markers.
*/
#define TXW_DATA_OFFSET 32
#define TXW_LOOPED 0x49
#define TXW_NO_LOOP 0xC9
/*------------------------------------------------------------------------------
** Private static functions.
*/
static int txw_read_header (SF_PRIVATE *psf) ;
static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
static sf_count_t txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
/*------------------------------------------------------------------------------
** Public functions.
*/
/*
* ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha
* ftp://ftp.t0.or.at/pub/sound/tx16w/faq/tx16w.tec
* http://www.t0.or.at/~mpakesch/tx16w/
*
* from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith)
* char filetype[6] "LM8953"
* nulls[10],
* dummy_aeg[6]
* format 0x49 = looped, 0xC9 = non-looped
* sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz
* atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16,
* depending on [5] but to heck with it
* rpt_length[3] (these are for looped samples, attack and loop lengths)
* unused[2]
*/
typedef struct
{ unsigned char format, srate, sr2, sr3 ;
unsigned short srhash ;
unsigned int attacklen, repeatlen ;
} TXW_HEADER ;
#define ERROR_666 666
int
txw_open (SF_PRIVATE *psf)
{ int error ;
if (psf->file.mode != SFM_READ)
return SFE_UNIMPLEMENTED ;
if ((error = txw_read_header (psf)))
return error ;
if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset)
return SFE_BAD_SEEK ;
psf->read_short = txw_read_s ;
psf->read_int = txw_read_i ;
psf->read_float = txw_read_f ;
psf->read_double = txw_read_d ;
psf->seek = txw_seek ;
return 0 ;
} /* txw_open */
/*------------------------------------------------------------------------------
*/
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 sf_count_t
txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
unsigned char *ucptr ;
short sample ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
bufferlen = sizeof (ubuf.cbuf) / 3 ;
bufferlen -= (bufferlen & 1) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
ucptr = ubuf.ucbuf ;
for (k = 0 ; k < readcount ; k += 2)
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
ptr [total + k] = sample ;
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
ptr [total + k + 1] = sample ;
ucptr += 3 ;
} ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* txw_read_s */
static sf_count_t
txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
unsigned char *ucptr ;
short sample ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
bufferlen = sizeof (ubuf.cbuf) / 3 ;
bufferlen -= (bufferlen & 1) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
ucptr = ubuf.ucbuf ;
for (k = 0 ; k < readcount ; k += 2)
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
ptr [total + k] = sample << 16 ;
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
ptr [total + k + 1] = sample << 16 ;
ucptr += 3 ;
} ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* txw_read_i */
static sf_count_t
txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
unsigned char *ucptr ;
short sample ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
float normfact ;
if (psf->norm_float == SF_TRUE)
normfact = 1.0 / 0x8000 ;
else
normfact = 1.0 / 0x10 ;
bufferlen = sizeof (ubuf.cbuf) / 3 ;
bufferlen -= (bufferlen & 1) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
ucptr = ubuf.ucbuf ;
for (k = 0 ; k < readcount ; k += 2)
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
ptr [total + k] = normfact * sample ;
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
ptr [total + k + 1] = normfact * sample ;
ucptr += 3 ;
} ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* txw_read_f */
static sf_count_t
txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
{ BUF_UNION ubuf ;
unsigned char *ucptr ;
short sample ;
int k, bufferlen, readcount, count ;
sf_count_t total = 0 ;
double normfact ;
if (psf->norm_double == SF_TRUE)
normfact = 1.0 / 0x8000 ;
else
normfact = 1.0 / 0x10 ;
bufferlen = sizeof (ubuf.cbuf) / 3 ;
bufferlen -= (bufferlen & 1) ;
while (len > 0)
{ readcount = (len >= bufferlen) ? bufferlen : len ;
count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
ucptr = ubuf.ucbuf ;
for (k = 0 ; k < readcount ; k += 2)
{ sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
ptr [total + k] = normfact * sample ;
sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
ptr [total + k + 1] = normfact * sample ;
ucptr += 3 ;
} ;
total += count ;
len -= readcount ;
} ;
return total ;
} /* txw_read_d */
static sf_count_t
txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
{ if (psf && mode)
return offset ;
return 0 ;
} /* txw_seek */
#endif