• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ** Copyright (C) 2002-2012 Erik de Castro Lopo <erikd@mega-nerd.com>
3 **
4 ** This program is free software; you can redistribute it and/or modify
5 ** it under the terms of the GNU Lesser General Public License as published by
6 ** the Free Software Foundation; either version 2.1 of the License, or
7 ** (at your option) any later version.
8 **
9 ** This program is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 ** GNU Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public License
15 ** along with this program; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 
19 /*===========================================================================
20 ** Yamaha TX16 Sampler Files.
21 **
22 ** This header parser was written using information from the SoX source code
23 ** and trial and error experimentation. The code here however is all original.
24 */
25 
26 #include	"sfconfig.h"
27 
28 #include	<stdio.h>
29 #include	<fcntl.h>
30 #include	<string.h>
31 #include	<ctype.h>
32 
33 #include	"sndfile.h"
34 #include	"sfendian.h"
35 #include	"common.h"
36 
37 #if (ENABLE_EXPERIMENTAL_CODE == 0)
38 
39 int
txw_open(SF_PRIVATE * psf)40 txw_open	(SF_PRIVATE *psf)
41 {	if (psf)
42 		return SFE_UNIMPLEMENTED ;
43 	return 0 ;
44 } /* txw_open */
45 
46 #else
47 
48 /*------------------------------------------------------------------------------
49 ** Markers.
50 */
51 
52 #define TXW_DATA_OFFSET		32
53 
54 #define	TXW_LOOPED			0x49
55 #define	TXW_NO_LOOP			0xC9
56 
57 /*------------------------------------------------------------------------------
58 ** Private static functions.
59 */
60 
61 static int txw_read_header (SF_PRIVATE *psf) ;
62 
63 static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ;
64 static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ;
65 static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ;
66 static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ;
67 
68 static sf_count_t txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset) ;
69 
70 /*------------------------------------------------------------------------------
71 ** Public functions.
72 */
73 
74 /*
75  * ftp://ftp.t0.or.at/pub/sound/tx16w/samples.yamaha
76  * ftp://ftp.t0.or.at/pub/sound/tx16w/faq/tx16w.tec
77  * http://www.t0.or.at/~mpakesch/tx16w/
78  *
79  * from tx16w.c sox 12.15: (7-Oct-98) (Mark Lakata and Leigh Smith)
80  *  char filetype[6] "LM8953"
81  *  nulls[10],
82  *  dummy_aeg[6]
83  *  format 0x49 = looped, 0xC9 = non-looped
84  *  sample_rate 1 = 33 kHz, 2 = 50 kHz, 3 = 16 kHz
85  *  atc_length[3] if sample rate 0, [2]&0xfe = 6: 33kHz, 0x10:50, 0xf6: 16,
86  *					depending on [5] but to heck with it
87  *  rpt_length[3] (these are for looped samples, attack and loop lengths)
88  *  unused[2]
89  */
90 
91 typedef struct
92 {	unsigned char	format, srate, sr2, sr3 ;
93 	unsigned short	srhash ;
94 	unsigned int	attacklen, repeatlen ;
95 } TXW_HEADER ;
96 
97 #define	ERROR_666	666
98 
99 int
txw_open(SF_PRIVATE * psf)100 txw_open	(SF_PRIVATE *psf)
101 {	int error ;
102 
103 	if (psf->file.mode != SFM_READ)
104 		return SFE_UNIMPLEMENTED ;
105 
106 	if ((error = txw_read_header (psf)))
107 			return error ;
108 
109  	if (psf_fseek (psf, psf->dataoffset, SEEK_SET) != psf->dataoffset)
110 		return SFE_BAD_SEEK ;
111 
112 	psf->read_short		= txw_read_s ;
113 	psf->read_int		= txw_read_i ;
114 	psf->read_float		= txw_read_f ;
115 	psf->read_double	= txw_read_d ;
116 
117 	psf->seek = txw_seek ;
118 
119 	return 0 ;
120 } /* txw_open */
121 
122 /*------------------------------------------------------------------------------
123 */
124 
125 static int
txw_read_header(SF_PRIVATE * psf)126 txw_read_header	(SF_PRIVATE *psf)
127 {	BUF_UNION	ubuf ;
128 	TXW_HEADER txwh ;
129 	const char	*strptr ;
130 
131 	memset (&txwh, 0, sizeof (txwh)) ;
132 	memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ;
133 	psf_binheader_readf (psf, "pb", 0, ubuf.cbuf, 16) ;
134 
135 	if (memcmp (ubuf.cbuf, "LM8953\0\0\0\0\0\0\0\0\0\0", 16) != 0)
136 		return ERROR_666 ;
137 
138 	psf_log_printf (psf, "Read only : Yamaha TX-16 Sampler (.txw)\nLM8953\n") ;
139 
140 	/* Jump 6 bytes (dummp_aeg), read format, read sample rate. */
141 	psf_binheader_readf (psf, "j11", 6, &txwh.format, &txwh.srate) ;
142 
143 	/* 8 bytes (atc_length[3], rpt_length[3], unused[2]). */
144 	psf_binheader_readf (psf, "e33j", &txwh.attacklen, &txwh.repeatlen, 2) ;
145 	txwh.sr2 = (txwh.attacklen >> 16) & 0xFE ;
146 	txwh.sr3 = (txwh.repeatlen >> 16) & 0xFE ;
147 	txwh.attacklen &= 0x1FFFF ;
148 	txwh.repeatlen &= 0x1FFFF ;
149 
150 	switch (txwh.format)
151 	{	case TXW_LOOPED :
152 				strptr = "looped" ;
153 				break ;
154 
155 		case TXW_NO_LOOP :
156 				strptr = "non-looped" ;
157 				break ;
158 
159 		default :
160 				psf_log_printf (psf, " Format      : 0x%02x => ?????\n", txwh.format) ;
161 				return ERROR_666 ;
162 		} ;
163 
164 	psf_log_printf (psf, " Format      : 0x%02X => %s\n", txwh.format, strptr) ;
165 
166 	strptr = NULL ;
167 
168 	switch (txwh.srate)
169 	{	case 1 :
170 				psf->sf.samplerate = 33333 ;
171 				break ;
172 
173 		case 2 :
174 				psf->sf.samplerate = 50000 ;
175 				break ;
176 
177 		case 3 :
178 				psf->sf.samplerate = 16667 ;
179 				break ;
180 
181 		default :
182 			/* This is ugly and braindead. */
183 			txwh.srhash = ((txwh.sr2 & 0xFE) << 8) | (txwh.sr3 & 0xFE) ;
184 			switch (txwh.srhash)
185 			{	case ((0x6 << 8) | 0x52) :
186 						psf->sf.samplerate = 33333 ;
187 						break ;
188 
189 				case ((0x10 << 8) | 0x52) :
190 						psf->sf.samplerate = 50000 ;
191 						break ;
192 
193 				case ((0xF6 << 8) | 0x52) :
194 						psf->sf.samplerate = 166667 ;
195 						break ;
196 
197 				default :
198 						strptr = " Sample Rate : Unknown : forcing to 33333\n" ;
199 						psf->sf.samplerate = 33333 ;
200 						break ;
201 				} ;
202 		} ;
203 
204 
205 	if (strptr)
206 		psf_log_printf (psf, strptr) ;
207 	else if (txwh.srhash)
208 		psf_log_printf (psf, " Sample Rate : %d (0x%X) => %d\n", txwh.srate, txwh.srhash, psf->sf.samplerate) ;
209 	else
210 		psf_log_printf (psf, " Sample Rate : %d => %d\n", txwh.srate, psf->sf.samplerate) ;
211 
212 	if (txwh.format == TXW_LOOPED)
213 	{	psf_log_printf (psf, " Attack Len  : %d\n", txwh.attacklen) ;
214 		psf_log_printf (psf, " Repeat Len  : %d\n", txwh.repeatlen) ;
215 		} ;
216 
217 	psf->dataoffset = TXW_DATA_OFFSET ;
218 	psf->datalength = psf->filelength - TXW_DATA_OFFSET ;
219 	psf->sf.frames	= 2 * psf->datalength / 3 ;
220 
221 
222 	if (psf->datalength % 3 == 1)
223 		psf_log_printf (psf, "*** File seems to be truncated, %d extra bytes.\n",
224 			(int) (psf->datalength % 3)) ;
225 
226 	if (txwh.attacklen + txwh.repeatlen > psf->sf.frames)
227 		psf_log_printf (psf, "*** File has been truncated.\n") ;
228 
229 	psf->sf.format = SF_FORMAT_TXW | SF_FORMAT_PCM_16 ;
230 	psf->sf.channels = 1 ;
231 	psf->sf.sections = 1 ;
232 	psf->sf.seekable = SF_TRUE ;
233 
234 	return 0 ;
235 } /* txw_read_header */
236 
237 static sf_count_t
txw_read_s(SF_PRIVATE * psf,short * ptr,sf_count_t len)238 txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
239 {	BUF_UNION		ubuf ;
240 	unsigned char	*ucptr ;
241 	short			sample ;
242 	int				k, bufferlen, readcount, count ;
243 	sf_count_t		total = 0 ;
244 
245 	bufferlen = sizeof (ubuf.cbuf) / 3 ;
246 	bufferlen -= (bufferlen & 1) ;
247 	while (len > 0)
248 	{	readcount = (len >= bufferlen) ? bufferlen : len ;
249 		count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
250 
251 		ucptr = ubuf.ucbuf ;
252 		for (k = 0 ; k < readcount ; k += 2)
253 		{	sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
254 			ptr [total + k] = sample ;
255 			sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
256 			ptr [total + k + 1] = sample ;
257 			ucptr += 3 ;
258 			} ;
259 
260 		total += count ;
261 		len -= readcount ;
262 		} ;
263 
264 	return total ;
265 } /* txw_read_s */
266 
267 static sf_count_t
txw_read_i(SF_PRIVATE * psf,int * ptr,sf_count_t len)268 txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
269 {	BUF_UNION		ubuf ;
270 	unsigned char	*ucptr ;
271 	short			sample ;
272 	int				k, bufferlen, readcount, count ;
273 	sf_count_t		total = 0 ;
274 
275 	bufferlen = sizeof (ubuf.cbuf) / 3 ;
276 	bufferlen -= (bufferlen & 1) ;
277 	while (len > 0)
278 	{	readcount = (len >= bufferlen) ? bufferlen : len ;
279 		count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
280 
281 		ucptr = ubuf.ucbuf ;
282 		for (k = 0 ; k < readcount ; k += 2)
283 		{	sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
284 			ptr [total + k] = sample << 16 ;
285 			sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
286 			ptr [total + k + 1] = sample << 16 ;
287 			ucptr += 3 ;
288 			} ;
289 
290 		total += count ;
291 		len -= readcount ;
292 		} ;
293 
294 	return total ;
295 } /* txw_read_i */
296 
297 static sf_count_t
txw_read_f(SF_PRIVATE * psf,float * ptr,sf_count_t len)298 txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
299 {	BUF_UNION		ubuf ;
300 	unsigned char	*ucptr ;
301 	short			sample ;
302 	int				k, bufferlen, readcount, count ;
303 	sf_count_t		total = 0 ;
304 	float			normfact ;
305 
306 	if (psf->norm_float == SF_TRUE)
307 		normfact = 1.0 / 0x8000 ;
308 	else
309 		normfact = 1.0 / 0x10 ;
310 
311 	bufferlen = sizeof (ubuf.cbuf) / 3 ;
312 	bufferlen -= (bufferlen & 1) ;
313 	while (len > 0)
314 	{	readcount = (len >= bufferlen) ? bufferlen : len ;
315 		count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
316 
317 		ucptr = ubuf.ucbuf ;
318 		for (k = 0 ; k < readcount ; k += 2)
319 		{	sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
320 			ptr [total + k] = normfact * sample ;
321 			sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
322 			ptr [total + k + 1] = normfact * sample ;
323 			ucptr += 3 ;
324 			} ;
325 
326 		total += count ;
327 		len -= readcount ;
328 		} ;
329 
330 	return total ;
331 } /* txw_read_f */
332 
333 static sf_count_t
txw_read_d(SF_PRIVATE * psf,double * ptr,sf_count_t len)334 txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
335 {	BUF_UNION		ubuf ;
336 	unsigned char	*ucptr ;
337 	short			sample ;
338 	int				k, bufferlen, readcount, count ;
339 	sf_count_t		total = 0 ;
340 	double			normfact ;
341 
342 	if (psf->norm_double == SF_TRUE)
343 		normfact = 1.0 / 0x8000 ;
344 	else
345 		normfact = 1.0 / 0x10 ;
346 
347 	bufferlen = sizeof (ubuf.cbuf) / 3 ;
348 	bufferlen -= (bufferlen & 1) ;
349 	while (len > 0)
350 	{	readcount = (len >= bufferlen) ? bufferlen : len ;
351 		count = psf_fread (ubuf.cbuf, 3, readcount, psf) ;
352 
353 		ucptr = ubuf.ucbuf ;
354 		for (k = 0 ; k < readcount ; k += 2)
355 		{	sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
356 			ptr [total + k] = normfact * sample ;
357 			sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
358 			ptr [total + k + 1] = normfact * sample ;
359 			ucptr += 3 ;
360 			} ;
361 
362 		total += count ;
363 		len -= readcount ;
364 		} ;
365 
366 	return total ;
367 } /* txw_read_d */
368 
369 static sf_count_t
txw_seek(SF_PRIVATE * psf,int mode,sf_count_t offset)370 txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
371 {	if (psf && mode)
372 		return offset ;
373 
374 	return 0 ;
375 } /* txw_seek */
376 
377 #endif
378