ref: f105762dd1ce7c0c9317e3b0d205804d1360b418
parent: 653a411b44f1b69d1e7bb7a4433fe48fdb548c45
author: Mans Rullgard <mans@mansr.com>
date: Fri Aug 7 17:49:52 EDT 2020
wav: expand format table with encoding and fmt parser Use the format table instead of switch statement to find the encoding and fmt parsing function.
--- a/src/wav.c
+++ b/src/wav.c
@@ -121,6 +121,8 @@
struct wave_format {
uint16_t tag;
const char *name;
+ sox_encoding_t encoding;
+ int (*read_fmt)(sox_format_t *ft, uint32_t len);
};
static const char *wav_format_str(unsigned tag);
@@ -533,16 +535,45 @@
/* General Sox WAV file code */
/****************************************************************************/
+static int wav_pcm_fmt(sox_format_t *ft, uint32_t len)
+{
+ priv_t *wav = ft->priv;
+ int bps = (wav->bitsPerSample + 7) / 8;
+
+ if (bps == 1) {
+ ft->encoding.encoding = SOX_ENCODING_UNSIGNED;
+ } else if (bps <= 4) {
+ ft->encoding.encoding = SOX_ENCODING_SIGN2;
+ } else {
+ lsx_fail_errno(ft, SOX_EFMT, "%d bytes per sample not suppored", bps);
+ return SOX_EOF;
+ }
+
+ return SOX_SUCCESS;
+}
+
static const struct wave_format wave_formats[] = {
{ WAVE_FORMAT_UNKNOWN, "Unknown Wave Type" },
- { WAVE_FORMAT_PCM, "PCM" },
- { WAVE_FORMAT_ADPCM, "Microsoft ADPCM" },
- { WAVE_FORMAT_IEEE_FLOAT, "IEEE Float" },
+ { WAVE_FORMAT_PCM, "PCM",
+ SOX_ENCODING_UNKNOWN,
+ wav_pcm_fmt,
+ },
+ { WAVE_FORMAT_ADPCM, "Microsoft ADPCM",
+ SOX_ENCODING_MS_ADPCM,
+ wav_ms_adpcm_fmt,
+ },
+ { WAVE_FORMAT_IEEE_FLOAT, "IEEE Float",
+ SOX_ENCODING_FLOAT },
{ WAVE_FORMAT_IBM_CVSD, "Digispeech CVSD" },
- { WAVE_FORMAT_ALAW, "CCITT A-law" },
- { WAVE_FORMAT_MULAW, "CCITT u-law" },
+ { WAVE_FORMAT_ALAW, "CCITT A-law",
+ SOX_ENCODING_ALAW },
+ { WAVE_FORMAT_MULAW, "CCITT u-law",
+ SOX_ENCODING_ULAW },
{ WAVE_FORMAT_OKI_ADPCM, "OKI ADPCM" },
- { WAVE_FORMAT_IMA_ADPCM, "IMA ADPCM" },
+ { WAVE_FORMAT_IMA_ADPCM, "IMA ADPCM",
+ SOX_ENCODING_IMA_ADPCM,
+ wav_ima_adpcm_fmt,
+ },
{ WAVE_FORMAT_MEDIASPACE_ADPCM, "MediaSpace ADPCM" },
{ WAVE_FORMAT_SIERRA_ADPCM, "Sierra ADPCM" },
{ WAVE_FORMAT_G723_ADPCM, "G.723 ADPCM" },
@@ -556,7 +587,10 @@
{ WAVE_FORMAT_APTX, "aptX" },
{ WAVE_FORMAT_AUDIOFILE_AF10, "Audio File AF10" },
{ WAVE_FORMAT_DOLBY_AC2, "Dolby AC-2" },
- { WAVE_FORMAT_GSM610, "GSM 6.10" },
+ { WAVE_FORMAT_GSM610, "GSM 6.10",
+ SOX_ENCODING_GSM,
+ wav_gsm_fmt,
+ },
{ WAVE_FORMAT_ADPCME, "Antex ADPCME" },
{ WAVE_FORMAT_CONTROL_RES_VQLPC, "Control Resources VQLPC" },
{ WAVE_FORMAT_DIGIREAL, "DSP Solutions REAL" },
@@ -607,8 +641,8 @@
uint32_t dwSamplesPerSecond; /* samples per second per channel */
uint32_t dwAvgBytesPerSec; /* estimate of bytes per second needed */
uint16_t wExtSize = 0; /* extended field for non-PCM */
- int bytespersample; /* bytes per sample (per channel */
- sox_encoding_t enc = SOX_ENCODING_UNKNOWN;;
+ const struct wave_format *fmt;
+ sox_encoding_t user_enc = ft->encoding.encoding;
if (len < 16) {
lsx_fail_errno(ft, SOX_EHDR, "WAVE file fmt chunk is too short");
@@ -685,58 +719,18 @@
else
lsx_report("User options overriding rate read in .wav header");
- switch (wav->formatTag) {
- case WAVE_FORMAT_PCM:
- bytespersample = (wav->bitsPerSample + 7) / 8;
+ fmt = wav_find_format(wav->formatTag);
+ if (!fmt)
+ return wavfail(ft, wav->formatTag);
- if (bytespersample == 1) {
- enc = SOX_ENCODING_UNSIGNED;
- } else if (bytespersample <= 4) {
- enc = SOX_ENCODING_SIGN2;
- } else {
- lsx_fail_errno(ft, SOX_EFMT, "%d bytes per sample not suppored",
- bytespersample);
- return SOX_EOF;
- }
+ /* format handler might override */
+ ft->encoding.encoding = fmt->encoding;
- break;
-
- case WAVE_FORMAT_IEEE_FLOAT:
- enc = SOX_ENCODING_FLOAT;
- break;
-
- case WAVE_FORMAT_ALAW:
- enc = SOX_ENCODING_ALAW;
- break;
-
- case WAVE_FORMAT_MULAW:
- enc = SOX_ENCODING_ULAW;
- break;
-
- case WAVE_FORMAT_ADPCM:
- if (wav_ms_adpcm_fmt(ft, len))
+ if (fmt->read_fmt) {
+ if (fmt->read_fmt(ft, len))
return SOX_EOF;
-
- enc = SOX_ENCODING_MS_ADPCM;
- break;
-
- case WAVE_FORMAT_IMA_ADPCM:
- if (wav_ima_adpcm_fmt(ft, len))
- return SOX_EOF;
-
- enc = SOX_ENCODING_IMA_ADPCM;
- break;
-
- case WAVE_FORMAT_GSM610:
- if (wav_gsm_fmt(ft, len))
- return SOX_EOF;
-
- enc = SOX_ENCODING_GSM;
- break;
-
- default:
+ } else if (!fmt->encoding) {
return wavfail(ft, wav->formatTag);
- break;
}
/* User options take precedence */
@@ -746,11 +740,10 @@
else
lsx_warn("User options overriding size read in .wav header");
- if (ft->encoding.encoding != SOX_ENCODING_UNKNOWN &&
- ft->encoding.encoding != enc)
+ if (user_enc && user_enc != ft->encoding.encoding) {
lsx_report("User options overriding encoding read in .wav header");
- else
- ft->encoding.encoding = enc;
+ ft->encoding.encoding = user_enc;
+ }
return 0;
}