1/* 2** Copyright (C) 2008-2018 Erik de Castro Lopo <erikd@mega-nerd.com> 3** Copyright (C) 2009 Uli Franke <cls@nebadje.org> 4** 5** This program is free software; you can redistribute it and/or modify 6** it under the terms of the GNU Lesser General Public License as published by 7** the Free Software Foundation; either version 2.1 of the License, or 8** (at your option) any later version. 9** 10** This program is distributed in the hope that it will be useful, 11** but WITHOUT ANY WARRANTY; without even the implied warranty of 12** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13** GNU Lesser General Public License for more details. 14** 15** You should have received a copy of the GNU Lesser General Public License 16** along with this program; if not, write to the Free Software 17** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 18*/ 19 20/* 21** This format documented at: 22** http://www.sr.se/utveckling/tu/bwf/prog/RF_64v1_4.pdf 23** 24** But this may be a better reference: 25** http://www.ebu.ch/CMSimages/en/tec_doc_t3306-2007_tcm6-42570.pdf 26*/ 27 28#include "sfconfig.h" 29 30#include <stdio.h> 31#include <fcntl.h> 32#include <string.h> 33#include <ctype.h> 34 35#include "sndfile.h" 36#include "sfendian.h" 37#include "common.h" 38#include "wavlike.h" 39 40/*------------------------------------------------------------------------------ 41** Macros to handle big/little endian issues. 42*/ 43#define RF64_MARKER MAKE_MARKER ('R', 'F', '6', '4') 44#define RIFF_MARKER MAKE_MARKER ('R', 'I', 'F', 'F') 45#define JUNK_MARKER MAKE_MARKER ('J', 'U', 'N', 'K') 46#define FFFF_MARKER MAKE_MARKER (0xff, 0xff, 0xff, 0xff) 47#define WAVE_MARKER MAKE_MARKER ('W', 'A', 'V', 'E') 48#define ds64_MARKER MAKE_MARKER ('d', 's', '6', '4') 49#define fmt_MARKER MAKE_MARKER ('f', 'm', 't', ' ') 50#define fact_MARKER MAKE_MARKER ('f', 'a', 'c', 't') 51#define data_MARKER MAKE_MARKER ('d', 'a', 't', 'a') 52 53#define bext_MARKER MAKE_MARKER ('b', 'e', 'x', 't') 54#define cart_MARKER MAKE_MARKER ('c', 'a', 'r', 't') 55#define OggS_MARKER MAKE_MARKER ('O', 'g', 'g', 'S') 56#define wvpk_MARKER MAKE_MARKER ('w', 'v', 'p', 'k') 57#define LIST_MARKER MAKE_MARKER ('L', 'I', 'S', 'T') 58 59/* 60** The file size limit in bytes below which we can, if requested, write this 61** file as a RIFF/WAVE file. 62*/ 63 64#define RIFF_DOWNGRADE_BYTES ((sf_count_t) 0xffffffff) 65 66/*------------------------------------------------------------------------------ 67** Private static functions. 68*/ 69 70static int rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) ; 71static int rf64_write_header (SF_PRIVATE *psf, int calc_length) ; 72static int rf64_write_tailer (SF_PRIVATE *psf) ; 73static int rf64_close (SF_PRIVATE *psf) ; 74static int rf64_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize) ; 75 76static int rf64_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) ; 77static SF_CHUNK_ITERATOR * rf64_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) ; 78static int rf64_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ; 79static int rf64_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) ; 80 81/*------------------------------------------------------------------------------ 82** Public function. 83*/ 84 85int 86rf64_open (SF_PRIVATE *psf) 87{ WAVLIKE_PRIVATE *wpriv ; 88 int subformat, error = 0 ; 89 int blockalign, framesperblock ; 90 91 if ((wpriv = calloc (1, sizeof (WAVLIKE_PRIVATE))) == NULL) 92 return SFE_MALLOC_FAILED ; 93 psf->container_data = wpriv ; 94 wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ; 95 96 /* All RF64 files are little endian. */ 97 psf->endian = SF_ENDIAN_LITTLE ; 98 99 psf->strings.flags = SF_STR_ALLOW_START | SF_STR_ALLOW_END ; 100 101 if (psf->file.mode == SFM_READ || (psf->file.mode == SFM_RDWR && psf->filelength > 0)) 102 { if ((error = rf64_read_header (psf, &blockalign, &framesperblock)) != 0) 103 return error ; 104 105 psf->next_chunk_iterator = rf64_next_chunk_iterator ; 106 psf->get_chunk_size = rf64_get_chunk_size ; 107 psf->get_chunk_data = rf64_get_chunk_data ; 108 } ; 109 110 if ((psf->sf.format & SF_FORMAT_TYPEMASK) != SF_FORMAT_RF64) 111 return SFE_BAD_OPEN_FORMAT ; 112 113 subformat = psf->sf.format & SF_FORMAT_SUBMASK ; 114 115 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) 116 { if (psf->is_pipe) 117 return SFE_NO_PIPE_WRITE ; 118 119 psf->blockwidth = psf->bytewidth * psf->sf.channels ; 120 121 if ((error = rf64_write_header (psf, SF_FALSE))) 122 return error ; 123 124 psf->write_header = rf64_write_header ; 125 psf->set_chunk = rf64_set_chunk ; 126 } ; 127 128 psf->container_close = rf64_close ; 129 psf->command = rf64_command ; 130 131 switch (subformat) 132 { case SF_FORMAT_PCM_U8 : 133 case SF_FORMAT_PCM_16 : 134 case SF_FORMAT_PCM_24 : 135 case SF_FORMAT_PCM_32 : 136 error = pcm_init (psf) ; 137 break ; 138 139 case SF_FORMAT_ULAW : 140 error = ulaw_init (psf) ; 141 break ; 142 143 case SF_FORMAT_ALAW : 144 error = alaw_init (psf) ; 145 break ; 146 147 /* Lite remove start */ 148 case SF_FORMAT_FLOAT : 149 error = float32_init (psf) ; 150 break ; 151 152 case SF_FORMAT_DOUBLE : 153 error = double64_init (psf) ; 154 break ; 155 156 /* Lite remove end */ 157 158 default : return SFE_UNIMPLEMENTED ; 159 } ; 160 161 return error ; 162} /* rf64_open */ 163 164/*------------------------------------------------------------------------------ 165*/ 166enum 167{ HAVE_ds64 = 0x01, 168 HAVE_fmt = 0x02, 169 HAVE_bext = 0x04, 170 HAVE_data = 0x08, 171 HAVE_cart = 0x10, 172 HAVE_PEAK = 0x20, 173 HAVE_other = 0x40 174} ; 175 176#define HAVE_CHUNK(CHUNK) ((parsestage & CHUNK) != 0) 177 178static int 179rf64_read_header (SF_PRIVATE *psf, int *blockalign, int *framesperblock) 180{ WAVLIKE_PRIVATE *wpriv ; 181 WAV_FMT *wav_fmt ; 182 sf_count_t riff_size = 0, frame_count = 0, ds64_datalength = 0 ; 183 uint32_t marks [2], marker, chunk_size, parsestage = 0 ; 184 int error, done = 0, format = 0 ; 185 186 if ((wpriv = psf->container_data) == NULL) 187 return SFE_INTERNAL ; 188 wav_fmt = &wpriv->wav_fmt ; 189 190 /* Set position to start of file to begin reading header. */ 191 psf_binheader_readf (psf, "pmmm", 0, &marker, marks, marks + 1) ; 192 if (marker != RF64_MARKER || marks [1] != WAVE_MARKER) 193 return SFE_RF64_NOT_RF64 ; 194 195 if (marks [0] == FFFF_MARKER) 196 psf_log_printf (psf, "%M\n %M\n", RF64_MARKER, WAVE_MARKER) ; 197 else 198 psf_log_printf (psf, "%M : 0x%x (should be 0xFFFFFFFF)\n %M\n", RF64_MARKER, WAVE_MARKER) ; 199 200 while (!done) 201 { 202 marker = chunk_size = 0 ; 203 psf_binheader_readf (psf, "em4", &marker, &chunk_size) ; 204 205 if (marker == 0) 206 { sf_count_t pos = psf_ftell (psf) ; 207 psf_log_printf (psf, "Have 0 marker at position %D (0x%x).\n", pos, pos) ; 208 break ; 209 } ; 210 211 psf_store_read_chunk_u32 (&psf->rchunks, marker, psf_ftell (psf), chunk_size) ; 212 213 switch (marker) 214 { case ds64_MARKER : 215 if (parsestage & HAVE_ds64) 216 { psf_log_printf (psf, "*** Second 'ds64' chunk?\n") ; 217 break ; 218 } ; 219 220 { unsigned int table_len, bytesread ; 221 222 /* Read ds64 sizes (3 8-byte words). */ 223 bytesread = psf_binheader_readf (psf, "888", &riff_size, &ds64_datalength, &frame_count) ; 224 225 /* Read table length. */ 226 bytesread += psf_binheader_readf (psf, "4", &table_len) ; 227 /* Skip table for now. (this was "table_len + 4", why?) */ 228 bytesread += psf_binheader_readf (psf, "j", table_len) ; 229 230 if (chunk_size == bytesread) 231 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ; 232 else if (chunk_size >= bytesread + 4) 233 { unsigned int next ; 234 psf_binheader_readf (psf, "m", &next) ; 235 if (next == fmt_MARKER) 236 { psf_log_printf (psf, "%M : %u (should be %u)\n", marker, chunk_size, bytesread) ; 237 psf_binheader_readf (psf, "j", -4) ; 238 } 239 else 240 { psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ; 241 psf_binheader_readf (psf, "j", chunk_size - bytesread - 4) ; 242 } ; 243 } ; 244 245 if (psf->filelength != riff_size + 8) 246 psf_log_printf (psf, " Riff size : %D (should be %D)\n", riff_size, psf->filelength - 8) ; 247 else 248 psf_log_printf (psf, " Riff size : %D\n", riff_size) ; 249 250 psf_log_printf (psf, " Data size : %D\n", ds64_datalength) ; 251 252 psf_log_printf (psf, " Frames : %D\n", frame_count) ; 253 psf_log_printf (psf, " Table length : %u\n", table_len) ; 254 255 } ; 256 parsestage |= HAVE_ds64 ; 257 break ; 258 259 case fmt_MARKER: 260 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ; 261 if ((error = wavlike_read_fmt_chunk (psf, chunk_size)) != 0) 262 return error ; 263 format = wav_fmt->format ; 264 parsestage |= HAVE_fmt ; 265 break ; 266 267 case bext_MARKER : 268 if ((error = wavlike_read_bext_chunk (psf, chunk_size)) != 0) 269 return error ; 270 parsestage |= HAVE_bext ; 271 break ; 272 273 case cart_MARKER : 274 if ((error = wavlike_read_cart_chunk (psf, chunk_size)) != 0) 275 return error ; 276 parsestage |= HAVE_cart ; 277 break ; 278 279 case INFO_MARKER : 280 case LIST_MARKER : 281 if ((error = wavlike_subchunk_parse (psf, marker, chunk_size)) != 0) 282 return error ; 283 parsestage |= HAVE_other ; 284 break ; 285 286 case PEAK_MARKER : 287 if ((parsestage & (HAVE_ds64 | HAVE_fmt)) != (HAVE_ds64 | HAVE_fmt)) 288 return SFE_RF64_PEAK_B4_FMT ; 289 290 parsestage |= HAVE_PEAK ; 291 292 psf_log_printf (psf, "%M : %u\n", marker, chunk_size) ; 293 if ((error = wavlike_read_peak_chunk (psf, chunk_size)) != 0) 294 return error ; 295 psf->peak_info->peak_loc = ((parsestage & HAVE_data) == 0) ? SF_PEAK_START : SF_PEAK_END ; 296 break ; 297 298 case data_MARKER : 299 /* see wav for more sophisticated parsing -> implement state machine with parsestage */ 300 301 if (HAVE_CHUNK (HAVE_ds64)) 302 { if (chunk_size == 0xffffffff) 303 psf_log_printf (psf, "%M : 0x%x\n", marker, chunk_size) ; 304 else 305 psf_log_printf (psf, "%M : 0x%x (should be 0xffffffff\n", marker, chunk_size) ; 306 psf->datalength = ds64_datalength ; 307 } 308 else 309 { if (chunk_size == 0xffffffff) 310 { psf_log_printf (psf, "%M : 0x%x\n", marker, chunk_size) ; 311 psf_log_printf (psf, " *** Data length not specified no 'ds64' chunk.\n") ; 312 } 313 else 314 { psf_log_printf (psf, "%M : 0x%x\n**** Weird, RF64 file without a 'ds64' chunk and no valid 'data' size.\n", marker, chunk_size) ; 315 psf->datalength = chunk_size ; 316 } ; 317 } ; 318 319 psf->dataoffset = psf_ftell (psf) ; 320 321 if (psf->dataoffset > 0) 322 { if (chunk_size == 0 && riff_size == 8 && psf->filelength > 44) 323 { psf_log_printf (psf, " *** Looks like a WAV file which wasn't closed properly. Fixing it.\n") ; 324 psf->datalength = psf->filelength - psf->dataoffset ; 325 } ; 326 327 /* Only set dataend if there really is data at the end. */ 328 if (psf->datalength + psf->dataoffset < psf->filelength) 329 psf->dataend = psf->datalength + psf->dataoffset ; 330 331 if (!psf->sf.seekable || psf->dataoffset < 0) 332 break ; 333 334 /* Seek past data and continue reading header. */ 335 psf_fseek (psf, psf->datalength, SEEK_CUR) ; 336 337 if (psf_ftell (psf) != psf->datalength + psf->dataoffset) 338 psf_log_printf (psf, " *** psf_fseek past end error ***\n") ; 339 } ; 340 break ; 341 342 case JUNK_MARKER : 343 case PAD_MARKER : 344 psf_log_printf (psf, "%M : %d\n", marker, chunk_size) ; 345 psf_binheader_readf (psf, "j", chunk_size) ; 346 break ; 347 348 default : 349 if (chunk_size >= 0xffff0000) 350 { psf_log_printf (psf, "*** Unknown chunk marker (%X) at position %D with length %u. Exiting parser.\n", marker, psf_ftell (psf) - 8, chunk_size) ; 351 done = SF_TRUE ; 352 break ; 353 } ; 354 355 if (isprint ((marker >> 24) & 0xFF) && isprint ((marker >> 16) & 0xFF) 356 && isprint ((marker >> 8) & 0xFF) && isprint (marker & 0xFF)) 357 { psf_log_printf (psf, "*** %M : %d (unknown marker)\n", marker, chunk_size) ; 358 psf_binheader_readf (psf, "j", chunk_size) ; 359 break ; 360 } ; 361 if (psf_ftell (psf) & 0x03) 362 { psf_log_printf (psf, " Unknown chunk marker at position 0x%x. Resynching.\n", chunk_size - 4) ; 363 psf_binheader_readf (psf, "j", -3) ; 364 break ; 365 } ; 366 psf_log_printf (psf, "*** Unknown chunk marker (0x%X) at position 0x%X. Exiting parser.\n", marker, psf_ftell (psf) - 4) ; 367 done = SF_TRUE ; 368 break ; 369 } ; /* switch (marker) */ 370 371 /* The 'data' chunk, a chunk size of 0xffffffff means that the 'data' chunk size 372 ** is actually given by the ds64_datalength field. 373 */ 374 if (marker != data_MARKER && chunk_size >= psf->filelength) 375 { psf_log_printf (psf, "*** Chunk size %u > file length %D. Exiting parser.\n", chunk_size, psf->filelength) ; 376 break ; 377 } ; 378 379 if (psf_ftell (psf) >= psf->filelength - SIGNED_SIZEOF (marker)) 380 { psf_log_printf (psf, "End\n") ; 381 break ; 382 } ; 383 } ; 384 385 if (psf->dataoffset <= 0) 386 return SFE_RF64_NO_DATA ; 387 388 if (psf->sf.channels < 1) 389 return SFE_CHANNEL_COUNT_ZERO ; 390 391 if (psf->sf.channels > SF_MAX_CHANNELS) 392 return SFE_CHANNEL_COUNT ; 393 394 /* WAVs can be little or big endian */ 395 psf->endian = psf->rwf_endian ; 396 397 psf_fseek (psf, psf->dataoffset, SEEK_SET) ; 398 399 if (psf->is_pipe == 0) 400 { /* 401 ** Check for 'wvpk' at the start of the DATA section. Not able to 402 ** handle this. 403 */ 404 psf_binheader_readf (psf, "4", &marker) ; 405 if (marker == wvpk_MARKER || marker == OggS_MARKER) 406 return SFE_WAV_WVPK_DATA ; 407 } ; 408 409 /* Seek to start of DATA section. */ 410 psf_fseek (psf, psf->dataoffset, SEEK_SET) ; 411 412 if (psf->blockwidth) 413 { if (psf->filelength - psf->dataoffset < psf->datalength) 414 psf->sf.frames = (psf->filelength - psf->dataoffset) / psf->blockwidth ; 415 else 416 psf->sf.frames = psf->datalength / psf->blockwidth ; 417 } ; 418 419 if (frame_count != psf->sf.frames) 420 psf_log_printf (psf, "*** Calculated frame count %d does not match value from 'ds64' chunk of %d.\n", psf->sf.frames, frame_count) ; 421 422 switch (format) 423 { 424 case WAVE_FORMAT_EXTENSIBLE : 425 426 /* with WAVE_FORMAT_EXTENSIBLE the psf->sf.format field is already set. We just have to set the major to rf64 */ 427 psf->sf.format = (psf->sf.format & ~SF_FORMAT_TYPEMASK) | SF_FORMAT_RF64 ; 428 429 if (psf->sf.format == (SF_FORMAT_WAVEX | SF_FORMAT_MS_ADPCM)) 430 { *blockalign = wav_fmt->msadpcm.blockalign ; 431 *framesperblock = wav_fmt->msadpcm.samplesperblock ; 432 } ; 433 break ; 434 435 case WAVE_FORMAT_PCM : 436 psf->sf.format = SF_FORMAT_RF64 | u_bitwidth_to_subformat (psf->bytewidth * 8) ; 437 break ; 438 439 case WAVE_FORMAT_MULAW : 440 case IBM_FORMAT_MULAW : 441 psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_ULAW) ; 442 break ; 443 444 case WAVE_FORMAT_ALAW : 445 case IBM_FORMAT_ALAW : 446 psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_ALAW) ; 447 break ; 448 449 case WAVE_FORMAT_MS_ADPCM : 450 psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_MS_ADPCM) ; 451 *blockalign = wav_fmt->msadpcm.blockalign ; 452 *framesperblock = wav_fmt->msadpcm.samplesperblock ; 453 break ; 454 455 case WAVE_FORMAT_IMA_ADPCM : 456 psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_IMA_ADPCM) ; 457 *blockalign = wav_fmt->ima.blockalign ; 458 *framesperblock = wav_fmt->ima.samplesperblock ; 459 break ; 460 461 case WAVE_FORMAT_GSM610 : 462 psf->sf.format = (SF_FORMAT_RF64 | SF_FORMAT_GSM610) ; 463 break ; 464 465 case WAVE_FORMAT_IEEE_FLOAT : 466 psf->sf.format = SF_FORMAT_RF64 ; 467 psf->sf.format |= (psf->bytewidth == 8) ? SF_FORMAT_DOUBLE : SF_FORMAT_FLOAT ; 468 break ; 469 470 case WAVE_FORMAT_G721_ADPCM : 471 psf->sf.format = SF_FORMAT_RF64 | SF_FORMAT_G721_32 ; 472 break ; 473 474 default : return SFE_UNIMPLEMENTED ; 475 } ; 476 477 if (wpriv->fmt_is_broken) 478 wavlike_analyze (psf) ; 479 480 /* Only set the format endian-ness if its non-standard big-endian. */ 481 if (psf->endian == SF_ENDIAN_BIG) 482 psf->sf.format |= SF_ENDIAN_BIG ; 483 484 return 0 ; 485} /* rf64_read_header */ 486 487/* known WAVEFORMATEXTENSIBLE GUIDS */ 488static const EXT_SUBFORMAT MSGUID_SUBTYPE_PCM = 489{ 0x00000001, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } 490} ; 491 492#if 0 493static const EXT_SUBFORMAT MSGUID_SUBTYPE_MS_ADPCM = 494{ 0x00000002, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } 495} ; 496#endif 497 498static const EXT_SUBFORMAT MSGUID_SUBTYPE_IEEE_FLOAT = 499{ 0x00000003, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } 500} ; 501 502static const EXT_SUBFORMAT MSGUID_SUBTYPE_ALAW = 503{ 0x00000006, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } 504} ; 505 506static const EXT_SUBFORMAT MSGUID_SUBTYPE_MULAW = 507{ 0x00000007, 0x0000, 0x0010, { 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 } 508} ; 509 510/* 511** the next two are from 512** http://dream.cs.bath.ac.uk/researchdev/wave-ex/bformat.html 513*/ 514static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM = 515{ 0x00000001, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } 516} ; 517 518static const EXT_SUBFORMAT MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT = 519{ 0x00000003, 0x0721, 0x11d3, { 0x86, 0x44, 0xC8, 0xC1, 0xCA, 0x00, 0x00, 0x00 } 520} ; 521 522 523static int 524rf64_write_fmt_chunk (SF_PRIVATE *psf) 525{ WAVLIKE_PRIVATE *wpriv ; 526 int subformat, fmt_size ; 527 528 if ((wpriv = psf->container_data) == NULL) 529 return SFE_INTERNAL ; 530 531 subformat = psf->sf.format & SF_FORMAT_SUBMASK ; 532 533 /* initial section (same for all, it appears) */ 534 switch (subformat) 535 { case SF_FORMAT_PCM_U8 : 536 case SF_FORMAT_PCM_16 : 537 case SF_FORMAT_PCM_24 : 538 case SF_FORMAT_PCM_32 : 539 case SF_FORMAT_FLOAT : 540 case SF_FORMAT_DOUBLE : 541 case SF_FORMAT_ULAW : 542 case SF_FORMAT_ALAW : 543 fmt_size = 2 + 2 + 4 + 4 + 2 + 2 + 2 + 2 + 4 + 4 + 2 + 2 + 8 ; 544 545 /* fmt : format, channels, samplerate */ 546 psf_binheader_writef (psf, "4224", BHW4 (fmt_size), BHW2 (WAVE_FORMAT_EXTENSIBLE), BHW2 (psf->sf.channels), BHW4 (psf->sf.samplerate)) ; 547 /* fmt : bytespersec */ 548 psf_binheader_writef (psf, "4", BHW4 (psf->sf.samplerate * psf->bytewidth * psf->sf.channels)) ; 549 /* fmt : blockalign, bitwidth */ 550 psf_binheader_writef (psf, "22", BHW2 (psf->bytewidth * psf->sf.channels), BHW2 (psf->bytewidth * 8)) ; 551 552 /* cbSize 22 is sizeof (WAVEFORMATEXTENSIBLE) - sizeof (WAVEFORMATEX) */ 553 psf_binheader_writef (psf, "2", BHW2 (22)) ; 554 555 /* wValidBitsPerSample, for our use same as bitwidth as we use it fully */ 556 psf_binheader_writef (psf, "2", BHW2 (psf->bytewidth * 8)) ; 557 558 /* For an Ambisonic file set the channel mask to zero. 559 ** Otherwise use a default based on the channel count. 560 */ 561 if (wpriv->wavex_ambisonic != SF_AMBISONIC_NONE) 562 psf_binheader_writef (psf, "4", BHW4 (0)) ; 563 else if (wpriv->wavex_channelmask != 0) 564 psf_binheader_writef (psf, "4", BHW4 (wpriv->wavex_channelmask)) ; 565 else 566 { /* 567 ** Ok some liberty is taken here to use the most commonly used channel masks 568 ** instead of "no mapping". If you really want to use "no mapping" for 8 channels and less 569 ** please don't use wavex. (otherwise we'll have to create a new SF_COMMAND) 570 */ 571 switch (psf->sf.channels) 572 { case 1 : /* center channel mono */ 573 psf_binheader_writef (psf, "4", BHW4 (0x4)) ; 574 break ; 575 576 case 2 : /* front left and right */ 577 psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2)) ; 578 break ; 579 580 case 4 : /* Quad */ 581 psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x10 | 0x20)) ; 582 break ; 583 584 case 6 : /* 5.1 */ 585 psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20)) ; 586 break ; 587 588 case 8 : /* 7.1 */ 589 psf_binheader_writef (psf, "4", BHW4 (0x1 | 0x2 | 0x4 | 0x8 | 0x10 | 0x20 | 0x40 | 0x80)) ; 590 break ; 591 592 default : /* 0 when in doubt , use direct out, ie NO mapping*/ 593 psf_binheader_writef (psf, "4", BHW4 (0x0)) ; 594 break ; 595 } ; 596 } ; 597 break ; 598 599 case SF_FORMAT_MS_ADPCM : /* Todo, GUID exists might have different header as per wav_write_header */ 600 default : 601 return SFE_UNIMPLEMENTED ; 602 } ; 603 604 /* GUID section, different for each */ 605 606 switch (subformat) 607 { case SF_FORMAT_PCM_U8 : 608 case SF_FORMAT_PCM_16 : 609 case SF_FORMAT_PCM_24 : 610 case SF_FORMAT_PCM_32 : 611 wavlike_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ? 612 &MSGUID_SUBTYPE_PCM : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_PCM) ; 613 break ; 614 615 case SF_FORMAT_FLOAT : 616 case SF_FORMAT_DOUBLE : 617 wavlike_write_guid (psf, wpriv->wavex_ambisonic == SF_AMBISONIC_NONE ? 618 &MSGUID_SUBTYPE_IEEE_FLOAT : &MSGUID_SUBTYPE_AMBISONIC_B_FORMAT_IEEE_FLOAT) ; 619 break ; 620 621 case SF_FORMAT_ULAW : 622 wavlike_write_guid (psf, &MSGUID_SUBTYPE_MULAW) ; 623 break ; 624 625 case SF_FORMAT_ALAW : 626 wavlike_write_guid (psf, &MSGUID_SUBTYPE_ALAW) ; 627 break ; 628 629 default : return SFE_UNIMPLEMENTED ; 630 } ; 631 632 return 0 ; 633} /* rf64_write_fmt_chunk */ 634 635 636static int 637rf64_write_header (SF_PRIVATE *psf, int calc_length) 638{ sf_count_t current, pad_size ; 639 int error = 0, has_data = SF_FALSE, add_fact_chunk = 0 ; 640 WAVLIKE_PRIVATE *wpriv ; 641 642 if ((wpriv = psf->container_data) == NULL) 643 return SFE_INTERNAL ; 644 645 current = psf_ftell (psf) ; 646 647 if (psf->dataoffset > 0 && current > psf->dataoffset) 648 has_data = SF_TRUE ; 649 650 if (calc_length) 651 { psf->filelength = psf_get_filelen (psf) ; 652 psf->datalength = psf->filelength - psf->dataoffset ; 653 654 if (psf->dataend) 655 psf->datalength -= psf->filelength - psf->dataend ; 656 657 if (psf->bytewidth > 0) 658 psf->sf.frames = psf->datalength / (psf->bytewidth * psf->sf.channels) ; 659 } ; 660 661 /* Reset the current header length to zero. */ 662 psf->header.ptr [0] = 0 ; 663 psf->header.indx = 0 ; 664 psf_fseek (psf, 0, SEEK_SET) ; 665 666 if (wpriv->rf64_downgrade && psf->filelength < RIFF_DOWNGRADE_BYTES) 667 { psf_binheader_writef (psf, "etm8m", BHWm (RIFF_MARKER), BHW8 ((psf->filelength < 8) ? 8 : psf->filelength - 8), BHWm (WAVE_MARKER)) ; 668 psf_binheader_writef (psf, "m4z", BHWm (JUNK_MARKER), BHW4 (24), BHWz (24)) ; 669 add_fact_chunk = 1 ; 670 } 671 else 672 { psf_binheader_writef (psf, "em4m", BHWm (RF64_MARKER), BHW4 (0xffffffff), BHWm (WAVE_MARKER)) ; 673 /* Currently no table. */ 674 psf_binheader_writef (psf, "m48884", BHWm (ds64_MARKER), BHW4 (28), BHW8 (psf->filelength - 8), BHW8 (psf->datalength), BHW8 (psf->sf.frames), BHW4 (0)) ; 675 } ; 676 677 /* WAVE and 'fmt ' markers. */ 678 psf_binheader_writef (psf, "m", BHWm (fmt_MARKER)) ; 679 680 /* Write the 'fmt ' chunk. */ 681 switch (psf->sf.format & SF_FORMAT_TYPEMASK) 682 { case SF_FORMAT_WAV : 683 psf_log_printf (psf, "ooops SF_FORMAT_WAV\n") ; 684 return SFE_UNIMPLEMENTED ; 685 break ; 686 687 case SF_FORMAT_WAVEX : 688 case SF_FORMAT_RF64 : 689 if ((error = rf64_write_fmt_chunk (psf)) != 0) 690 return error ; 691 if (add_fact_chunk) 692 psf_binheader_writef (psf, "tm48", BHWm (fact_MARKER), BHW4 (4), BHW8 (psf->sf.frames)) ; 693 break ; 694 695 default : 696 return SFE_UNIMPLEMENTED ; 697 } ; 698 699 if (psf->broadcast_16k != NULL) 700 wavlike_write_bext_chunk (psf) ; 701 702 if (psf->cart_16k != NULL) 703 wavlike_write_cart_chunk (psf) ; 704 705 /* The LIST/INFO chunk. */ 706 if (psf->strings.flags & SF_STR_LOCATE_START) 707 wavlike_write_strings (psf, SF_STR_LOCATE_START) ; 708 709 if (psf->peak_info != NULL && psf->peak_info->peak_loc == SF_PEAK_START) 710 wavlike_write_peak_chunk (psf) ; 711 712 /* Write custom headers. */ 713 if (psf->wchunks.used > 0) 714 wavlike_write_custom_chunks (psf) ; 715 716#if 0 717 if (psf->instrument != NULL) 718 { int tmp ; 719 double dtune = (double) (0x40000000) / 25.0 ; 720 721 psf_binheader_writef (psf, "m4", BHWm (smpl_MARKER), BHW4 (9 * 4 + psf->instrument->loop_count * 6 * 4)) ; 722 psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (0)) ; /* Manufacturer zero is everyone */ 723 tmp = (int) (1.0e9 / psf->sf.samplerate) ; /* Sample period in nano seconds */ 724 psf_binheader_writef (psf, "44", BHW4 (tmp), BHW4 (psf->instrument->basenote)) ; 725 tmp = (unsigned int) (psf->instrument->detune * dtune + 0.5) ; 726 psf_binheader_writef (psf, "4", BHW4 (tmp)) ; 727 psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (0)) ; /* SMTPE format */ 728 psf_binheader_writef (psf, "44", BHW4 (psf->instrument->loop_count), BHW4 (0)) ; 729 730 for (tmp = 0 ; tmp < psf->instrument->loop_count ; tmp++) 731 { int type ; 732 733 type = psf->instrument->loops [tmp].mode ; 734 type = (type == SF_LOOP_FORWARD ? 0 : type == SF_LOOP_BACKWARD ? 2 : type == SF_LOOP_ALTERNATING ? 1 : 32) ; 735 736 psf_binheader_writef (psf, "44", BHW4 (tmp), BHW4 (type)) ; 737 psf_binheader_writef (psf, "44", BHW4 (psf->instrument->loops [tmp].start), BHW4 (psf->instrument->loops [tmp].end)) ; 738 psf_binheader_writef (psf, "44", BHW4 (0), BHW4 (psf->instrument->loops [tmp].count)) ; 739 } ; 740 } ; 741 742#endif 743 744 /* Padding may be needed if string data sizes change. */ 745 pad_size = psf->dataoffset - 16 - psf->header.indx ; 746 if (pad_size >= 0) 747 psf_binheader_writef (psf, "m4z", BHWm (PAD_MARKER), BHW4 ((unsigned int) pad_size), BHWz (pad_size)) ; 748 749 if (wpriv->rf64_downgrade && (psf->filelength < RIFF_DOWNGRADE_BYTES)) 750 psf_binheader_writef (psf, "tm8", BHWm (data_MARKER), BHW8 (psf->datalength)) ; 751 else 752 psf_binheader_writef (psf, "m4", BHWm (data_MARKER), BHW4 (0xffffffff)) ; 753 754 psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; 755 if (psf->error) 756 return psf->error ; 757 758 if (has_data && psf->dataoffset != psf->header.indx) 759 { psf_log_printf (psf, "Oooops : has_data && psf->dataoffset != psf->header.indx\n") ; 760 return psf->error = SFE_INTERNAL ; 761 } ; 762 763 psf->dataoffset = psf->header.indx ; 764 765 if (!has_data) 766 psf_fseek (psf, psf->dataoffset, SEEK_SET) ; 767 else if (current > 0) 768 psf_fseek (psf, current, SEEK_SET) ; 769 770 return psf->error ; 771} /* rf64_write_header */ 772 773static int 774rf64_write_tailer (SF_PRIVATE *psf) 775{ 776 /* Reset the current header buffer length to zero. */ 777 psf->header.ptr [0] = 0 ; 778 psf->header.indx = 0 ; 779 780 if (psf->bytewidth > 0 && psf->sf.seekable == SF_TRUE) 781 { psf->datalength = psf->sf.frames * psf->bytewidth * psf->sf.channels ; 782 psf->dataend = psf->dataoffset + psf->datalength ; 783 } ; 784 785 if (psf->dataend > 0) 786 psf_fseek (psf, psf->dataend, SEEK_SET) ; 787 else 788 psf->dataend = psf_fseek (psf, 0, SEEK_END) ; 789 790 if (psf->dataend & 1) 791 psf_binheader_writef (psf, "z", BHWz (1)) ; 792 793 if (psf->strings.flags & SF_STR_LOCATE_END) 794 wavlike_write_strings (psf, SF_STR_LOCATE_END) ; 795 796 /* Write the tailer. */ 797 if (psf->header.indx > 0) 798 psf_fwrite (psf->header.ptr, psf->header.indx, 1, psf) ; 799 800 return 0 ; 801} /* rf64_write_tailer */ 802 803static int 804rf64_close (SF_PRIVATE *psf) 805{ 806 if (psf->file.mode == SFM_WRITE || psf->file.mode == SFM_RDWR) 807 { rf64_write_tailer (psf) ; 808 rf64_write_header (psf, SF_TRUE) ; 809 } ; 810 811 return 0 ; 812} /* rf64_close */ 813 814static int 815rf64_command (SF_PRIVATE *psf, int command, void * UNUSED (data), int datasize) 816{ WAVLIKE_PRIVATE *wpriv ; 817 818 if ((wpriv = psf->container_data) == NULL) 819 return SFE_INTERNAL ; 820 821 switch (command) 822 { case SFC_WAVEX_SET_AMBISONIC : 823 if ((SF_CONTAINER (psf->sf.format)) == SF_FORMAT_WAVEX) 824 { if (datasize == SF_AMBISONIC_NONE) 825 wpriv->wavex_ambisonic = SF_AMBISONIC_NONE ; 826 else if (datasize == SF_AMBISONIC_B_FORMAT) 827 wpriv->wavex_ambisonic = SF_AMBISONIC_B_FORMAT ; 828 else 829 return 0 ; 830 } ; 831 return wpriv->wavex_ambisonic ; 832 833 case SFC_WAVEX_GET_AMBISONIC : 834 return wpriv->wavex_ambisonic ; 835 836 case SFC_SET_CHANNEL_MAP_INFO : 837 wpriv->wavex_channelmask = wavlike_gen_channel_mask (psf->channel_map, psf->sf.channels) ; 838 return (wpriv->wavex_channelmask != 0) ; 839 840 case SFC_RF64_AUTO_DOWNGRADE : 841 if (psf->have_written == 0) 842 wpriv->rf64_downgrade = datasize ? SF_TRUE : SF_FALSE ; 843 return wpriv->rf64_downgrade ; 844 845 default : 846 break ; 847 } ; 848 849 return 0 ; 850} /* rf64_command */ 851 852static int 853rf64_set_chunk (SF_PRIVATE *psf, const SF_CHUNK_INFO * chunk_info) 854{ return psf_save_write_chunk (&psf->wchunks, chunk_info) ; 855} /* rf64_set_chunk */ 856 857static SF_CHUNK_ITERATOR * 858rf64_next_chunk_iterator (SF_PRIVATE *psf, SF_CHUNK_ITERATOR * iterator) 859{ return psf_next_chunk_iterator (&psf->rchunks, iterator) ; 860} /* rf64_next_chunk_iterator */ 861 862static int 863rf64_get_chunk_size (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) 864{ int indx ; 865 866 if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0) 867 return SFE_UNKNOWN_CHUNK ; 868 869 chunk_info->datalen = psf->rchunks.chunks [indx].len ; 870 871 return SFE_NO_ERROR ; 872} /* rf64_get_chunk_size */ 873 874static int 875rf64_get_chunk_data (SF_PRIVATE *psf, const SF_CHUNK_ITERATOR * iterator, SF_CHUNK_INFO * chunk_info) 876{ int indx ; 877 sf_count_t pos ; 878 879 if ((indx = psf_find_read_chunk_iterator (&psf->rchunks, iterator)) < 0) 880 return SFE_UNKNOWN_CHUNK ; 881 882 if (chunk_info->data == NULL) 883 return SFE_BAD_CHUNK_DATA_PTR ; 884 885 chunk_info->id_size = psf->rchunks.chunks [indx].id_size ; 886 memcpy (chunk_info->id, psf->rchunks.chunks [indx].id, sizeof (chunk_info->id) / sizeof (*chunk_info->id)) ; 887 888 pos = psf_ftell (psf) ; 889 psf_fseek (psf, psf->rchunks.chunks [indx].offset, SEEK_SET) ; 890 psf_fread (chunk_info->data, SF_MIN (chunk_info->datalen, psf->rchunks.chunks [indx].len), 1, psf) ; 891 psf_fseek (psf, pos, SEEK_SET) ; 892 893 return SFE_NO_ERROR ; 894} /* rf64_get_chunk_data */ 895