1 /*
2 ** Copyright (C) 2001-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 #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
rx2_open(SF_PRIVATE * psf)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
rx2_open(SF_PRIVATE * psf)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 	BUF_UNION	ubuf ;
84 	int error, marker, length, glob_offset, slce_count, frames ;
85 	int sdat_length = 0, slce_total = 0 ;
86 	int n_channels ;
87 
88 
89 	/* So far only doing read. */
90 
91 	psf_binheader_readf (psf, "Epm4", 0, &marker, &length) ;
92 
93 	if (marker != CAT_MARKER)
94 	{	psf_log_printf (psf, "length : %d\n", length) ;
95 		return -1000 ;
96 		} ;
97 
98 	if (length != psf->filelength - 8)
99 		psf_log_printf (psf, "%M : %d (should be %d)\n", marker, length, psf->filelength - 8) ;
100 	else
101 		psf_log_printf (psf, "%M : %d\n", marker, length) ;
102 
103 	/* 'REX2' marker */
104 	psf_binheader_readf (psf, "m", &marker) ;
105 	psf_log_printf (psf, "%M", marker) ;
106 
107 	/* 'HEAD' marker */
108 	psf_binheader_readf (psf, "m", &marker) ;
109 	psf_log_printf (psf, "%M\n", marker) ;
110 
111 	/* Grab 'GLOB' offset. */
112 	psf_binheader_readf (psf, "E4", &glob_offset) ;
113 	glob_offset += 0x14 ;	/* Add the current file offset. */
114 
115 	/* Jump to offset 0x30 */
116 	psf_binheader_readf (psf, "p", 0x30) ;
117 
118 	/* Get name length */
119 	length = 0 ;
120 	psf_binheader_readf (psf, "1", &length) ;
121 	if (length >= SIGNED_SIZEOF (ubuf.cbuf))
122 	{	psf_log_printf (psf, "  Text : %d *** Error : Too sf_count_t!\n") ;
123 		return -1001 ;
124 		}
125 
126 	memset (ubuf.cbuf, 0, sizeof (ubuf.cbuf)) ;
127 	psf_binheader_readf (psf, "b", ubuf.cbuf, length) ;
128 	psf_log_printf (psf, " Text : \"%s\"\n", ubuf.cbuf) ;
129 
130 	/* Jump to GLOB offset position. */
131 	if (glob_offset & 1)
132 		glob_offset ++ ;
133 
134 	psf_binheader_readf (psf, "p", glob_offset) ;
135 
136 	slce_count = 0 ;
137 	/* GLOB */
138 	while (1)
139 	{	psf_binheader_readf (psf, "m", &marker) ;
140 
141 		if (marker != SLCE_MARKER && slce_count > 0)
142 		{	psf_log_printf (psf, "   SLCE count : %d\n", slce_count) ;
143 			slce_count = 0 ;
144 			}
145 		switch (marker)
146 		{	case GLOB_MARKER:
147 					psf_binheader_readf (psf, "E4", &length) ;
148 					psf_log_printf (psf, " %M : %d\n", marker, length) ;
149 					psf_binheader_readf (psf, "j", length) ;
150 					break ;
151 
152 			case RECY_MARKER:
153 					psf_binheader_readf (psf, "E4", &length) ;
154 					psf_log_printf (psf, " %M : %d\n", marker, length) ;
155 					psf_binheader_readf (psf, "j", (length+1) & 0xFFFFFFFE) ; /* ?????? */
156 					break ;
157 
158 			case CAT_MARKER:
159 					psf_binheader_readf (psf, "E4", &length) ;
160 					psf_log_printf (psf, " %M : %d\n", marker, length) ;
161 					/*-psf_binheader_readf (psf, "j", length) ;-*/
162 					break ;
163 
164 			case DEVL_MARKER:
165 					psf_binheader_readf (psf, "mE4", &marker, &length) ;
166 					psf_log_printf (psf, "  DEVL%M : %d\n", marker, length) ;
167 					if (length & 1)
168 						length ++ ;
169 					psf_binheader_readf (psf, "j", length) ;
170 					break ;
171 
172 			case EQ_MARKER:
173 			case COMP_MARKER:
174 					psf_binheader_readf (psf, "E4", &length) ;
175 					psf_log_printf (psf, "   %M : %d\n", marker, length) ;
176 					/* This is weird!!!! why make this (length - 1) */
177 					if (length & 1)
178 						length ++ ;
179 					psf_binheader_readf (psf, "j", length) ;
180 					break ;
181 
182 			case SLCL_MARKER:
183 					psf_log_printf (psf, "  %M\n    (Offset, Next Offset, Type)\n", marker) ;
184 					slce_count = 0 ;
185 					break ;
186 
187 			case SLCE_MARKER:
188 					{	int len [4], indx ;
189 
190 						psf_binheader_readf (psf, "E4444", &len [0], &len [1], &len [2], &len [3]) ;
191 
192 						indx = ((len [3] & 0x0000FFFF) >> 8) & 3 ;
193 
194 						if (len [2] == 1)
195 						{	if (indx != 1)
196 								indx = 3 ;	/* 2 cases, where next slice offset = 1 -> disabled & enabled/hidden */
197 
198 							psf_log_printf (psf, "   %M : (%6d, ?: 0x%X, %s)\n", marker, len [1], (len [3] & 0xFFFF0000) >> 16, marker_type [indx]) ;
199 							}
200 						else
201 						{	slce_total += len [2] ;
202 
203 							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]) ;
204 							} ;
205 
206 						slce_count ++ ;
207 						} ;
208 					break ;
209 
210 			case SINF_MARKER:
211 					psf_binheader_readf (psf, "E4", &length) ;
212 					psf_log_printf (psf, " %M : %d\n", marker, length) ;
213 
214 					psf_binheader_readf (psf, "E2", &n_channels) ;
215 					n_channels = (n_channels & 0x0000FF00) >> 8 ;
216 					psf_log_printf (psf, "  Channels    : %d\n", n_channels) ;
217 
218 					psf_binheader_readf (psf, "E44", &psf->sf.samplerate, &frames) ;
219 					psf->sf.frames = frames ;
220 					psf_log_printf (psf, "  Sample Rate : %d\n", psf->sf.samplerate) ;
221 					psf_log_printf (psf, "  Frames      : %D\n", psf->sf.frames) ;
222 
223 					psf_binheader_readf (psf, "E4", &length) ;
224 					psf_log_printf (psf, "  ??????????? : %d\n", length) ;
225 
226 					psf_binheader_readf (psf, "E4", &length) ;
227 					psf_log_printf (psf, "  ??????????? : %d\n", length) ;
228 					break ;
229 
230 			case SDAT_MARKER:
231 					psf_binheader_readf (psf, "E4", &length) ;
232 
233 				sdat_length = length ;
234 
235 					/* Get the current offset. */
236 					psf->dataoffset = psf_binheader_readf (psf, NULL) ;
237 
238 					if (psf->dataoffset + length != psf->filelength)
239 						psf_log_printf (psf, " %M : %d (should be %d)\n", marker, length, psf->dataoffset + psf->filelength) ;
240 					else
241 						psf_log_printf (psf, " %M : %d\n", marker, length) ;
242 					break ;
243 
244 			default :
245 					psf_log_printf (psf, "Unknown marker : 0x%X %M", marker, marker) ;
246 					return -1003 ;
247 					break ;
248 			} ;
249 
250 		/* SDAT always last marker in file. */
251 		if (marker == SDAT_MARKER)
252 			break ;
253 		} ;
254 
255 	puts (psf->parselog.buf) ;
256 	puts ("-----------------------------------") ;
257 
258 	printf ("SDAT length  : %d\n", sdat_length) ;
259 	printf ("SLCE count   : %d\n", slce_count) ;
260 
261 	/* Hack for zero slice count. */
262 	if (slce_count == 0 && slce_total == 1)
263 		slce_total = frames ;
264 
265 	printf ("SLCE samples : %d\n", slce_total) ;
266 
267 	/* Two bytes per sample. */
268 	printf ("Comp Ratio   : %f:1\n", (2.0 * slce_total * n_channels) / sdat_length) ;
269 
270 	puts (" ") ;
271 
272 	psf->parselog.buf [0] = 0 ;
273 
274 	/* OK, have the header although not too sure what it all means. */
275 
276 	psf->endian = SF_ENDIAN_BIG ;
277 
278 	psf->datalength = psf->filelength - psf->dataoffset ;
279 
280  	if (psf_fseek (psf, psf->dataoffset, SEEK_SET))
281 		return SFE_BAD_SEEK ;
282 
283 	psf->sf.format = (SF_FORMAT_REX2 | SF_FORMAT_DWVW_12) ;
284 
285 	psf->sf.channels	= 1 ;
286 	psf->bytewidth		= 2 ;
287 	psf->blockwidth		= psf->sf.channels * psf->bytewidth ;
288 
289 	if ((error = dwvw_init (psf, 16)))
290 		return error ;
291 
292 	psf->container_close = rx2_close ;
293 
294 	if (! psf->sf.frames && psf->blockwidth)
295 		psf->sf.frames = psf->datalength / psf->blockwidth ;
296 
297 	/* All done. */
298 
299 	return 0 ;
300 } /* rx2_open */
301 
302 /*------------------------------------------------------------------------------
303 */
304 
305 static int
rx2_close(SF_PRIVATE * psf)306 rx2_close	(SF_PRIVATE *psf)
307 {
308 	if (psf->file.mode == SFM_WRITE)
309 	{	/*  Now we know for certain the length of the file we can re-write
310 		**	correct values for the FORM, 8SVX and BODY chunks.
311 		*/
312 
313 		} ;
314 
315 	return 0 ;
316 } /* rx2_close */
317 
318 #endif
319