1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376
|
/* Yamaha TX-16W sampler file support
*
* May 20, 1993
* Copyright 1993 Rob Talley (rob@aii.com)
* This source code is freely redistributable and may be used for
* any purpose. This copyright notice and the following copyright
* notice must be maintained intact. No warranty whatsoever is
* provided. This code is furnished AS-IS as a component of the
* larger work Copyright 1991 Lance Norskog and Sundry Contributors.
* Much appreciation to ross-c for his sampConv utility for SGI/IRIX
* from where these methods were derived.
*
* Jan 24, 1994
* Pat McElhatton, HP Media Technology Lab <patmc@apollo.hp.com>
* Handles reading of files which do not have the sample rate field
* set to one of the expected by looking at some other bytes in the
* attack/loop length fields, and defaulting to 33kHz if the sample
* rate is still unknown.
*
* January 12, 1995
* Copyright 1995 Mark Lakata (lakata@physics.berkeley.edu)
* Additions to tx16w.c SOX driver. This version writes as well as
* reads TX16W format.
*
* July 31, 1998
* Cleaned up by Leigh Smith (leigh@psychokiller.dialix.oz.au)
* for incorporation into the main sox distribution.
*
* September 24, 1998
* Forced output to mono signed words to match input. It was basically
* doing this anyways but now the user will see a display that its being
* overriding. cbagwell@sprynet.com
*
*/
#define TXMAXLEN 0x3FF80
/*
* Sound Tools skeleton file format driver.
*/
#include <stdio.h>
#include <string.h>
#include "st.h"
/* Private data for TX16 file */
typedef struct txwstuff {
LONG rest; /* bytes remaining in sample file */
} *txw_t;
IMPORT float volume, amplitude;
IMPORT int summary, verbose;
struct WaveHeader_ {
char filetype[6]; /* = "LM8953", */
unsigned char
nulls[10],
dummy_aeg[6], /* space for the AEG (never mind this) */
format, /* 0x49 = looped, 0xC9 = non-looped */
sample_rate, /* 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz */
atc_length[3], /* I'll get to this... */
rpt_length[3],
unused[2]; /* set these to null, to be on the safe side */
} ;
static unsigned char magic1[4] = {0, 0x06, 0x10, 0xF6};
static unsigned char magic2[4] = {0, 0x52, 0x00, 0x52};
static LONG tx16w_len=0;
static LONG writedone=0;
/*
* Do anything required before you start reading samples.
* Read file header.
* Find out sampling rate,
* size and style of samples,
* mono/stereo/quad.
*/
void txwstartread(ft)
ft_t ft;
{
int c;
char filetype[7];
char format;
char sample_rate;
LONG num_samp_bytes = 0;
char dummy;
char gunk[8];
int blewIt;
txw_t sk = (txw_t) ft->priv;
/* If you need to seek around the input file. */
if (! ft->seekable)
fail("txw input file must be a file, not a pipe");
/* This is dumb but portable, just count the bytes til EOF */
while ( getc(ft->fp) != EOF )
num_samp_bytes++;
num_samp_bytes -= 32; /* calculate num samples by sub header size */
fseek(ft->fp,0L,0); /* rewind file */
sk->rest = num_samp_bytes; /* set how many sample bytes to read */
/* first 6 bytes are file type ID LM8953 */
filetype[0] = getc(ft->fp);
filetype[1] = getc(ft->fp);
filetype[2] = getc(ft->fp);
filetype[3] = getc(ft->fp);
filetype[4] = getc(ft->fp);
filetype[5] = getc(ft->fp);
filetype[6] = '\0';
for( c = 16; c > 0 ; c-- ) /* Discard next 16 bytes */
dummy = getc(ft->fp); /* they have no meaning here */
format = getc(ft->fp);
sample_rate = getc(ft->fp);
/*
* save next 8 bytes - if sample rate is 0, then we need
* to look at gunk[2] and gunk[5] to get real rate
*/
for( c = 0; c < 8; c++ )
gunk[c] = getc(ft->fp);
/*
* We should now be pointing at start of raw sample data in file
*/
/* Check to make sure we got a good filetype ID from file */
report("Found header filetype %s",filetype);
if(strcmp(filetype,"LM8953"))
fail("Invalid filetype ID in input file header, != LM8953");
/*
* Set up the sample rate as indicated by the header
*/
switch( sample_rate ) {
case 1:
ft->info.rate = 33000;
break;
case 2:
ft->info.rate = 50000;
break;
case 3:
ft->info.rate = 16000;
break;
default:
blewIt = 1;
switch( gunk[2] & 0xFE ) {
case 0x06:
if ( (gunk[5] & 0xFE) == 0x52 ) {
blewIt = 0;
ft->info.rate = 33000;
}
break;
case 0x10:
if ( (gunk[5] & 0xFE) == 0x00 ) {
blewIt = 0;
ft->info.rate = 50000;
}
break;
case 0xF6:
if ( (gunk[5] & 0xFE) == 0x52 ) {
blewIt = 0;
ft->info.rate = 16000;
}
break;
}
if ( blewIt ) {
report("Invalid sample rate identifier found %d", (int)sample_rate);
ft->info.rate = 33000;
}
}
report("Sample rate = %ld",ft->info.rate);
ft->info.channels = 1 ; /* not sure about stereo sample data yet ??? */
ft->info.size = WORD; /* this is close enough */
ft->info.style = SIGN2;
}
/*
* Read up to len samples from file.
* Convert to signed LONGs.
* Place in buf[].
* Return number of samples read.
*/
LONG txwread(ft, buf, len)
ft_t ft;
LONG *buf, len;
{
txw_t sk = (txw_t) ft->priv;
int done = 0;
unsigned char uc1,uc2,uc3;
unsigned short s1,s2;
/*
* This gets called by the top level 'process' routine.
* We will essentially get called with a buffer pointer
* and a max length to read. Graciously, it is always
* an even amount so we don't have to worry about
* hanging onto the left over odd samples since there
* won't be any. Something to look out for though :-(
* We return the number of samples we read.
* We will get called over and over again until we return
* 0 bytes read.
*/
/*
* This is ugly but it's readable!
* Read three bytes from stream, then decompose these into
* two unsigned short samples.
* TCC 3.0 appeared to do unwanted things, so we really specify
* exactly what we want to happen.
* Convert unsigned short to LONG then shift up the result
* so that the 12-bit sample lives in the most significant
* 12-bits of the LONG.
* This gets our two samples into the internal format which we
* deposit into the given buffer and adjust our counts respectivly.
*/
for(done = 0; done < len; ) {
if(sk->rest <= 0) break; /* Finished reading from file? */
uc1 = (unsigned char)getc(ft->fp); /* read the three bytes */
uc2 = (unsigned char)getc(ft->fp);
uc3 = (unsigned char)getc(ft->fp);
sk->rest -= 3; /* adjust remaining for bytes we just read */
s1 = (unsigned short) (uc1 << 4) | (((uc2 >> 4) & 017));
s2 = (unsigned short) (uc3 << 4) | (( uc2 & 017 ));
*buf = (LONG) s1;
*buf = (*buf << 20);
buf++; /* sample one is done */
*buf = (LONG) s2;
*buf = (*buf << 20);
buf++; /* sample two is done */
done += 2; /* adjust converted & stored sample count */
}
return done;
}
/*
* Do anything required when you stop reading samples.
* Don't close input file!
*/
void txwstopread(ft)
ft_t ft;
{
}
void txwstartwrite(ft)
ft_t ft;
{
struct WaveHeader_ WH;
report("tx16w selected output");
if (ft->info.channels != 1)
report("tx16w is overriding output format to 1 channel.");
ft->info.channels = 1 ; /* not sure about stereo sample data yet ??? */
if (ft->info.size != WORD || ft->info.style != SIGN2)
report("tx16w is overriding output format to size Signed Word format.");
ft->info.size = WORD; /* this is close enough */
ft->info.style = SIGN2;
/* If you have to seek around the output file */
if (! ft->seekable)
fail("Output .txw file must be a file, not a pipe");
/* dummy numbers, just for place holder, real header is written
at end of processing, since byte count is needed */
fwrite(&WH,1,32,ft->fp);
writedone = 32;
}
void txwwrite(ft, buf, len)
ft_t ft;
LONG *buf, len;
{
int i;
unsigned int w1,w2;
tx16w_len += len;
if (tx16w_len > TXMAXLEN) return;
for (i=0;i<len;i+=2) {
w1 = *buf++ >> 20;
if (i+1==len)
w2 = 0;
else {
w2 = *buf++ >> 20;
}
putc((w1 >> 4) & 0xFF,ft->fp);
putc((((w1 & 0x0F) << 4) | (w2 & 0x0F)) & 0xFF,ft->fp);
putc((w2 >> 4) & 0xFF,ft->fp);
writedone += 3;
}
}
void txwstopwrite(ft)
ft_t ft;
{
struct WaveHeader_ WH;
int AttackLength, LoopLength, i;
/* All samples are already written out. */
/* If file header needs fixing up, for example it needs the */
/* the number of samples in a field, seek back and write them here. */
/* If your format specifies any of the following info. */
/*
ft->info.rate =
ft->info.size = BYTE or WORD ...;
ft->info.style = UNSIGNED or SIGN2 ...;
ft->info.channels = 1 or 2 or 4;
*/
report("tx16w:output finished");
strncpy(WH.filetype,"LM8953",6);
for (i=0;i<10;i++) WH.nulls[i]=0;
for (i=0;i<6;i++) WH.dummy_aeg[i]=0;
for (i=0;i<2;i++) WH.unused[i]=0;
for (i=0;i<2;i++) WH.dummy_aeg[i] = 0;
for (i=2;i<6;i++) WH.dummy_aeg[i] = 0x7F;
WH.format = 0xC9; /* loop off */
/* the actual sample rate is not that important ! */
if (ft->info.rate < 24000) WH.sample_rate = 3;
else if (ft->info.rate < 41000) WH.sample_rate = 1;
else WH.sample_rate = 2;
if (tx16w_len >= TXMAXLEN) {
fprintf(stderr,"Sound too large for TX16W. Truncating, Loop Off\n");
AttackLength = TXMAXLEN/2;
LoopLength = TXMAXLEN/2;
}
else if (tx16w_len >=TXMAXLEN/2) {
AttackLength = TXMAXLEN/2;
LoopLength = tx16w_len - TXMAXLEN/2;
if (LoopLength < 0x40) {
LoopLength +=0x40;
AttackLength -= 0x40;
}
}
else if (tx16w_len >= 0x80) {
AttackLength = tx16w_len -0x40;
LoopLength = 0x40;
}
else {
AttackLength = 0x40;
LoopLength = 0x40;
for(i=tx16w_len;i<0x80;i++) {
putc(0,ft->fp);
putc(0,ft->fp);
putc(0,ft->fp);
writedone += 3;
}
}
/* Fill up to 256 byte blocks; the TX16W seems to like that */
while ((writedone % 0x100) != 0) {
putc(0,ft->fp);
writedone++;
}
WH.atc_length[0] = 0xFF & AttackLength;
WH.atc_length[1] = 0xFF & (AttackLength >> 8);
WH.atc_length[2] = (0x01 & (AttackLength >> 16)) +
magic1[WH.sample_rate];
WH.rpt_length[0] = 0xFF & LoopLength;
WH.rpt_length[1] = 0xFF & (LoopLength >> 8);
WH.rpt_length[2] = (0x01 & (LoopLength >> 16)) +
magic2[WH.sample_rate];
rewind(ft->fp);
fwrite(&WH,1,32,ft->fp);
}
|