Git init
[external/libsndfile.git] / src / rx2.c
1 /*
2 ** Copyright (C) 2001-2009 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