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 32int 33rx2_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*/ 70static int rx2_close (SF_PRIVATE *psf) ; 71 72/*------------------------------------------------------------------------------ 73** Public functions. 74*/ 75 76int 77rx2_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 305static int 306rx2_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