History

wav: move adpcm/gsm fmt parsing to separate functions

Mans Rullgard committed 6 years ago

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

Showing the changes to src (1 of 1 file). Show all

Unified · Split

src/wav.c+144−122
@@ -69,6 +69,7 @@ typedef struct { · 68 unmodified lines
6969 unsigned short formatTag; /* What type of encoding file is using */
7070 unsigned short samplesPerBlock;
7171 unsigned short blockAlign;
72+ uint16_t bitsPerSample; /* bits per sample */
7273 size_t dataStart; /* need to for seeking */
7374 int ignoreSize; /* ignoreSize allows us to process 32-bit WAV files that are
7475 * 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
102103 /* IMA ADPCM Support Functions Section */
103104 /****************************************************************************/
104105
106+static 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+
105143 /*
106144 *
107145 * ImaAdpcmReadBlock - Grab and decode complete block of samples
@@ -142,6 +180,74 @@ static unsigned short ImaAdpcmReadBlock(sox_format_t * ft) · 34 unmodified lines
142180 /* MS ADPCM Support Functions Section */
143181 /****************************************************************************/
144182
183+static 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+
145251 /*
146252 *
147253 * AdpcmReadBlock - Grab and decode complete block of samples
@@ -220,6 +326,36 @@ static int xxxAdpcmWriteBlock(sox_format_t * ft) · 72 unmodified lines
220326 /****************************************************************************/
221327 /* WAV GSM6.10 support functions */
222328 /****************************************************************************/
329+
330+static 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+
223359 /* create the gsm object, malloc buffer for 160*2 samples */
224360 static int wavgsminit(sox_format_t * ft)
225361 {
@@ -382,9 +518,7 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 156 unmodified lines
382518 uint16_t wChannels; /* number of channels */
383519 uint32_t dwSamplesPerSecond; /* samples per second per channel */
384520 uint32_t dwAvgBytesPerSec; /* estimate of bytes per second needed */
385− uint16_t wBitsPerSample; /* bits per sample */
386521 uint16_t wExtSize = 0; /* extended field for non-PCM */
387− size_t bytesPerBlock = 0;
388522 int bytespersample; /* bytes per sample (per channel */
389523 sox_encoding_t enc = SOX_ENCODING_UNKNOWN;;
390524
@@ -398,7 +532,7 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 7 unmodified lines
398532 lsx_readdw(ft, &dwSamplesPerSecond);
399533 lsx_readdw(ft, &dwAvgBytesPerSec); /* Average bytes/second */
400534 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 */
402536 len -= 16;
403537
404538 /* 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
437571 lsx_skipbytes(ft, 14);
438572 len -= 22;
439573
440− if (numberOfValidBits != wBitsPerSample) {
574+ if (numberOfValidBits != wav->bitsPerSample) {
441575 lsx_fail_errno(ft, SOX_EHDR, "WAVE file fmt with padded samples is not supported yet");
442576 return SOX_EOF;
443577 }
@@ -498,147 +632,35 @@ static int wav_read_fmt(sox_format_t *ft, uint32_t len) · 54 unmodified lines
498632
499633 switch (wav->formatTag) {
500634 case WAVE_FORMAT_ADPCM:
501− if (wExtSize < 4) {
502− lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects wExtSize >= %d",
503− wav_format_str(wav->formatTag), 4);
635+ if (wav_ms_adpcm_fmt(ft, len))
504636 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− }
564637
565638 bytespersample = 2; /* AFTER de-compression */
566639 break;
567640
568641 case WAVE_FORMAT_IMA_ADPCM:
569− if (wExtSize < 2) {
570− lsx_fail_errno(ft, SOX_EOF, "format[%s]: expects wExtSize >= %d",
571− wav_format_str(wav->formatTag), 2);
642+ if (wav_ima_adpcm_fmt(ft, len))
572643 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));
598644
599645 bytespersample = 2; /* AFTER de-compression */
600646 break;
601647
602− /* GSM formats have extended fmt chunk. Check for those cases. */
603648 case WAVE_FORMAT_GSM610:
604− if (wExtSize < 2) {
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);
649+ if (wav_gsm_fmt(ft, len))
619650 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− }
629651
630652 bytespersample = 2; /* AFTER de-compression */
631653 break;
632654
633655 default:
634− bytespersample = (wBitsPerSample + 7) / 8;
656+ bytespersample = (wav->bitsPerSample + 7) / 8;
635657 break;
636658 }
637659
638660 /* User options take precedence */
639661 if (!ft->encoding.bits_per_sample ||
640− ft->encoding.bits_per_sample == wBitsPerSample)
641− ft->encoding.bits_per_sample = wBitsPerSample;
662+ ft->encoding.bits_per_sample == wav->bitsPerSample)
663+ ft->encoding.bits_per_sample = wav->bitsPerSample;
642664 else
643665 lsx_warn("User options overriding size read in .wav header");
644666

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