Git init
[external/libsndfile.git] / src / txw.c
1 /*
2 ** Copyright (C) 2002-2009 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
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
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
126 txw_read_header (SF_PRIVATE *psf)
127 {       TXW_HEADER txwh ;
128         const char      *strptr ;
129
130         memset (&txwh, 0, sizeof (txwh)) ;
131         memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
132         psf_binheader_readf (psf, "pb", 0, psf->u.cbuf, 16) ;
133
134         if (memcmp (psf->u.cbuf, "LM8953\0\0\0\0\0\0\0\0\0\0", 16) != 0)
135                 return ERROR_666 ;
136
137         psf_log_printf (psf, "Read only : Yamaha TX-16 Sampler (.txw)\nLM8953\n") ;
138
139         /* Jump 6 bytes (dummp_aeg), read format, read sample rate. */
140         psf_binheader_readf (psf, "j11", 6, &txwh.format, &txwh.srate) ;
141
142         /* 8 bytes (atc_length[3], rpt_length[3], unused[2]). */
143         psf_binheader_readf (psf, "e33j", &txwh.attacklen, &txwh.repeatlen, 2) ;
144         txwh.sr2 = (txwh.attacklen >> 16) & 0xFE ;
145         txwh.sr3 = (txwh.repeatlen >> 16) & 0xFE ;
146         txwh.attacklen &= 0x1FFFF ;
147         txwh.repeatlen &= 0x1FFFF ;
148
149         switch (txwh.format)
150         {       case TXW_LOOPED :
151                                 strptr = "looped" ;
152                                 break ;
153
154                 case TXW_NO_LOOP :
155                                 strptr = "non-looped" ;
156                                 break ;
157
158                 default :
159                                 psf_log_printf (psf, " Format      : 0x%02x => ?????\n", txwh.format) ;
160                                 return ERROR_666 ;
161                 } ;
162
163         psf_log_printf (psf, " Format      : 0x%02X => %s\n", txwh.format, strptr) ;
164
165         strptr = NULL ;
166
167         switch (txwh.srate)
168         {       case 1 :
169                                 psf->sf.samplerate = 33333 ;
170                                 break ;
171
172                 case 2 :
173                                 psf->sf.samplerate = 50000 ;
174                                 break ;
175
176                 case 3 :
177                                 psf->sf.samplerate = 16667 ;
178                                 break ;
179
180                 default :
181                         /* This is ugly and braindead. */
182                         txwh.srhash = ((txwh.sr2 & 0xFE) << 8) | (txwh.sr3 & 0xFE) ;
183                         switch (txwh.srhash)
184                         {       case ((0x6 << 8) | 0x52) :
185                                                 psf->sf.samplerate = 33333 ;
186                                                 break ;
187
188                                 case ((0x10 << 8) | 0x52) :
189                                                 psf->sf.samplerate = 50000 ;
190                                                 break ;
191
192                                 case ((0xF6 << 8) | 0x52) :
193                                                 psf->sf.samplerate = 166667 ;
194                                                 break ;
195
196                                 default :
197                                                 strptr = " Sample Rate : Unknown : forcing to 33333\n" ;
198                                                 psf->sf.samplerate = 33333 ;
199                                                 break ;
200                                 } ;
201                 } ;
202
203
204         if (strptr)
205                 psf_log_printf (psf, strptr) ;
206         else if (txwh.srhash)
207                 psf_log_printf (psf, " Sample Rate : %d (0x%X) => %d\n", txwh.srate, txwh.srhash, psf->sf.samplerate) ;
208         else
209                 psf_log_printf (psf, " Sample Rate : %d => %d\n", txwh.srate, psf->sf.samplerate) ;
210
211         if (txwh.format == TXW_LOOPED)
212         {       psf_log_printf (psf, " Attack Len  : %d\n", txwh.attacklen) ;
213                 psf_log_printf (psf, " Repeat Len  : %d\n", txwh.repeatlen) ;
214                 } ;
215
216         psf->dataoffset = TXW_DATA_OFFSET ;
217         psf->datalength = psf->filelength - TXW_DATA_OFFSET ;
218         psf->sf.frames  = 2 * psf->datalength / 3 ;
219
220
221         if (psf->datalength % 3 == 1)
222                 psf_log_printf (psf, "*** File seems to be truncated, %d extra bytes.\n",
223                         (int) (psf->datalength % 3)) ;
224
225         if (txwh.attacklen + txwh.repeatlen > psf->sf.frames)
226                 psf_log_printf (psf, "*** File has been truncated.\n") ;
227
228         psf->sf.format = SF_FORMAT_TXW | SF_FORMAT_PCM_16 ;
229         psf->sf.channels = 1 ;
230         psf->sf.sections = 1 ;
231         psf->sf.seekable = SF_TRUE ;
232
233         return 0 ;
234 } /* txw_read_header */
235
236 static sf_count_t
237 txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len)
238 {       unsigned char   *ucptr ;
239         short                   sample ;
240         int                             k, bufferlen, readcount, count ;
241         sf_count_t              total = 0 ;
242
243         bufferlen = sizeof (psf->u.cbuf) / 3 ;
244         bufferlen -= (bufferlen & 1) ;
245         while (len > 0)
246         {       readcount = (len >= bufferlen) ? bufferlen : len ;
247                 count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
248
249                 ucptr = psf->u.ucbuf ;
250                 for (k = 0 ; k < readcount ; k += 2)
251                 {       sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
252                         ptr [total + k] = sample ;
253                         sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
254                         ptr [total + k + 1] = sample ;
255                         ucptr += 3 ;
256                         } ;
257
258                 total += count ;
259                 len -= readcount ;
260                 } ;
261
262         return total ;
263 } /* txw_read_s */
264
265 static sf_count_t
266 txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len)
267 {       unsigned char   *ucptr ;
268         short                   sample ;
269         int                             k, bufferlen, readcount, count ;
270         sf_count_t              total = 0 ;
271
272         bufferlen = sizeof (psf->u.cbuf) / 3 ;
273         bufferlen -= (bufferlen & 1) ;
274         while (len > 0)
275         {       readcount = (len >= bufferlen) ? bufferlen : len ;
276                 count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
277
278                 ucptr = psf->u.ucbuf ;
279                 for (k = 0 ; k < readcount ; k += 2)
280                 {       sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
281                         ptr [total + k] = sample << 16 ;
282                         sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
283                         ptr [total + k + 1] = sample << 16 ;
284                         ucptr += 3 ;
285                         } ;
286
287                 total += count ;
288                 len -= readcount ;
289                 } ;
290
291         return total ;
292 } /* txw_read_i */
293
294 static sf_count_t
295 txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len)
296 {       unsigned char   *ucptr ;
297         short                   sample ;
298         int                             k, bufferlen, readcount, count ;
299         sf_count_t              total = 0 ;
300         float                   normfact ;
301
302         if (psf->norm_float == SF_TRUE)
303                 normfact = 1.0 / 0x8000 ;
304         else
305                 normfact = 1.0 / 0x10 ;
306
307         bufferlen = sizeof (psf->u.cbuf) / 3 ;
308         bufferlen -= (bufferlen & 1) ;
309         while (len > 0)
310         {       readcount = (len >= bufferlen) ? bufferlen : len ;
311                 count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
312
313                 ucptr = psf->u.ucbuf ;
314                 for (k = 0 ; k < readcount ; k += 2)
315                 {       sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
316                         ptr [total + k] = normfact * sample ;
317                         sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
318                         ptr [total + k + 1] = normfact * sample ;
319                         ucptr += 3 ;
320                         } ;
321
322                 total += count ;
323                 len -= readcount ;
324                 } ;
325
326         return total ;
327 } /* txw_read_f */
328
329 static sf_count_t
330 txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len)
331 {       unsigned char   *ucptr ;
332         short                   sample ;
333         int                             k, bufferlen, readcount, count ;
334         sf_count_t              total = 0 ;
335         double                  normfact ;
336
337         if (psf->norm_double == SF_TRUE)
338                 normfact = 1.0 / 0x8000 ;
339         else
340                 normfact = 1.0 / 0x10 ;
341
342         bufferlen = sizeof (psf->u.cbuf) / 3 ;
343         bufferlen -= (bufferlen & 1) ;
344         while (len > 0)
345         {       readcount = (len >= bufferlen) ? bufferlen : len ;
346                 count = psf_fread (psf->u.cbuf, 3, readcount, psf) ;
347
348                 ucptr = psf->u.ucbuf ;
349                 for (k = 0 ; k < readcount ; k += 2)
350                 {       sample = (ucptr [0] << 8) | (ucptr [1] & 0xF0) ;
351                         ptr [total + k] = normfact * sample ;
352                         sample = (ucptr [2] << 8) | ((ucptr [1] & 0xF) << 4) ;
353                         ptr [total + k + 1] = normfact * sample ;
354                         ucptr += 3 ;
355                         } ;
356
357                 total += count ;
358                 len -= readcount ;
359                 } ;
360
361         return total ;
362 } /* txw_read_d */
363
364 static sf_count_t
365 txw_seek (SF_PRIVATE *psf, int mode, sf_count_t offset)
366 {       if (psf && mode)
367                 return offset ;
368
369         return 0 ;
370 } /* txw_seek */
371
372 #endif