Coverage Report

Created: 2026-06-10 06:53

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libsndfile/src/txw.c
Line
Count
Source
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
40
txw_open  (SF_PRIVATE *psf)
41
2
{ if (psf)
42
2
    return SFE_UNIMPLEMENTED ;
43
0
  return 0 ;
44
2
} /* 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
{ 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
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
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
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
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
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