1 /* libSoX Yamaha TX-16W sampler file support
4 * Copyright 1993 Rob Talley (rob@aii.com)
5 * This source code is freely redistributable and may be used for
6 * any purpose. This copyright notice and the following copyright
7 * notice must be maintained intact. No warranty whatsoever is
8 * provided. This code is furnished AS-IS as a component of the
9 * larger work Copyright 1991 Lance Norskog and Sundry Contributors.
10 * Much appreciation to ross-c for his sampConv utility for SGI/IRIX
11 * from where these methods were derived.
14 * Pat McElhatton, HP Media Technology Lab <patmc@apollo.hp.com>
15 * Handles reading of files which do not have the sample rate field
16 * set to one of the expected by looking at some other bytes in the
17 * attack/loop length fields, and defaulting to 33kHz if the sample
18 * rate is still unknown.
21 * Copyright 1995 Mark Lakata (lakata@physics.berkeley.edu)
22 * Additions to tx16w.c SOX handler. This version writes as well as
26 * Cleaned up by Leigh Smith (leigh@psychokiller.dialix.oz.au)
27 * for incorporation into the main sox distribution.
30 * Forced output to mono signed words to match input. It was basically
31 * doing this anyways but now the user will see a display that it's been
32 * overridden. cbagwell@sprynet.com
40 #define TXMAXLEN 0x3FF80
42 /* Private data for TX16 file */
46 size_t rest
; /* bytes remaining in sample file */
52 char filetype
[6]; /* = "LM8953", */
55 dummy_aeg
[6], /* space for the AEG (never mind this) */
56 format
, /* 0x49 = looped, 0xC9 = non-looped */
57 sample_rate
, /* 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz */
58 atc_length
[3], /* I'll get to this... */
60 unused
[2]; /* set these to null, to be on the safe side */
63 static const unsigned char magic1
[4] = {0, 0x06, 0x10, 0xF6};
64 static const unsigned char magic2
[4] = {0, 0x52, 0x00, 0x52};
67 * Do anything required before you start reading samples.
69 * Find out sampling rate,
70 * size and encoding of samples,
73 static int startread(sox_format_t
* ft
)
78 unsigned char sample_rate
;
79 size_t num_samp_bytes
= 0;
80 unsigned char gunk
[8];
84 priv_t
* sk
= (priv_t
*) ft
->priv
;
85 /* If you need to seek around the input file. */
88 lsx_fail_errno(ft
,SOX_EOF
,"txw input file must be a file, not a pipe");
92 /* This is dumb but portable, just count the bytes til EOF */
93 while (lsx_read_b_buf(ft
, &trash
, (size_t) 1) == 1)
95 num_samp_bytes
-= 32; /* calculate num samples by sub header size */
96 lsx_seeki(ft
, (off_t
)0, 0); /* rewind file */
97 sk
->rest
= num_samp_bytes
; /* set how many sample bytes to read */
99 /* first 6 bytes are file type ID LM8953 */
100 lsx_readchars(ft
, filetype
, sizeof(filetype
) - 1);
102 for( c
= 16; c
> 0 ; c
-- ) /* Discard next 16 bytes */
103 lsx_readb(ft
, &trash
);
104 lsx_readsb(ft
, &format
);
105 lsx_readb(ft
, &sample_rate
);
107 * save next 8 bytes - if sample rate is 0, then we need
108 * to look at gunk[2] and gunk[5] to get real rate
110 for( c
= 0; c
< 8; c
++ )
111 lsx_readb(ft
, &(gunk
[c
]));
113 * We should now be pointing at start of raw sample data in file
116 /* Check to make sure we got a good filetype ID from file */
117 lsx_debug("Found header filetype %s",filetype
);
118 if(strcmp(filetype
,"LM8953"))
120 lsx_fail_errno(ft
,SOX_EHDR
,"Invalid filetype ID in input file header, != LM8953");
124 * Set up the sample rate as indicated by the header
127 switch( sample_rate
) {
129 ft
->signal
.rate
= 1e5
/ 3;
132 ft
->signal
.rate
= 1e5
/ 2;
135 ft
->signal
.rate
= 1e5
/ 6;
139 switch( gunk
[2] & 0xFE ) {
141 if ( (gunk
[5] & 0xFE) == 0x52 ) {
143 ft
->signal
.rate
= 1e5
/ 3;
147 if ( (gunk
[5] & 0xFE) == 0x00 ) {
149 ft
->signal
.rate
= 1e5
/ 2;
153 if ( (gunk
[5] & 0xFE) == 0x52 ) {
155 ft
->signal
.rate
= 1e5
/ 6;
160 lsx_debug("Invalid sample rate identifier found %d", sample_rate
);
161 ft
->signal
.rate
= 1e5
/ 3;
164 lsx_debug("Sample rate = %g", ft
->signal
.rate
);
166 ft
->signal
.channels
= 1 ; /* not sure about stereo sample data yet ??? */
167 ft
->encoding
.bits_per_sample
= 12;
168 ft
->encoding
.encoding
= SOX_ENCODING_SIGN2
;
174 * Read up to len samples from file.
175 * Convert to sox_sample_t.
177 * Return number of samples read.
180 static size_t read_samples(sox_format_t
* ft
, sox_sample_t
*buf
, size_t len
)
182 priv_t
* sk
= (priv_t
*) ft
->priv
;
184 unsigned char uc1
,uc2
,uc3
;
185 unsigned short s1
,s2
;
188 * This gets called by the top level 'process' routine.
189 * We will essentially get called with a buffer pointer
190 * and a max length to read. Graciously, it is always
191 * an even amount so we don't have to worry about
192 * hanging onto the left over odd samples since there
193 * won't be any. Something to look out for though :-(
194 * We return the number of samples we read.
195 * We will get called over and over again until we return
200 * This is ugly but it's readable!
201 * Read three bytes from stream, then decompose these into
202 * two unsigned short samples.
203 * TCC 3.0 appeared to do unwanted things, so we really specify
204 * exactly what we want to happen.
205 * Convert unsigned short to sox_sample_t then shift up the result
206 * so that the 12-bit sample lives in the most significant
207 * 12-bits of the sox_sample_t.
208 * This gets our two samples into the internal format which we
209 * deposit into the given buffer and adjust our counts respectivly.
211 for(done
= 0; done
< len
; ) {
212 if(sk
->rest
< 3) break; /* Finished reading from file? */
216 sk
->rest
-= 3; /* adjust remaining for bytes we just read */
217 s1
= (unsigned short) (uc1
<< 4) | (((uc2
>> 4) & 017));
218 s2
= (unsigned short) (uc3
<< 4) | (( uc2
& 017 ));
219 *buf
= (sox_sample_t
) s1
;
221 buf
++; /* sample one is done */
222 *buf
= (sox_sample_t
) s2
;
224 buf
++; /* sample two is done */
225 done
+= 2; /* adjust converted & stored sample count */
230 static int startwrite(sox_format_t
* ft
)
232 priv_t
* sk
= (priv_t
*) ft
->priv
;
233 struct WaveHeader_ WH
;
235 lsx_debug("tx16w selected output");
237 memset(&WH
, 0, sizeof(struct WaveHeader_
));
239 /* If you have to seek around the output file */
242 lsx_fail_errno(ft
,SOX_EOF
,"Output .txw file must be a file, not a pipe");
246 /* dummy numbers, just for place holder, real header is written
247 at end of processing, since byte count is needed */
249 lsx_writebuf(ft
, &WH
, (size_t) 32);
254 static size_t write_samples(sox_format_t
* ft
, const sox_sample_t
*buf
, size_t len0
)
256 priv_t
* sk
= (priv_t
*) ft
->priv
;
257 size_t last_i
, i
= 0, len
= min(len0
, TXMAXLEN
- sk
->samples_out
);
264 sk
->odd_flag
= sox_false
;
266 else w1
= *buf
++ >> 20, ++i
;
269 w2
= *buf
++ >> 20, ++i
;
270 if (lsx_writesb(ft
, (w1
>> 4) & 0xFF) ||
271 lsx_writesb(ft
, (((w1
& 0x0F) << 4) | (w2
& 0x0F)) & 0xFF) ||
272 lsx_writesb(ft
, (w2
>> 4) & 0xFF)) {
276 sk
->samples_out
+= 2;
281 sk
->odd_flag
= sox_true
;
287 static int stopwrite(sox_format_t
* ft
)
289 priv_t
* sk
= (priv_t
*) ft
->priv
;
290 struct WaveHeader_ WH
;
291 int AttackLength
, LoopLength
, i
;
294 sox_sample_t pad
= 0;
295 write_samples(ft
, &pad
, (size_t) 1);
298 /* All samples are already written out. */
299 /* If file header needs fixing up, for example it needs the */
300 /* the number of samples in a field, seek back and write them here. */
302 lsx_debug("tx16w:output finished");
304 memset(&WH
, 0, sizeof(struct WaveHeader_
));
305 memcpy(WH
.filetype
, "LM8953", 6);
306 for (i
=0;i
<10;i
++) WH
.nulls
[i
]=0;
307 for (i
=0;i
<6;i
++) WH
.dummy_aeg
[i
]=0;
308 for (i
=0;i
<2;i
++) WH
.unused
[i
]=0;
309 for (i
=0;i
<2;i
++) WH
.dummy_aeg
[i
] = 0;
310 for (i
=2;i
<6;i
++) WH
.dummy_aeg
[i
] = 0x7F;
312 WH
.format
= 0xC9; /* loop off */
314 /* the actual sample rate is not that important ! */
315 if (ft
->signal
.rate
< 24000) WH
.sample_rate
= 3;
316 else if (ft
->signal
.rate
< 41000) WH
.sample_rate
= 1;
317 else WH
.sample_rate
= 2;
319 if (sk
->samples_out
>= TXMAXLEN
) {
320 lsx_warn("Sound too large for TX16W. Truncating, Loop Off");
321 AttackLength
= TXMAXLEN
/2;
322 LoopLength
= TXMAXLEN
/2;
324 else if (sk
->samples_out
>=TXMAXLEN
/2) {
325 AttackLength
= TXMAXLEN
/2;
326 LoopLength
= sk
->samples_out
- TXMAXLEN
/2;
327 if (LoopLength
< 0x40) {
329 AttackLength
-= 0x40;
332 else if (sk
->samples_out
>= 0x80) {
333 AttackLength
= sk
->samples_out
-0x40;
339 for(i
=sk
->samples_out
;i
<0x80;i
++) {
347 /* Fill up to 256 byte blocks; the TX16W seems to like that */
349 while ((sk
->bytes_out
% 0x100) != 0) {
354 WH
.atc_length
[0] = 0xFF & AttackLength
;
355 WH
.atc_length
[1] = 0xFF & (AttackLength
>> 8);
356 WH
.atc_length
[2] = (0x01 & (AttackLength
>> 16)) +
357 magic1
[WH
.sample_rate
];
359 WH
.rpt_length
[0] = 0xFF & LoopLength
;
360 WH
.rpt_length
[1] = 0xFF & (LoopLength
>> 8);
361 WH
.rpt_length
[2] = (0x01 & (LoopLength
>> 16)) +
362 magic2
[WH
.sample_rate
];
365 lsx_writebuf(ft
, &WH
, (size_t) 32);
370 LSX_FORMAT_HANDLER(txw
)
372 static char const * const names
[] = {"txw", NULL
};
373 static sox_rate_t
const write_rates
[] = {1e5
/6, 1e5
/3, 1e5
/2, 0};
374 static unsigned const write_encodings
[] = {SOX_ENCODING_SIGN2
, 12, 0, 0};
375 static sox_format_handler_t
const handler
= {SOX_LIB_VERSION_CODE
,
376 "Yamaha TX-16W sampler", names
, SOX_FILE_MONO
,
377 startread
, read_samples
, NULL
,
378 startwrite
, write_samples
, stopwrite
,
379 NULL
, write_encodings
, write_rates
, sizeof(priv_t
)