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 39int 40txw_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 61static int txw_read_header (SF_PRIVATE *psf) ; 62 63static sf_count_t txw_read_s (SF_PRIVATE *psf, short *ptr, sf_count_t len) ; 64static sf_count_t txw_read_i (SF_PRIVATE *psf, int *ptr, sf_count_t len) ; 65static sf_count_t txw_read_f (SF_PRIVATE *psf, float *ptr, sf_count_t len) ; 66static sf_count_t txw_read_d (SF_PRIVATE *psf, double *ptr, sf_count_t len) ; 67 68static 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 91typedef 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 99int 100txw_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 125static int 126txw_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 237static sf_count_t 238txw_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 267static sf_count_t 268txw_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 297static sf_count_t 298txw_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 333static sf_count_t 334txw_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 369static sf_count_t 370txw_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