1 /*---------------------------------------------------------------------------* 2 * riff.c * 3 * * 4 * Copyright 2007, 2008 Nuance Communciations, Inc. * 5 * * 6 * Licensed under the Apache License, Version 2.0 (the 'License'); * 7 * you may not use this file except in compliance with the License. * 8 * * 9 * You may obtain a copy of the License at * 10 * http://www.apache.org/licenses/LICENSE-2.0 * 11 * * 12 * Unless required by applicable law or agreed to in writing, software * 13 * distributed under the License is distributed on an 'AS IS' BASIS, * 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * 15 * See the License for the specific language governing permissions and * 16 * limitations under the License. * 17 * * 18 *---------------------------------------------------------------------------*/ 19 20 #include "plog.h" 21 #include "riff.h" 22 23 #define MTAG NULL 24 25 typedef struct ChunkContext_t 26 { 27 char tag[4]; 28 long start; 29 int length; 30 } 31 ChunkContext; 32 33 typedef enum 34 { 35 FIND_RIFF, 36 FIND_CHUNK, 37 FIND_LIST 38 } DescendType; 39 40 int isLittleEndian() 41 { 42 char b[4]; 43 44 *(int *)b = 1; 45 return (int)b[0]; 46 } 47 48 /* waveReadFunc 49 * - converts data to an array of signed shorts 50 * - fills in *length with the number of samples converted 51 * - allocates memory for *samples 52 * - returns GS_OK if conversion was successful or GS_ERROR and an error 53 * message in res if not. If the conversion fails the function must free 54 * all the memory it had allocated before returning. 55 * On entry 56 * wf - points to the WaveFormat structure that describes the data format 57 * cb - data read from the RIFF file 58 * data - descriptor for the "data" chunk 59 */ 60 typedef ESR_ReturnCode(waveReadFunc)(WaveFormat *wf, ChunkContext *data, 61 char *cb, short **samples, int *length, int doSwap); 62 63 static ESR_ReturnCode readPCMWave(WaveFormat *wf, ChunkContext *data, 64 char *cb, short **samples, int *length, int doSwap); 65 static ESR_ReturnCode readMulawWave(WaveFormat *wf, ChunkContext *data, 66 char *cb, short **samples, int *length, int doSwap); 67 static ESR_ReturnCode readAlawWave(WaveFormat *wf, ChunkContext *data, 68 char *cb, short **samples, int *length, int doSwap); 69 70 static struct 71 { 72 int id; 73 waveReadFunc *func; 74 } 75 WaveCodecs[] = { 76 {WAVEFORMAT_PCM, readPCMWave}, 77 {WAVEFORMAT_MULAW, readMulawWave}, 78 {WAVEFORMAT_ALAW, readAlawWave}, 79 {0, 0}, 80 }; 81 82 /************* FIXME: regroup all swap routines outahere; 83 * ditto for audio conversion routines 84 */ 85 86 static void swapInt(int *i) 87 { 88 char *a = (char *)i, t; 89 t = a[0]; 90 a[0] = a[3]; 91 a[3] = t; 92 t = a[1]; 93 a[1] = a[2]; 94 a[2] = t; 95 } 96 97 static void swapShort(short *s) 98 { 99 char *a = (char *)s, t; 100 t = a[0]; 101 a[0] = a[1]; 102 a[1] = t; 103 } 104 105 static int swapConstInt(const int value) 106 { 107 int converted = value; 108 unsigned char *cp = (unsigned char *) & converted; 109 110 *cp ^= *(cp + 3); 111 *(cp + 3) ^= *cp; 112 *cp ^= *(cp + 3); 113 *(cp + 1) ^= *(cp + 2); 114 *(cp + 2) ^= *(cp + 1); 115 *(cp + 1) ^= *(cp + 2); 116 117 return converted; 118 } 119 120 static short swapConstShort(const short value) 121 { 122 short converted = value; 123 unsigned char *cp = (unsigned char *) & converted; 124 unsigned char tmp = *cp; 125 126 *cp = *(cp + 1); 127 *++cp = tmp; 128 129 return converted; 130 } 131 132 /* len == number of bytes to swap 133 */ 134 static void short_byte_swap(short *buf, int len) 135 { 136 char *cp, *end, tmp; 137 138 end = ((char *)buf) + (len << 1); 139 for (cp = (char *)buf; cp < end; cp++) 140 { 141 tmp = *cp; 142 *cp = *(cp + 1); 143 *++cp = tmp; 144 } 145 } 146 147 /* len == number of bytes to swap 148 */ 149 static void int_byte_swap(int *buf, int len) 150 { 151 char *cp, *end; 152 153 end = ((char *)buf) + (len << 2); 154 for (cp = (char *)buf; cp < end; cp += 4) 155 { 156 *cp ^= *(cp + 3); 157 *(cp + 3) ^= *cp; 158 *cp ^= *(cp + 3); 159 *(cp + 1) ^= *(cp + 2); 160 *(cp + 2) ^= *(cp + 1); 161 *(cp + 1) ^= *(cp + 2); 162 } 163 } 164 165 static void swapWaveFormat(WaveFormat *wf) 166 { 167 swapShort(&wf->nFormatTag); 168 swapShort(&wf->nChannels); 169 swapInt(&wf->nSamplesPerSec); 170 swapInt(&wf->nAvgBytesPerSec); 171 swapShort(&wf->nBlockAlign); 172 swapShort(&wf->wBitsPerSample); 173 //swapShort(&wf->cbSize); 174 } 175 176 static int ulaw2linear(unsigned char ulawbyte) 177 { 178 static int exp_lut[8] = 179 { 180 0, 132, 396, 924, 1980, 4092, 8316, 16764 181 }; 182 int sign, exponent, mantissa, sample; 183 184 ulawbyte = ~ulawbyte; 185 sign = (ulawbyte & 0x80); 186 exponent = (ulawbyte >> 4) & 0x07; 187 mantissa = ulawbyte & 0x0F; 188 sample = exp_lut[exponent] + (mantissa << (exponent + 3)); 189 if (sign != 0) sample = -sample; 190 return sample; 191 } 192 193 static int alaw2linear(unsigned char alawbyte) 194 { 195 196 int sign, achord, astep, delta, sample; 197 unsigned char alawcode; 198 static int exp_lut[8] = 199 { 200 1, 1, 2, 4, 8, 16, 32, 64 201 }; 202 alawcode = alawbyte ^ 0x55; 203 sign = (alawcode & 0x80); 204 achord = (alawcode >> 4) & 0x07; 205 astep = alawcode & 0x0F; 206 delta = ((achord == 0) ? 1 : 0); 207 sample = ((2 * astep + 33) * exp_lut[achord]) - 32 * delta; 208 if (sign != 0) sample = -sample; 209 sample = sample * 8; 210 211 return sample; 212 } 213 214 /* Converts PCM wave data 215 * cb: input :1 216 217 */ 218 static ESR_ReturnCode readPCMWave(WaveFormat *wf, ChunkContext *data, 219 char *cb, short **samples, int *length, int doSwap) 220 { 221 int i; 222 if (wf->nChannels != 1) 223 { 224 //GS_SetResult(res,"PCM WAVE file contains more than one data channel", 225 //GS_STATIC); 226 return ESR_FATAL_ERROR; 227 } 228 if (wf->wBitsPerSample != 16 && wf->wBitsPerSample != 8) 229 { 230 //GS_SetResult(res,GS_Spf(0,"%d bits per sample PCM format not supported", 231 //wf->wBitsPerSample),GS_VOLATILE); 232 return ESR_FATAL_ERROR; 233 } 234 *length = data->length * 8 / wf->wBitsPerSample; 235 *samples = MALLOC(*length * sizeof(short), MTAG); 236 if (wf->wBitsPerSample == 16) 237 { 238 memcpy(*samples, cb, *length*sizeof(short)); 239 if (doSwap) 240 for (i = 0;i < *length;i++) swapShort(*samples + i); 241 } 242 else 243 { 244 for (i = 0;i < *length;i++)(*samples)[i] = (short)((unsigned)(cb[i]) - 128) << 8; 245 } 246 return ESR_SUCCESS; 247 } 248 249 /* Converts CCITT u-law wave data 250 */ 251 static ESR_ReturnCode readMulawWave(WaveFormat *wf, ChunkContext *data, 252 char *cb, short **samples, int *length, int doSwap) 253 { 254 int i; 255 if (wf->nChannels != 1) 256 { 257 //GS_SetResult(res,"u-law WAVE file contains more than one data channel", 258 //GS_STATIC); 259 return ESR_FATAL_ERROR; 260 } 261 if (wf->wBitsPerSample != 8) 262 { 263 //GS_SetResult(res,GS_Spf(0,"%d bits per sample u-law format not supported", 264 //wf->wBitsPerSample),GS_VOLATILE); 265 return ESR_FATAL_ERROR; 266 } 267 *length = data->length; 268 *samples = MALLOC(*length * sizeof(short), MTAG); 269 for (i = 0;i < *length;i++) 270 (*samples)[i] = (short) ulaw2linear(cb[i]); 271 return ESR_SUCCESS; 272 } 273 274 /* Converts a-law wave data 275 */ 276 static ESR_ReturnCode readAlawWave(WaveFormat *wf, ChunkContext *data, 277 char *cb, short **samples, int *length, int doSwap) 278 { 279 int i; 280 if (wf->nChannels != 1) 281 { 282 //GS_SetResult(res,"u-law WAVE file contains more than one data channel", 283 //GS_STATIC); 284 return ESR_FATAL_ERROR; 285 } 286 if (wf->wBitsPerSample != 8) 287 { 288 //GS_SetResult(res,GS_Spf(0,"%d bits per sample u-law format not supported", 289 //wf->wBitsPerSample),GS_VOLATILE); 290 return ESR_FATAL_ERROR; 291 } 292 *length = data->length; 293 samples = MALLOC(*length * sizeof(short), MTAG); 294 for (i = 0;i < *length;i++)(*samples)[i] = alaw2linear(cb[i]); 295 return ESR_SUCCESS; 296 } 297 298 /* ------------------------------------------------------------------------- */ 299 300 /* RIFF INTERFACE UTILS */ 301 302 void free_swiRiff(SwiRiffStruct *swichunk) 303 { 304 if (swichunk->segs.num_tuples) 305 { 306 FREE(swichunk->segs.tuples); 307 swichunk->segs.num_tuples = 0; 308 } 309 if (swichunk->kvals.num_pairs) 310 { 311 FREE(swichunk->kvals.kvpairs[0].key); 312 FREE(swichunk->kvals.kvpairs); 313 swichunk->kvals.num_pairs = 0; 314 } 315 } 316 317 char *getSwiRiffKVal(SwiRiffStruct *swichunk, char *key) 318 { 319 int i; 320 321 for (i = 0; i < swichunk->kvals.num_pairs; i++) 322 if (! strcmp(swichunk->kvals.kvpairs[i].key, key)) 323 return swichunk->kvals.kvpairs[i].value; 324 325 return NULL; 326 } 327 328 /* ------------------------------------------------------------------------- */ 329 330 static int riffDescend(FILE *f, ChunkContext *c, ChunkContext *parent, DescendType t, int doSwap) 331 { 332 char form[4], tag[4]; 333 int len; 334 long start, end; 335 336 end = 0; 337 if (!parent) start = 0; 338 else 339 { 340 start = parent->start; 341 end = start + parent->length; 342 } 343 if (fseek(f, start, SEEK_SET) < 0) 344 { 345 //GS_SetResult(res,"seek failed",GS_STATIC); 346 return ESR_FATAL_ERROR; 347 } 348 349 switch (t) 350 { 351 352 case FIND_RIFF: 353 while (1) 354 { 355 if (fread(form, 1, 4, f) != 4) break; 356 if (fread(&len, sizeof(int), 1, f) != 1) 357 return ESR_FATAL_ERROR; 358 if (doSwap) 359 swapInt(&len); 360 if (strncmp(form, "RIFF", 4)) 361 { /* skip this non-RIFF chunk */ 362 if (fseek(f, (long)len, SEEK_CUR) < 0) break; 363 start += len + 8; 364 if (end && start >= end) 365 { 366 //GS_SetResult(res,"RIFF form type not found",GS_STATIC); 367 return ESR_FATAL_ERROR; 368 } 369 continue; 370 } 371 if (fread(tag, 1, 4, f) != 4) break; 372 if (!strncmp(tag, c->tag, 4)) 373 { 374 c->start = start + 12; 375 c->length = len - 4; 376 return ESR_SUCCESS; 377 } 378 } 379 //if(feof(f)) GS_SetResult(res,"RIFF form type not found",GS_STATIC); 380 //else GS_SetResult(res,"Corrupt RIFF file",GS_STATIC); 381 return ESR_FATAL_ERROR; 382 383 case FIND_CHUNK: 384 while (1) 385 { 386 if (fread(tag, 1, 4, f) != 4) break; 387 if (fread(&len, sizeof(int), 1, f) != 1) 388 return ESR_FATAL_ERROR; 389 if (doSwap) 390 swapInt(&len); 391 if (!strncmp(tag, c->tag, 4)) 392 { 393 c->start = start + 8; 394 c->length = len; 395 return ESR_SUCCESS; 396 } 397 if (fseek(f, (long)len, SEEK_CUR) < 0) break; 398 start += len + 8; 399 if (end && start >= end) 400 { 401 //GS_SetResult(res,"RIFF chunk not found",GS_STATIC); 402 return ESR_FATAL_ERROR; 403 } 404 } 405 //if(feof(f)) GS_SetResult(res,"RIFF chunk not found",GS_STATIC); 406 //else GS_SetResult(res,"corrupt RIFF file",GS_STATIC); 407 return ESR_FATAL_ERROR; 408 409 case FIND_LIST: 410 while (1) 411 { 412 if (fread(form, 1, 4, f) != 4) break; 413 if (fread(&len, sizeof(int), 1, f) != 1) 414 return ESR_FATAL_ERROR; 415 if (doSwap) 416 swapInt(&len); 417 if (strncmp(form, "LIST", 4)) 418 { /* skip this non-LIST chunk */ 419 if (fseek(f, (long)len, SEEK_CUR) < 0) break; 420 start += len + 8; 421 if (end && start >= end) 422 { 423 //GS_SetResult(res,"RIFF form type not found",GS_STATIC); 424 return ESR_FATAL_ERROR; 425 } 426 continue; 427 } 428 if (fread(tag, 1, 4, f) != 4) break; 429 if (!strncmp(tag, c->tag, 4)) 430 { 431 c->start = start + 12; 432 c->length = len - 4; 433 return ESR_SUCCESS; 434 } 435 } 436 437 //if(feof(f)) GS_SetResult(res,"RIFF form type not found",GS_STATIC); 438 //else GS_SetResult(res,"Corrupt RIFF file",GS_STATIC); 439 return ESR_FATAL_ERROR; 440 } 441 442 //GS_AppendResult(res,"bad search flag",GS_STATIC); 443 return ESR_FATAL_ERROR; 444 } 445 446 static int riffAscend(FILE *f, ChunkContext *c) 447 { 448 if (fseek(f, c->start + c->length, SEEK_SET) < 0) 449 { 450 //GS_SetResult(res,"seek failed",GS_STATIC); 451 return ESR_FATAL_ERROR; 452 } 453 return ESR_SUCCESS; 454 } 455 456 457 static ESR_ReturnCode readSwiChunk(FILE *f, ChunkContext *parent, SwiRiffStruct *swichunk, int doSwap) 458 { 459 ESR_ReturnCode rc = ESR_SUCCESS; 460 ChunkContext chunk, list_chunk; 461 int sub_length; 462 swichunk->segs.num_tuples = 0; 463 swichunk->kvals.num_pairs = 0; 464 465 strncpy(chunk.tag, "swi ", 4); 466 if (riffDescend(f, &chunk, parent, FIND_LIST, doSwap) == ESR_SUCCESS) 467 { 468 /* is it as "swi " list? */ 469 strncpy(list_chunk.tag, "segs", 4); 470 if (riffDescend(f, &list_chunk, &chunk, FIND_CHUNK, doSwap) == ESR_SUCCESS) 471 { 472 fread(&swichunk->segs.num_tuples, 1, sizeof(int), f); 473 if (doSwap) swapInt(&swichunk->segs.num_tuples); 474 475 sub_length = list_chunk.length - sizeof(int); 476 if (sub_length) 477 { 478 swichunk->segs.tuples = MALLOC(sub_length, MTAG); 479 if (!swichunk->segs.tuples) 480 { 481 swichunk->segs.num_tuples = 0; /* so that the free routine will work */ 482 rc = ESR_OUT_OF_MEMORY; 483 } 484 else if (fread(swichunk->segs.tuples, 1, sub_length, f) != (size_t)sub_length) 485 { 486 rc = ESR_FATAL_ERROR; 487 } 488 if (rc != ESR_SUCCESS) 489 goto swichunk_cleanup; 490 491 } 492 else 493 swichunk->segs.tuples = NULL; 494 } 495 strncpy(list_chunk.tag, "kvs ", 4); 496 /* start searching from after "swi" */ 497 if (riffDescend(f, &list_chunk, &chunk, FIND_CHUNK, doSwap) == ESR_SUCCESS) 498 { 499 int i, num_pairs; 500 501 fread(&num_pairs, 1, sizeof(int), f); 502 if (doSwap) swapInt(&num_pairs); 503 swichunk->kvals.num_pairs = num_pairs; 504 505 sub_length = list_chunk.length - sizeof(int); 506 if (sub_length) 507 { 508 char *kvpair_buf = NULL; 509 RiffKVPair *pairs; 510 511 swichunk->kvals.kvpairs = (RiffKVPair *)CALLOC(num_pairs, sizeof(RiffKVPair), MTAG); 512 kvpair_buf = CALLOC(sub_length, sizeof(char), MTAG); 513 if (!swichunk->kvals.kvpairs || !kvpair_buf) 514 { 515 if (kvpair_buf) FREE(kvpair_buf); 516 if (swichunk->kvals.kvpairs) FREE(swichunk->kvals.kvpairs); 517 swichunk->kvals.num_pairs = 0; 518 rc = ESR_OUT_OF_MEMORY; 519 goto swichunk_cleanup; 520 } 521 522 swichunk->kvals.kvpairs[0].key = kvpair_buf; 523 if (fread(kvpair_buf, 1, sub_length, f) != (size_t)sub_length) 524 { 525 rc = ESR_FATAL_ERROR; 526 goto swichunk_cleanup; 527 } 528 for (pairs = swichunk->kvals.kvpairs, i = 0; i < swichunk->kvals.num_pairs; i++, pairs++) 529 { 530 pairs->key = kvpair_buf; 531 kvpair_buf += strlen(kvpair_buf) + 1; 532 pairs->value = kvpair_buf; 533 kvpair_buf += strlen(kvpair_buf) + 1; 534 } 535 } 536 else 537 swichunk->kvals.kvpairs = NULL; 538 } 539 } 540 /* no matter what was found or not found, return with the file pointer in 541 * the state that it was upon entering this function */ 542 if (riffAscend(f, parent) != ESR_SUCCESS) 543 { 544 rc = ESR_FATAL_ERROR; 545 goto swichunk_cleanup; 546 } 547 548 swichunk_cleanup: 549 if (rc == ESR_FATAL_ERROR) free_swiRiff(swichunk); 550 return rc; 551 } 552 553 554 /* Reads RIFF format WAVE files 555 */ 556 ESR_ReturnCode riffReadWave2L16(FILE *f, double from, double to, 557 short **samples, int *rate, int *length, SwiRiffStruct *swichunk) 558 { 559 ChunkContext chunk, parent; 560 WaveFormat *wf; 561 char *cb; 562 ESR_ReturnCode rc; 563 int i, ifrom, ito; 564 int doSwap = ! isLittleEndian(); 565 566 /* find the WAVE chunk */ 567 strncpy(parent.tag, "WAVE", 4); 568 if (riffDescend(f, &parent, NULL, FIND_RIFF, doSwap) != ESR_SUCCESS) 569 { 570 //GS_AppendResult(res,"\nnot a RIFF waveform audio file",NULL); 571 return ESR_FATAL_ERROR; 572 } 573 574 /* Wave format */ 575 strncpy(chunk.tag, "fmt ", 4); 576 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS) 577 { 578 //GS_AppendResult(res,"\nwaveform audio file has no \"fmt \" chunk.",NULL); 579 return ESR_FATAL_ERROR; 580 } 581 if (chunk.length < sizeof(WaveFormat)) 582 wf = MALLOC(sizeof(WaveFormat), MTAG); 583 else 584 wf = MALLOC(chunk.length, MTAG); 585 586 if (fread(wf, 1, chunk.length, f) != (size_t)chunk.length) 587 { 588 FREE((char *)wf); 589 //GS_SetResult(res,"fmt chunk read failed.",GS_STATIC); 590 return ESR_FATAL_ERROR; 591 } 592 if (doSwap) swapWaveFormat(wf); 593 *rate = wf->nSamplesPerSec; 594 595 /* data chunk */ 596 if (riffAscend(f, &chunk) != ESR_SUCCESS) 597 { 598 return ESR_FATAL_ERROR; 599 } 600 strncpy(chunk.tag, "data", 4); 601 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS) 602 { 603 //GS_AppendResult(res,"\nwaveform audio file has no \"data\" chunk.",NULL); 604 return ESR_FATAL_ERROR; 605 } 606 cb = MALLOC(chunk.length, MTAG); /* waveform */ 607 if (fread(cb, 1, chunk.length, f) != (size_t)chunk.length) 608 { 609 FREE((char *)wf); 610 FREE((char *)cb); 611 //GS_SetResult(res,"truncated \"data\" chunk",GS_STATIC); 612 return ESR_FATAL_ERROR; 613 } 614 615 if (swichunk) 616 { 617 rc = readSwiChunk(f, &parent, swichunk, doSwap); 618 if (rc != ESR_SUCCESS) 619 { 620 FREE((char *)wf); 621 FREE((char *)cb); 622 return rc; 623 } 624 } 625 626 for (i = 0;WaveCodecs[i].func;i++) 627 628 if (wf->nFormatTag == WaveCodecs[i].id) 629 { 630 rc = (WaveCodecs[i].func)(wf, &chunk, cb, samples, length, doSwap); 631 FREE((char *)wf); 632 FREE((char *)cb); 633 if (rc != ESR_SUCCESS) 634 { 635 if (swichunk) free_swiRiff(swichunk); 636 return rc; 637 } 638 /* handle 'from' and 'to' - this isn't very efficient, but 639 * saves all the format conversion routines the trouble of doing so 640 */ 641 if (from == 0 && to == -1) return ESR_SUCCESS; 642 if (from > 0) 643 ifrom = (int)(from * (*rate) / 1000.0); 644 else 645 ifrom = 0; 646 647 if (to >= 0) 648 { 649 ito = (int)(to * (*rate) / 1000.0 + 0.5); 650 if (ito > *length) 651 ito = *length; 652 } 653 else 654 ito = *length; 655 656 *length = ito - ifrom; 657 if (ifrom > 0) memmove(*samples, (*samples) + ifrom, (*length)*sizeof(short)); 658 return ESR_SUCCESS; 659 } 660 661 //GS_SetResult(res,GS_Spf(0,"WAVE format (id 0x%x) not supported", 662 //wf->nFormatTag),GS_VOLATILE); 663 // 664 if (swichunk) free_swiRiff(swichunk); 665 FREE((char *)cb); 666 return ESR_FATAL_ERROR; 667 } 668 669 670 671 /* Reads RIFF format WAVE files and returns: 672 * waveform: allocated with size num_bytes 673 * audio_type is a constant string (not allocated) 674 * If swichunk==NULL, does not look for swi-specific chunk, 675 * Returns ESR_FATAL_ERROR if num_channels != 1 676 * If and only if ESR_SUCCESS, caller must free waveform, and swichunk contents (if any) 677 */ 678 ESR_ReturnCode readRiff2Buf(FILE *f, void **waveform, unsigned int *num_bytes, 679 const wchar_t **audio_type, SwiRiffStruct *swichunk) 680 { 681 ChunkContext chunk, parent; 682 WaveFormat *wf = NULL; 683 ESR_ReturnCode rc = ESR_SUCCESS; 684 int doSwap = ! isLittleEndian(); 685 *waveform = NULL; 686 687 *audio_type = NULL; /* for error recovery higher up */ 688 689 if (swichunk) 690 { /* for error recovery */ 691 swichunk->segs.num_tuples = 0; 692 swichunk->kvals.num_pairs = 0; 693 } 694 695 /* find the WAVE chunk */ 696 strncpy(parent.tag, "WAVE", 4); 697 if (riffDescend(f, &parent, NULL, FIND_RIFF, doSwap) != ESR_SUCCESS) 698 { 699 return ESR_FATAL_ERROR; 700 } 701 702 /* Wave format */ 703 strncpy(chunk.tag, "fmt ", 4); 704 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS) 705 { 706 return ESR_FATAL_ERROR; 707 } 708 if (chunk.length < sizeof(WaveFormat)) 709 wf = MALLOC(sizeof(WaveFormat), MTAG); 710 else 711 wf = MALLOC(chunk.length, MTAG); 712 713 if (fread(wf, 1, chunk.length, f) != (size_t)chunk.length) 714 { 715 FREE((char *)wf); 716 return ESR_FATAL_ERROR; 717 } 718 if (doSwap) swapWaveFormat(wf); 719 720 if (wf->nChannels != 1) 721 { 722 FREE((char *)wf); 723 return ESR_FATAL_ERROR; 724 } 725 if (doSwap) 726 { 727 swapShort(&wf->nBlockAlign); /* usually == blockAlign / nChannels */ 728 swapInt(&wf->nSamplesPerSec); 729 swapShort(&wf->nFormatTag); 730 } 731 732 /* data chunk */ 733 if (riffAscend(f, &chunk) != ESR_SUCCESS) 734 { 735 rc = ESR_FATAL_ERROR; 736 goto cleanup; 737 } 738 739 strncpy(chunk.tag, "data", 4); 740 if (riffDescend(f, &chunk, &parent, FIND_CHUNK, doSwap) != ESR_SUCCESS) 741 { 742 rc = ESR_FATAL_ERROR; 743 goto cleanup; 744 } 745 746 *num_bytes = chunk.length; /* already swapped, if need be */ 747 *waveform = CALLOC(chunk.length, 1, MTAG); 748 if (fread(*waveform, 1, chunk.length, f) != (size_t)chunk.length) 749 { 750 rc = ESR_FATAL_ERROR; 751 goto cleanup; 752 } 753 if (doSwap) 754 { 755 if (wf->nBlockAlign == 2) 756 short_byte_swap((short *)*waveform, chunk.length); 757 else if (wf->nBlockAlign == 4) 758 int_byte_swap((int *)*waveform, chunk.length); 759 } 760 761 if (swichunk) 762 { 763 rc = readSwiChunk(f, &parent, swichunk, doSwap); 764 goto cleanup; 765 } 766 767 *audio_type = NULL; 768 769 /* assuming nchannels = 1, usually bytes_per_sample==blockAlign / nchannels (not aurora!) */ 770 if (wf->nFormatTag == WAVEFORMAT_PCM) 771 { 772 if (wf->nBlockAlign == 2) 773 {/* can only be L16 */ 774 if (wf->nSamplesPerSec == 8000) 775 *audio_type = L"audio/L16;rate=8000"; 776 else if (wf->nSamplesPerSec == 16000) 777 *audio_type = L"audio/L16;rate=16000"; 778 } 779 } 780 else if (wf->nFormatTag == WAVEFORMAT_ALAW) 781 { 782 if (wf->nSamplesPerSec == 8000) 783 *audio_type = L"audio/x-alaw-basic;rate=8000"; 784 } 785 else if (wf->nFormatTag == WAVEFORMAT_MULAW) 786 { 787 if (wf->nSamplesPerSec == 8000) 788 { 789 if (swichunk) 790 { 791 char *encoding = getSwiRiffKVal(swichunk, "orig-encoding"); 792 if (!encoding) 793 *audio_type = L"audio/basic;rate=8000"; 794 else if (! strcmp(encoding, "g723")) 795 *audio_type = L"audio/basic;rate=8000;orig-encoding=g723"; 796 else if (! strcmp(encoding, "g729")) 797 *audio_type = L"audio/basic;rate=8000;orig-encoding=g729"; 798 else 799 { 800 // FIXME: warning because unknown orig-encoding?? 801 // rec_test will never get here cuz already checked validity of audiotype 802 // but to be careful pour l'avenir, should handle this 803 *audio_type = L"audio/basic;rate=8000"; 804 } 805 } 806 else 807 *audio_type = L"audio/basic;rate=8000"; 808 } 809 else if (wf->nSamplesPerSec == 16000) 810 *audio_type = L"audio/basic;rate=16000"; 811 812 } 813 else if (wf->nFormatTag == WAVEFORMAT_AURORA) 814 { 815 if (wf->nSamplesPerSec == 8000) 816 *audio_type = L"application/x-feature;rate=8000;encoding=swifeature_aurora"; 817 else if (wf->nSamplesPerSec == 11000) 818 *audio_type = L"application/x-feature;rate=11000;encoding=swifeature_aurora"; 819 else if (wf->nSamplesPerSec == 16000) 820 *audio_type = L"application/x-feature;rate=16000;encoding=swifeature_aurora"; 821 } 822 else if (wf->nFormatTag == WAVEFORMAT_ES_202_050) 823 { 824 if (wf->nSamplesPerSec == 8000) 825 *audio_type = L"application/x-feature;rate=8000;encoding=ES_202_050"; 826 else if (wf->nSamplesPerSec == 11000) 827 *audio_type = L"application/x-feature;rate=11000;encoding=ES_202_050"; 828 else if (wf->nSamplesPerSec == 16000) 829 *audio_type = L"application/x-feature;rate=16000;encoding=ES_202_050"; 830 } 831 832 if (*audio_type == NULL) 833 { 834 rc = ESR_FATAL_ERROR; 835 goto cleanup; 836 } 837 838 cleanup: 839 if (wf) FREE((char *)wf); 840 if (rc != ESR_SUCCESS) 841 { 842 if (swichunk) 843 free_swiRiff(swichunk); 844 if (*waveform) 845 { 846 FREE((char *)*waveform); 847 *waveform = NULL; 848 } 849 } 850 return rc; 851 } 852 853 static int getFormatTag(wchar_t *audio_type) 854 { 855 if (!wcsncmp(audio_type, L"audio/basic", 11)) 856 { 857 return WAVEFORMAT_MULAW; 858 } 859 if (!wcsncmp(audio_type, L"application/x-feature;", 14) && 860 wcsstr(audio_type, L"encoding=swifeature_aurora")) 861 { 862 return WAVEFORMAT_AURORA; 863 } 864 else if (!wcsncmp(audio_type, L"application/x-feature;", 14) && 865 wcsstr(audio_type, L"encoding=ES_202_050")) 866 { 867 return WAVEFORMAT_ES_202_050; 868 } 869 else if (!wcsncmp(audio_type, L"audio/x-alaw-basic", 18)) 870 { 871 return WAVEFORMAT_ALAW; 872 } 873 else if (!wcsncmp(audio_type, L"audio/L16", 9)) 874 { 875 return WAVEFORMAT_PCM; 876 } 877 return -1; 878 } 879 880 /* we are assuming that riffaudio->num_tuples!=0, and hence riffaudio->tuples!=NULL 881 */ 882 static unsigned char *writeSwiAudioChunk(int doSwap, int chunk_len, SwiRiffAudio *riffaudio, 883 unsigned char *workbuf) 884 { 885 ChunkInfoStruct ck; 886 int chunkinfosize = sizeof(ChunkInfoStruct); 887 888 strncpy(ck.ckString, "segs", 4); 889 ck.ckLength = chunk_len; 890 if (doSwap) 891 { 892 swapInt(&ck.ckLength); 893 memcpy(workbuf, &ck, chunkinfosize); 894 workbuf += chunkinfosize; 895 896 memcpy(workbuf, &riffaudio->num_tuples, sizeof(int)); 897 workbuf += sizeof(int); 898 chunk_len -= sizeof(int); 899 900 memcpy(workbuf, riffaudio->tuples, chunk_len); 901 int_byte_swap((int *)workbuf, riffaudio->num_tuples*3 + 1); 902 /* count every tuple (3) + num_tuples itself */ 903 return workbuf + chunk_len; 904 } 905 else 906 { 907 memcpy(workbuf, &ck, chunkinfosize); 908 workbuf += chunkinfosize; 909 memcpy(workbuf, &riffaudio->num_tuples, sizeof(int)); 910 workbuf += sizeof(int); 911 chunk_len -= sizeof(int); 912 913 memcpy(workbuf, riffaudio->tuples, chunk_len); 914 return workbuf + chunk_len; 915 } 916 } 917 918 /* WARNING: returns with file pointer past the 4 first chars 919 * 920 * If the first 4 bytes of the specified file are "RIFF", 921 * then we assume it's a RIFF file 922 */ 923 int isRiffFile(FILE *fp) 924 { 925 char tmpbuf[4]; 926 fseek(fp, 0, SEEK_SET); 927 fread(tmpbuf, 4, sizeof(char), fp); 928 return !strncmp(tmpbuf, "RIFF", 4); 929 930 } 931 932 /* 933 * WARNING: assuming num_channels = 1 934 * INPUT: waveform, num_bytes (waveform length), audio_type, 935 * swichunk (it returns unmodified, including not swapped) 936 * OUTPUT: buf (entire riff chunk) and buflen 937 * 938 * AURORA special case: 939 * sampling rate = bytes_per_sample = -1; other fields of WaveFormat undefined 940 */ 941 ESR_ReturnCode convertBuf2Riff( 942 unsigned char *waveform, 943 unsigned int num_bytes, 944 wchar_t *audio_type, 945 int rate, 946 int bytes_per_sample, 947 SwiRiffStruct *swichunk, 948 unsigned char **buf, 949 unsigned int *buflen) 950 { 951 unsigned int total_buflen; 952 unsigned char *ptr, *workbuf; 953 short num_channels = 1; 954 int num_samples; 955 int bytes_sec; 956 short block_align; 957 int doSwap; 958 ChunkInfoStruct ck; 959 RiffHeaderStruct header; 960 int headerSize = sizeof(RiffHeaderStruct); 961 int chunkInfoSize = sizeof(ChunkInfoStruct); 962 int listChunkSize = 0; 963 int segs_chunk_size, kvals_chunk_size; 964 short format_tag = (short) getFormatTag(audio_type); 965 966 if (format_tag == -1 || 967 (bytes_per_sample == -1 && format_tag != WAVEFORMAT_AURORA && 968 format_tag != WAVEFORMAT_ES_202_050)) 969 { 970 PLogError(L("audio type not supported for RIFF conversion")); 971 return ESR_FATAL_ERROR; 972 973 } 974 if (bytes_per_sample > 0) 975 num_samples = num_bytes / bytes_per_sample; 976 else 977 num_samples = num_bytes; 978 979 strncpy(header.riffString, "RIFF", 4); 980 strncpy(header.waveString, "WAVE", 4); 981 strncpy(header.fmtString, "fmt ", 4); 982 strncpy(header.dataString, "data", 4); 983 984 total_buflen = headerSize + num_bytes; 985 986 if (swichunk->segs.num_tuples || swichunk->kvals.num_pairs) 987 { 988 listChunkSize = chunkInfoSize /* LIST chunk info */ + 4 * sizeof(char); /* "swi " */ 989 if (swichunk->segs.num_tuples) 990 { 991 segs_chunk_size = sizeof(int) + (swichunk->segs.num_tuples) * sizeof(RiffAudioTuple); 992 listChunkSize += chunkInfoSize + segs_chunk_size; 993 } 994 if (swichunk->kvals.num_pairs) 995 { 996 int i; 997 kvals_chunk_size = 0; 998 for (i = 0; i < swichunk->kvals.num_pairs; i++) 999 { 1000 kvals_chunk_size += (strlen(swichunk->kvals.kvpairs[i].key) + 1 1001 + strlen(swichunk->kvals.kvpairs[i].value) + 1) * sizeof(char); 1002 } 1003 kvals_chunk_size += sizeof(int); /* num_pairs */ 1004 listChunkSize += chunkInfoSize + kvals_chunk_size; 1005 } 1006 total_buflen += listChunkSize; 1007 } 1008 if (total_buflen > *buflen) 1009 { 1010 PLogError(L("ESR_BUFFER_OVERFLOW")); 1011 return ESR_BUFFER_OVERFLOW; 1012 } 1013 workbuf = *buf; 1014 1015 *buflen = total_buflen; 1016 ptr = workbuf; 1017 if (format_tag == WAVEFORMAT_AURORA || format_tag == WAVEFORMAT_ES_202_050) 1018 { 1019 bytes_sec = AURORA_BYTES_SEC; 1020 block_align = 4; 1021 } 1022 else 1023 { 1024 bytes_sec = (short)(rate * num_channels * bytes_per_sample); 1025 block_align = bytes_per_sample * num_channels; 1026 } 1027 doSwap = !isLittleEndian(); 1028 if (doSwap) 1029 { 1030 header.riffChunkLength = swapConstInt(*buflen - chunkInfoSize); 1031 header.fmtChunkLength = swapConstInt(sizeof(WaveFormat)); 1032 header.waveinfo.nFormatTag = swapConstShort(format_tag); /* codec */ 1033 header.waveinfo.nChannels = swapConstShort(num_channels); 1034 header.waveinfo.nSamplesPerSec = swapConstInt(rate); 1035 header.waveinfo.nAvgBytesPerSec = swapConstInt(bytes_sec); 1036 header.waveinfo.nBlockAlign = swapConstShort(block_align); 1037 header.waveinfo.wBitsPerSample = swapConstShort((short)((bytes_sec * 8) / rate)); 1038 header.dataLength = swapConstInt(num_bytes); 1039 memcpy(ptr, &header, headerSize); 1040 1041 memcpy(ptr + headerSize, waveform, header.dataLength); 1042 if (bytes_per_sample == 2) 1043 short_byte_swap((short *)(ptr + headerSize), num_samples); 1044 } 1045 else 1046 { 1047 header.riffChunkLength = total_buflen - chunkInfoSize; 1048 header.fmtChunkLength = sizeof(WaveFormat); 1049 header.waveinfo.nFormatTag = format_tag; /* codec */ 1050 header.waveinfo.nChannels = num_channels; 1051 header.waveinfo.nSamplesPerSec = rate; 1052 header.waveinfo.nAvgBytesPerSec = bytes_sec; 1053 header.waveinfo.nBlockAlign = (short) block_align; 1054 header.waveinfo.wBitsPerSample = (bytes_sec * 8) / rate; 1055 header.dataLength = num_bytes; 1056 1057 memcpy(ptr, &header, headerSize); 1058 memcpy(ptr + headerSize, waveform, header.dataLength); 1059 } 1060 ptr += headerSize + header.dataLength; 1061 1062 if (swichunk->segs.num_tuples || swichunk->kvals.num_pairs) 1063 { 1064 strncpy(ck.ckString, "LIST", 4); 1065 ck.ckLength = listChunkSize - chunkInfoSize; 1066 if (doSwap) swapInt(&ck.ckLength); 1067 memcpy(ptr, &ck, chunkInfoSize); /* copy LIST */ 1068 ptr += chunkInfoSize; 1069 1070 strncpy((char *)ptr, "swi ", 4); 1071 ptr += 4; 1072 1073 if (swichunk->segs.num_tuples) 1074 { 1075 ptr = writeSwiAudioChunk(doSwap, segs_chunk_size, &swichunk->segs, ptr); 1076 } 1077 if (swichunk->kvals.num_pairs) 1078 { 1079 int i, num_pairs; 1080 RiffKVPair *pairs; 1081 1082 strncpy(ck.ckString, "kvs ", 4); 1083 ck.ckLength = kvals_chunk_size; /* num_pairs and pairs themselves */ 1084 if (doSwap) swapInt(&ck.ckLength); 1085 memcpy(ptr, &ck, chunkInfoSize); 1086 ptr += chunkInfoSize; 1087 1088 num_pairs = (doSwap) ? swapConstInt(swichunk->kvals.num_pairs) : swichunk->kvals.num_pairs; 1089 memcpy(ptr, &num_pairs, sizeof(int)); 1090 ptr += sizeof(int); 1091 1092 for (pairs = swichunk->kvals.kvpairs, i = 0; i < num_pairs; i++, pairs++) 1093 { 1094 strcpy((char *)ptr, pairs->key); 1095 ptr += strlen(pairs->key) + 1; 1096 1097 strcpy((char *)ptr, pairs->value); 1098 ptr += strlen(pairs->value) + 1; 1099 } 1100 } 1101 } 1102 passert((unsigned int)(ptr - workbuf) == *buflen); 1103 1104 return ESR_SUCCESS; 1105 } 1106 1107 1108