libsndfile source files.
[Faustine.git] / interpretor / libsndfile-1.0.25 / src / rx2.c
1 /*
2 ** Copyright (C) 2001-2011 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 #include "sfconfig.h"
20
21 #include <stdio.h>
22 #include <string.h>
23 #include <ctype.h>
24 #include <stdarg.h>
25
26 #include "sndfile.h"
27 #include "sfendian.h"
28 #include "common.h"
29
30 #if (ENABLE_EXPERIMENTAL_CODE == 0)
31
32 int
33 rx2_open (SF_PRIVATE *psf)
34 { if (psf)
35 return SFE_UNIMPLEMENTED ;
36 return 0 ;
37 } /* rx2_open */
38
39 #else
40
41 /*------------------------------------------------------------------------------
42 * Macros to handle big/little endian issues.
43 */
44
45 #define CAT_MARKER (MAKE_MARKER ('C', 'A', 'T', ' '))
46 #define GLOB_MARKER (MAKE_MARKER ('G', 'L', 'O', 'B'))
47
48 #define RECY_MARKER (MAKE_MARKER ('R', 'E', 'C', 'Y'))
49
50 #define SLCL_MARKER (MAKE_MARKER ('S', 'L', 'C', 'L'))
51 #define SLCE_MARKER (MAKE_MARKER ('S', 'L', 'C', 'E'))
52
53 #define DEVL_MARKER (MAKE_MARKER ('D', 'E', 'V', 'L'))
54 #define TRSH_MARKER (MAKE_MARKER ('T', 'R', 'S', 'H'))
55
56 #define EQ_MARKER (MAKE_MARKER ('E', 'Q', ' ', ' '))
57 #define COMP_MARKER (MAKE_MARKER ('C', 'O', 'M', 'P'))
58
59 #define SINF_MARKER (MAKE_MARKER ('S', 'I', 'N', 'F'))
60 #define SDAT_MARKER (MAKE_MARKER ('S', 'D', 'A', 'T'))
61
62 /*------------------------------------------------------------------------------
63 * Typedefs for file chunks.
64 */
65
66
67 /*------------------------------------------------------------------------------
68 * Private static functions.
69 */
70 static int rx2_close (SF_PRIVATE *psf) ;
71
72 /*------------------------------------------------------------------------------
73 ** Public functions.
74 */
75
76 int
77 rx2_open (SF_PRIVATE *psf)
78 { static const char *marker_type [4] =
79 { "Original Enabled", "Enabled Hidden",
80 "Additional/PencilTool", "Disabled"
81 } ;
82
83 int error, marker, length, glob_offset, slce_count, frames ;
84
85 int sdat_length = 0, slce_total = 0 ;
86
87 int n_channels ;
88
89
90 /* So far only doing read. */
91
92 psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ;
93
94 if (marker != CAT_MARKER)
95 { psf_log_printf (psf, "length : %d\n", length) ;
96 return -1000 ;
97 } ;
98
99 if (length != psf->filelength - 8)
100 psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ;
101 else
102 psf_log_printf (psf, "%M : %d\n", marker, length) ;
103
104 /* 'REX2' marker */
105 psf_binheader_readf (psf, "m", &marker) ;
106 psf_log_printf (psf, "%M", marker) ;
107
108 /* 'HEAD' marker */
109 psf_binheader_readf (psf, "m", &marker) ;
110 psf_log_printf (psf, "%M\n", marker) ;
111
112 /* Grab 'GLOB' offset. */
113 psf_binheader_readf (psf, "E4", &glob_offset) ;
114 glob_offset += 0x14 ; /* Add the current file offset. */
115
116 /* Jump to offset 0x30 */
117 psf_binheader_readf (psf, "p", 0x30) ;
118
119 /* Get name length */
120 length = 0 ;
121 psf_binheader_readf (psf, "1", &length) ;
122 if (length >= SIGNED_SIZEOF (psf->u.cbuf))
123 { psf_log_printf (psf, " Text : %d *** Error : Too sf_count_t!\n") ;
124 return -1001 ;
125 }
126
127 memset (psf->u.cbuf, 0, sizeof (psf->u.cbuf)) ;
128 psf_binheader_readf (psf, "b", psf->u.cbuf, length) ;
129 psf_log_printf (psf, " Text : \"%s\"\n", psf->u.cbuf) ;
130
131 /* Jump to GLOB offset position. */
132 if (glob_offset & 1)
133 glob_offset ++ ;
134
135 psf_binheader_readf (psf, "p", glob_offset) ;
136
137 slce_count = 0 ;
138 /* GLOB */
139 while (1)
140 { psf_binheader_readf (psf, "m", &marker) ;
141
142 if (marker != SLCE_MARKER && slce_count > 0)
143 { psf_log_printf (psf, " SLCE count : %d\n", slce_count) ;
144 slce_count = 0 ;
145 }
146 switch (marker)
147 { case GLOB_MARKER:
148 psf_binheader_readf (psf, "E4", &length) ;
149 psf_log_printf (psf, " %M : %d\n", marker, length) ;
150 psf_binheader_readf (psf, "j", length) ;
151 break ;
152
153 case RECY_MARKER:
154 psf_binheader_readf (psf, "E4", &length) ;
155 psf_log_printf (psf, " %M : %d\n", marker, length) ;
156 psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */
157 break ;
158
159 case CAT_MARKER:
160 psf_binheader_readf (psf, "E4", &length) ;
161 psf_log_printf (psf, " %M : %d\n", marker, length) ;
162 /*-psf_binheader_readf (psf, "j", length) ;-*/
163 break ;
164
165 case DEVL_MARKER:
166 psf_binheader_readf (psf, "mE4", &marker, &length) ;
167 psf_log_printf (psf, " DEVL%M : %d\n", marker, length) ;
168 if (length & 1)
169 length ++ ;
170 psf_binheader_readf (psf, "j", length) ;
171 break ;
172
173 case EQ_MARKER:
174 case COMP_MARKER:
175 psf_binheader_readf (psf, "E4", &length) ;
176 psf_log_printf (psf, " %M : %d\n", marker, length) ;
177 /* This is weird!!!! why make this (length - 1) */
178 if (length & 1)
179 length ++ ;
180 psf_binheader_readf (psf, "j", length) ;
181 break ;
182
183 case SLCL_MARKER:
184 psf_log_printf (psf, " %M\n (Offset, Next Offset, Type)\n", marker) ;
185 slce_count = 0 ;
186 break ;
187
188 case SLCE_MARKER:
189 { int len [4], indx ;
190
191 psf_binheader_readf (psf, "E4444", &len [0], &len [1], &len [2], &len [3]) ;
192
193 indx = ((len [3] & 0x0000FFFF) >> 8) & 3 ;
194
195 if (len [2] == 1)
196 { if (indx != 1)
197 indx = 3 ; /* 2 cases, where next slice offset = 1 -> disabled & enabled/hidden */
198
199 psf_log_printf (psf, " %M : (%6d, ?: 0x%X, %s)\n", marker, len [1], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
200 }
201 else
202 { slce_total += len [2] ;
203
204 psf_log_printf (psf, " %M : (%6d, SLCE_next_ofs:%d, ?: 0x%X, %s)\n", marker, len [1], len [2], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
205 } ;
206
207 slce_count ++ ;
208 } ;
209 break ;
210
211 case SINF_MARKER:
212 psf_binheader_readf (psf, "E4", &length) ;
213 psf_log_printf (psf, " %M : %d\n", marker, length) ;
214
215 psf_binheader_readf (psf, "E2", &n_channels) ;
216 n_channels = (n_channels & 0x0000FF00) >> 8 ;
217 psf_log_printf (psf, " Channels : %d\n", n_channels) ;
218
219 psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &frames) ;
220 psf->sf.frames = frames ;
221 psf_log_printf (psf, " Sample Rate : %d\n", psf->sf.samplerate) ;
222 psf_log_printf (psf, " Frames : %D\n", psf->sf.frames) ;
223
224 psf_binheader_readf (psf, "E4", &length) ;
225 psf_log_printf (psf, " ??????????? : %d\n", length) ;
226
227 psf_binheader_readf (psf, "E4", &length) ;
228 psf_log_printf (psf, " ??????????? : %d\n", length) ;
229 break ;
230
231 case SDAT_MARKER:
232 psf_binheader_readf (psf, "E4", &length) ;
233
234 sdat_length = length ;
235
236 /* Get the current offset. */
237 psf->dataoffset = psf_binheader_readf (psf, NULL) ;
238
239 if (psf->dataoffset + length != psf->filelength)
240 psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ;
241 else
242 psf_log_printf (psf, " %M : %d\n", marker, length) ;
243 break ;
244
245 default :
246 psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ;
247 return -1003 ;
248 break ;
249 } ;
250
251 /* SDAT always last marker in file. */
252 if (marker == SDAT_MARKER)
253 break ;
254 } ;
255
256 puts (psf->logbuffer) ;
257 puts ("-----------------------------------") ;
258
259 printf ("SDAT length : %d\n", sdat_length) ;
260 printf ("SLCE count : %d\n", slce_count) ;
261
262 /* Hack for zero slice count. */
263 if (slce_count == 0 && slce_total == 1)
264 slce_total = frames ;
265
266 printf ("SLCE samples : %d\n", slce_total) ;
267
268 /* Two bytes per sample. */
269 printf ("Comp Ratio : %f:1\n", (2.0 * slce_total * n_channels) / sdat_length) ;
270
271 puts (" ") ;
272
273 psf->logbuffer [0] = 0 ;
274
275 /* OK, have the header although not too sure what it all means. */
276
277 psf->endian = SF_ENDIAN_BIG ;
278
279 psf->datalength = psf->filelength - psf->dataoffset ;
280
281 if (psf_fseek (psf, psf->dataoffset, SEEK_SET))
282 return SFE_BAD_SEEK ;
283
284 psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ;
285
286 psf->sf.channels = 1 ;
287 psf->bytewidth = 2 ;
288 psf->blockwidth = psf->sf.channels * psf->bytewidth ;
289
290 if ((error = dwvw_init (psf, 16)))
291 return error ;
292
293 psf->container_close = rx2_close ;
294
295 if (! psf->sf.frames && psf->blockwidth)
296 psf->sf.frames = psf->datalength / psf->blockwidth ;
297
298 /* All done. */
299
300 return 0 ;
301 } /* rx2_open */
302
303 /*------------------------------------------------------------------------------
304 */
305
306 static int
307 rx2_close (SF_PRIVATE *psf)
308 {
309 if (psf->file.mode == SFM_WRITE)
310 { /* Now we know for certain the length of the file we can re-write
311 ** correct values for the FORM, 8SVX and BODY chunks.
312 */
313
314 } ;
315
316 return 0 ;
317 } /* rx2_close */
318
319 #endif