History

wav: move adpcm/gsm fmt parsing to separate functions

Mans Rullgard committed 6 years ago

Commit a5092b21 parent 1e0a00d1 file · +144 −122Browse files

Unified · Split

src/wav.c+144−122
@@ -69,6 +69,7 @@ typedef struct { · 68 unmodified lines
69 unsigned short formatTag; /* What type of encoding file is using */69 unsigned short formatTag; /* What type of encoding file is using */
70 unsigned short samplesPerBlock;70 unsigned short samplesPerBlock;
71 unsigned short blockAlign;71 unsigned short blockAlign;
72 uint16_t bitsPerSample; /* bits per sample */
72 size_t dataStart; /* need to for seeking */73 size_t dataStart; /* need to for seeking */
73 int ignoreSize; /* ignoreSize allows us to process 32-bit WAV files that are74 int ignoreSize; /* ignoreSize allows us to process 32-bit WAV files that are
74 * greater then 2 Gb and can't be represented by the75 * greater then 2 Gb and can't be represented by the
@@ -102,6 +103,43 @@ static int wavwritehdr(sox_format_t *, int); · 27 unmodified lines
102/* IMA ADPCM Support Functions Section */103/* IMA ADPCM Support Functions Section */
103/****************************************************************************/104/****************************************************************************/
104 105
106static int wav_ima_adpcm_fmt(sox_format_t *ft, uint32_t len)
107{
108 priv_t *wav = ft->priv;
109 size_t bytesPerBlock;
110
111 if (len < 2) {
112 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects cbSize >= %d",
113 wav_format_str(wav->formatTag), 2);
114 return SOX_EOF;
115 }
116
117 if (wav->bitsPerSample != 4) {
118 lsx_fail_errno(ft, SOX_EOF,
119 "Can only handle 4-bit IMA ADPCM in wav files");
120 return SOX_EOF;
121 }
122
123 lsx_readw(ft, &wav->samplesPerBlock);
124
125 bytesPerBlock = lsx_ima_bytes_per_block(ft->signal.channels,
126 wav->samplesPerBlock);
127
128 if (bytesPerBlock != wav->blockAlign || wav->samplesPerBlock % 8 != 1) {
129 lsx_fail_errno(ft, SOX_EOF,
130 "format[%s]: samplesPerBlock(%d) != blockAlign(%d)",
131 wav_format_str(wav->formatTag),
132 wav->samplesPerBlock, wav->blockAlign);
133 return SOX_EOF;
134 }
135
136 wav->packet = lsx_malloc(wav->blockAlign);
137 wav->samples =
138 lsx_malloc(ft->signal.channels * wav->samplesPerBlock * sizeof(short));
139
140 return SOX_SUCCESS;
141}
142
105/*143/*
106 *144 *
107 * ImaAdpcmReadBlock - Grab and decode complete block of samples145 * ImaAdpcmReadBlock - Grab and decode complete block of samples
@@ -142,6 +180,74 @@ static unsigned short ImaAdpcmReadBlock(sox_format_t * ft) · 34 unmodified lines
142/* MS ADPCM Support Functions Section */180/* MS ADPCM Support Functions Section */
143/****************************************************************************/181/****************************************************************************/
144 182
183static int wav_ms_adpcm_fmt(sox_format_t *ft, uint32_t len)
184{
185 priv_t *wav = ft->priv;
186 size_t bytesPerBlock;
187 int i, errct = 0;
188
189 if (len < 4) {
190 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects cbSize >= %d",
191 wav_format_str(wav->formatTag), 4);
192 return SOX_EOF;
193 }
194
195 if (wav->bitsPerSample != 4) {
196 lsx_fail_errno(ft, SOX_EOF,
197 "Can only handle 4-bit MS ADPCM in wav files");
198 return SOX_EOF;
199 }
200
201 lsx_readw(ft, &wav->samplesPerBlock);
202 lsx_readw(ft, &wav->nCoefs);
203 len -= 4;
204
205 bytesPerBlock = lsx_ms_adpcm_bytes_per_block(ft->signal.channels,
206 wav->samplesPerBlock);
207
208 if (bytesPerBlock != wav->blockAlign) {
209 lsx_fail_errno(ft, SOX_EOF,
210 "format[%s]: samplesPerBlock(%d) != blockAlign(%d)",
211 wav_format_str(wav->formatTag),
212 wav->samplesPerBlock, wav->blockAlign);
213 return SOX_EOF;
214 }
215
216 if (wav->nCoefs < 7 || wav->nCoefs > 0x100) {
217 lsx_fail_errno(ft, SOX_EOF,
218 "ADPCM file nCoefs (%.4hx) makes no sense",
219 wav->nCoefs);
220 return SOX_EOF;
221 }
222
223 if (len < 4 * wav->nCoefs) {
224 lsx_fail_errno(ft, SOX_EOF, "wave header error: cbSize too small");
225 return SOX_EOF;
226 }
227
228 wav->packet = lsx_malloc(wav->blockAlign);
229 wav->samples =
230 lsx_malloc(ft->signal.channels * wav->samplesPerBlock * sizeof(short));
231
232 /* nCoefs, lsx_ms_adpcm_i_coefs used by adpcm.c */
233 wav->lsx_ms_adpcm_i_coefs = lsx_malloc(wav->nCoefs * 2 * sizeof(short));
234 wav->ms_adpcm_data = lsx_ms_adpcm_alloc(ft->signal.channels);
235
236 for (i = 0; len >= 2 && i < 2 * wav->nCoefs; i++) {
237 lsx_readsw(ft, &wav->lsx_ms_adpcm_i_coefs[i]);
238 len -= 2;
239
240 if (i < 14)
241 errct +=
242 wav->lsx_ms_adpcm_i_coefs[i] != lsx_ms_adpcm_i_coef[i/2][i%2];
243 }
244
245 if (errct)
246 lsx_warn("base lsx_ms_adpcm_i_coefs differ in %d/14 positions", errct);
247
248 return SOX_SUCCESS;
249}
250
145/*251/*
146 *252 *
147 * AdpcmReadBlock - Grab and decode complete block of samples253 * AdpcmReadBlock - Grab and decode complete block of samples
@@ -220,6 +326,36 @@ static int xxxAdpcmWriteBlock(sox_format_t * ft) · 72 unmodified lines
220/****************************************************************************/326/****************************************************************************/
221/* WAV GSM6.10 support functions */327/* WAV GSM6.10 support functions */
222/****************************************************************************/328/****************************************************************************/
329
330static int wav_gsm_fmt(sox_format_t *ft, uint32_t len)
331{
332 priv_t *wav = ft->priv;
333
334 if (len < 2) {
335 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects wExtSize >= %d",
336 wav_format_str(wav->formatTag), 2);
337 return SOX_EOF;
338 }
339
340 lsx_readw(ft, &wav->samplesPerBlock);
341
342 if (wav->blockAlign != 65) {
343 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects blockAlign(%d) = %d",
344 wav_format_str(wav->formatTag), wav->blockAlign, 65);
345 return SOX_EOF;
346 }
347
348 if (wav->samplesPerBlock != 320) {
349 lsx_fail_errno(ft, SOX_EOF,
350 "format[%s]: expects samplesPerBlock(%d) = %d",
351 wav_format_str(wav->formatTag),
352 wav->samplesPerBlock, 320);
353 return SOX_EOF;
354 }
355
356 return SOX_SUCCESS;
357}
358
223/* create the gsm object, malloc buffer for 160*2 samples */359/* create the gsm object, malloc buffer for 160*2 samples */
224static int wavgsminit(sox_format_t * ft)360static int wavgsminit(sox_format_t * ft)
225{361{
@@ -382,9 +518,7 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 156 unmodified lines
382 uint16_t wChannels; /* number of channels */518 uint16_t wChannels; /* number of channels */
383 uint32_t dwSamplesPerSecond; /* samples per second per channel */519 uint32_t dwSamplesPerSecond; /* samples per second per channel */
384 uint32_t dwAvgBytesPerSec; /* estimate of bytes per second needed */520 uint32_t dwAvgBytesPerSec; /* estimate of bytes per second needed */
385 uint16_t wBitsPerSample; /* bits per sample */
386 uint16_t wExtSize = 0; /* extended field for non-PCM */521 uint16_t wExtSize = 0; /* extended field for non-PCM */
387 size_t bytesPerBlock = 0;
388 int bytespersample; /* bytes per sample (per channel */522 int bytespersample; /* bytes per sample (per channel */
389 sox_encoding_t enc = SOX_ENCODING_UNKNOWN;;523 sox_encoding_t enc = SOX_ENCODING_UNKNOWN;;
390 524
@@ -398,7 +532,7 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 7 unmodified lines
398 lsx_readdw(ft, &dwSamplesPerSecond);532 lsx_readdw(ft, &dwSamplesPerSecond);
399 lsx_readdw(ft, &dwAvgBytesPerSec); /* Average bytes/second */533 lsx_readdw(ft, &dwAvgBytesPerSec); /* Average bytes/second */
400 lsx_readw(ft, &wav->blockAlign); /* Block align */534 lsx_readw(ft, &wav->blockAlign); /* Block align */
401 lsx_readw(ft, &wBitsPerSample); /* bits per sample per channel */535 lsx_readw(ft, &wav->bitsPerSample); /* bits per sample per channel */
402 len -= 16;536 len -= 16;
403 537
404 /* non-PCM formats except alaw and mulaw formats have extended fmt chunk.538 /* non-PCM formats except alaw and mulaw formats have extended fmt chunk.
@@ -437,7 +571,7 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 32 unmodified lines
437 lsx_skipbytes(ft, 14);571 lsx_skipbytes(ft, 14);
438 len -= 22;572 len -= 22;
439 573
440 if (numberOfValidBits != wBitsPerSample) {574 if (numberOfValidBits != wav->bitsPerSample) {
441 lsx_fail_errno(ft, SOX_EHDR, "WAVE file fmt with padded samples is not supported yet");575 lsx_fail_errno(ft, SOX_EHDR, "WAVE file fmt with padded samples is not supported yet");
442 return SOX_EOF;576 return SOX_EOF;
443 }577 }
@@ -498,147 +632,35 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 54 unmodified lines
498 632
499 switch (wav->formatTag) {633 switch (wav->formatTag) {
500 case WAVE_FORMAT_ADPCM:634 case WAVE_FORMAT_ADPCM:
501 if (wExtSize < 4) {635 if (wav_ms_adpcm_fmt(ft, len))
502 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects wExtSize >= %d",
503 wav_format_str(wav->formatTag), 4);
504 return SOX_EOF;636 return SOX_EOF;
505 }
506
507 if (wBitsPerSample != 4) {
508 lsx_fail_errno(ft, SOX_EOF,
509 "Can only handle 4-bit MS ADPCM in wav files");
510 return SOX_EOF;
511 }
512
513 lsx_readw(ft, &wav->samplesPerBlock);
514 lsx_readw(ft, &wav->nCoefs);
515 len -= 4;
516
517 bytesPerBlock = lsx_ms_adpcm_bytes_per_block(ft->signal.channels,
518 wav->samplesPerBlock);
519
520 if (bytesPerBlock != wav->blockAlign) {
521 lsx_fail_errno(ft, SOX_EOF,
522 "format[%s]: samplesPerBlock(%d) != blockAlign(%d)",
523 wav_format_str(wav->formatTag),
524 wav->samplesPerBlock, wav->blockAlign);
525 return SOX_EOF;
526 }
527
528 if (wav->nCoefs < 7 || wav->nCoefs > 0x100) {
529 lsx_fail_errno(ft, SOX_EOF,
530 "ADPCM file nCoefs (%.4hx) makes no sense",
531 wav->nCoefs);
532 return SOX_EOF;
533 }
534
535 if (wExtSize < 4 + 4 * wav->nCoefs) {
536 lsx_fail_errno(ft, SOX_EOF, "wave header error: wExtSize(%d) too small for nCoefs(%d)", wExtSize, wav->nCoefs);
537 return SOX_EOF;
538 }
539
540 wav->packet = lsx_malloc(wav->blockAlign);
541 wav->samples =
542 lsx_malloc(wChannels * wav->samplesPerBlock * sizeof(short));
543
544 /* nCoefs, lsx_ms_adpcm_i_coefs used by adpcm.c */
545 wav->lsx_ms_adpcm_i_coefs = lsx_malloc(wav->nCoefs * 2 * sizeof(short));
546 wav->ms_adpcm_data = lsx_ms_adpcm_alloc(wChannels);
547
548 {
549 int i, errct = 0;
550
551 for (i = 0; len >= 2 && i < 2 * wav->nCoefs; i++) {
552 lsx_readsw(ft, &wav->lsx_ms_adpcm_i_coefs[i]);
553 len -= 2;
554
555 if (i < 14)
556 errct += wav->lsx_ms_adpcm_i_coefs[i] !=
557 lsx_ms_adpcm_i_coef[i / 2][i % 2];
558 }
559
560 if (errct)
561 lsx_warn("base lsx_ms_adpcm_i_coefs differ in %d/14 positions",
562 errct);
563 }
564 637
565 bytespersample = 2; /* AFTER de-compression */638 bytespersample = 2; /* AFTER de-compression */
566 break;639 break;
567 640
568 case WAVE_FORMAT_IMA_ADPCM:641 case WAVE_FORMAT_IMA_ADPCM:
569 if (wExtSize < 2) {642 if (wav_ima_adpcm_fmt(ft, len))
570 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects wExtSize >= %d",
571 wav_format_str(wav->formatTag), 2);
572 return SOX_EOF;643 return SOX_EOF;
573 }
574
575 if (wBitsPerSample != 4) {
576 lsx_fail_errno(ft, SOX_EOF,
577 "Can only handle 4-bit IMA ADPCM in wav files");
578 return SOX_EOF;
579 }
580
581 lsx_readw(ft, &wav->samplesPerBlock);
582 len -= 2;
583
584 bytesPerBlock = lsx_ima_bytes_per_block(ft->signal.channels,
585 wav->samplesPerBlock);
586
587 if (bytesPerBlock != wav->blockAlign || wav->samplesPerBlock % 8 != 1) {
588 lsx_fail_errno(ft, SOX_EOF,
589 "format[%s]: samplesPerBlock(%d) != blockAlign(%d)",
590 wav_format_str(wav->formatTag),
591 wav->samplesPerBlock, wav->blockAlign);
592 return SOX_EOF;
593 }
594
595 wav->packet = lsx_malloc(wav->blockAlign);
596 wav->samples =
597 lsx_malloc(wChannels * wav->samplesPerBlock * sizeof(short));
598 644
599 bytespersample = 2; /* AFTER de-compression */645 bytespersample = 2; /* AFTER de-compression */
600 break;646 break;
601 647
602 /* GSM formats have extended fmt chunk. Check for those cases. */
603 case WAVE_FORMAT_GSM610:648 case WAVE_FORMAT_GSM610:
604 if (wExtSize < 2) {649 if (wav_gsm_fmt(ft, len))
605 lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects wExtSize >= %d",
606 wav_format_str(wav->formatTag), 2);
607 return SOX_EOF;
608 }
609
610 lsx_readw(ft, &wav->samplesPerBlock);
611 len -= 2;
612
613 bytesPerBlock = 65;
614
615 if (wav->blockAlign != 65) {
616 lsx_fail_errno(ft, SOX_EOF,
617 "format[%s]: expects blockAlign(%d) = %d",
618 wav_format_str(wav->formatTag), wav->blockAlign, 65);
619 return SOX_EOF;650 return SOX_EOF;
620 }
621
622 if (wav->samplesPerBlock != 320) {
623 lsx_fail_errno(ft, SOX_EOF,
624 "format[%s]: expects samplesPerBlock(%d) = %d",
625 wav_format_str(wav->formatTag),
626 wav->samplesPerBlock, 320);
627 return SOX_EOF;
628 }
629 651
630 bytespersample = 2; /* AFTER de-compression */652 bytespersample = 2; /* AFTER de-compression */
631 break;653 break;
632 654
633 default:655 default:
634 bytespersample = (wBitsPerSample + 7) / 8;656 bytespersample = (wav->bitsPerSample + 7) / 8;
635 break;657 break;
636 }658 }
637 659
638 /* User options take precedence */660 /* User options take precedence */
639 if (!ft->encoding.bits_per_sample ||661 if (!ft->encoding.bits_per_sample ||
640 ft->encoding.bits_per_sample == wBitsPerSample)662 ft->encoding.bits_per_sample == wav->bitsPerSample)
641 ft->encoding.bits_per_sample = wBitsPerSample;663 ft->encoding.bits_per_sample = wav->bitsPerSample;
642 else664 else
643 lsx_warn("User options overriding size read in .wav header");665 lsx_warn("User options overriding size read in .wav header");
644 666

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t