ref: 82fb783babaa341b64599850a62bf12bc5b40025
parent: 1cdc830867f1a0edcca70884abef27c2661f1d56
author: robs <robs>
date: Wed Nov 22 15:50:44 EST 2006
Added support for WAVE_FORMAT_EXTENSIBLE for 24 bit PCM wav fmt.
--- a/Changelog
+++ b/Changelog
@@ -39,7 +39,8 @@
effects: synth, deemph, vibro. (robs)
o Fix wav file handler discarding the last PCM sample in certain
circumstances. (robs)
- o Add support for 24-bit PCM raw, wav, & flac files. (robs)
+ o Add support for 24-bit PCM raw, wav (WAVE_FORMAT_EXTENSIBLE) [FR# 801015],
+ & flac files. (robs)
sox-12.18.2
-----------
--- a/src/wav.c
+++ b/src/wav.c
@@ -508,6 +508,40 @@
st_readw(ft, &wBitsPerSample); /* bits per sample per channel */
len -= 16;
+ if (wav->formatTag == WAVE_FORMAT_EXTENSIBLE)
+ {
+ uint16_t extensionSize;
+ uint16_t numberOfValidBits;
+ uint32_t speakerPositionMask;
+ uint16_t subFormatTag;
+ uint8_t dummyByte;
+ int i;
+
+ if (wFmtSize < 18)
+ {
+ st_fail_errno(ft,ST_EHDR,"WAVE file fmt chunk is too short");
+ return ST_EOF;
+ }
+ st_readw(ft, &extensionSize);
+ len -= 2;
+ if (extensionSize < 22)
+ {
+ st_fail_errno(ft,ST_EHDR,"WAVE file fmt chunk is too short");
+ return ST_EOF;
+ }
+ st_readw(ft, &numberOfValidBits);
+ st_readdw(ft, &speakerPositionMask);
+ st_readw(ft, &subFormatTag);
+ for (i = 0; i < 14; ++i) st_readb(ft, &dummyByte);
+ len -= 22;
+ if (numberOfValidBits != wBitsPerSample)
+ {
+ st_fail_errno(ft,ST_EHDR,"WAVE file fmt with padded samples is not supported yet");
+ return ST_EOF;
+ }
+ wav->formatTag = subFormatTag;
+ }
+
switch (wav->formatTag)
{
case WAVE_FORMAT_UNKNOWN:
@@ -1364,6 +1398,7 @@
/* internal variables, intermediate values etc */
int bytespersample; /* (uncompressed) bytes per sample (per channel) */
long blocksWritten = 0;
+ bool isExtensible = false; /* WAVE_FORMAT_EXTENSIBLE? */
dwSamplesPerSecond = ft->info.rate;
wChannels = ft->info.channels;
@@ -1529,7 +1564,12 @@
dwDataLength = (dwDataLength+1) & ~1; /*round up to even */
#endif
- if (wFormatTag != WAVE_FORMAT_PCM)
+ if (wFormatTag == WAVE_FORMAT_PCM && wBitsPerSample > ST_SIZE_16BIT)
+ {
+ isExtensible = true;
+ wFmtSize += 2 + 22;
+ }
+ else if (wFormatTag != WAVE_FORMAT_PCM)
wFmtSize += 2+wExtSize; /* plus ExtData */
wRiffLength = 4 + (8+wFmtSize) + (8+dwDataLength);
@@ -1558,7 +1598,7 @@
st_writes(ft, "WAVE");
st_writes(ft, "fmt ");
st_writedw(ft, wFmtSize);
- st_writew(ft, wFormatTag);
+ st_writew(ft, isExtensible? WAVE_FORMAT_EXTENSIBLE : wFormatTag);
st_writew(ft, wChannels);
st_writedw(ft, dwSamplesPerSecond);
st_writedw(ft, dwAvgBytesPerSec);
@@ -1565,6 +1605,20 @@
st_writew(ft, wBlockAlign);
st_writew(ft, wBitsPerSample); /* end info common to all fmts */
+ if (isExtensible)
+ {
+ int i;
+ static const char guid[14] = "\x00\x00\x00\x00\x10\x00\x80\x00\x00\xAA\x00\x38\x9B\x71";
+ st_writew(ft, 22);
+ st_writew(ft, wBitsPerSample); /* No padding in container */
+ st_writedw(ft, 0); /* Speaker mapping not specified */
+ st_writew(ft, wFormatTag);
+ for (i = 0; i < array_length(guid); ++i)
+ {
+ st_writeb(ft, guid[i]);
+ }
+ }
+ else
/* if not PCM, we need to write out wExtSize even if wExtSize=0 */
if (wFormatTag != WAVE_FORMAT_PCM)
st_writew(ft,wExtSize);
@@ -1593,7 +1647,7 @@
}
/* if not PCM, write the 'fact' chunk */
- if (wFormatTag != WAVE_FORMAT_PCM){
+ if (isExtensible || wFormatTag != WAVE_FORMAT_PCM){
st_writes(ft, "fact");
st_writedw(ft,dwFactSize);
st_writedw(ft,dwSamplesWritten);
--- a/src/wav.h
+++ b/src/wav.h
@@ -25,6 +25,7 @@
#define WAVE_FORMAT_MPEGLAYER3 (0x0055)
#define WAVE_FORMAT_G726_ADPCM (0x0064)
#define WAVE_FORMAT_G722_ADPCM (0x0065)
+#define WAVE_FORMAT_EXTENSIBLE (0xfffe)
#endif /* WAV_H_INCLUDED */