/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 |