Support a couple of other wav file variants.

This commit is contained in:
Shpoike 2024-08-25 02:29:35 +01:00
parent 75ee7daa82
commit e002c43430

View file

@ -756,12 +756,28 @@ static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int
COM_CharBias(data + info.dataofs, info.samples*info.numchannels); COM_CharBias(data + info.dataofs, info.samples*info.numchannels);
format = QAF_S8; format = QAF_S8;
} }
else if (info.format == 1 && info.bitwidth == 16) //signed shorts else if (info.format == 1 && (info.bitwidth > 8 && info.bitwidth <= 16)) //signed shorts
{ {
COM_SwapLittleShortBlock((short *)(data + info.dataofs), info.samples*info.numchannels); COM_SwapLittleShortBlock((short *)(data + info.dataofs), info.samples*info.numchannels);
format = QAF_S16; format = QAF_S16;
} }
else if (info.format == 1 && info.bitwidth == 32) //24 or 32bit int audio else if (info.format == 1 && (info.bitwidth > 16 && info.bitwidth <= 24))
{ //packed
short *out = (short *)(data + info.dataofs);
qbyte *in = (qbyte *)(data + info.dataofs);
int s;
size_t samples = info.samples*info.numchannels;
while(samples --> 0)
{
s = *in++<<0;
s |= *in++<<8;
s |= *in++<<16;
s |= 0 <<24;
*out++ = s>>8; //just drop the least significant bits.
}
format = QAF_S16;
}
else if (info.format == 1 && (info.bitwidth > 24 && info.bitwidth <= 32)) //24(padded) or 32bit int audio
{ {
short *out = (short *)(data + info.dataofs); short *out = (short *)(data + info.dataofs);
int *in = (int *)(data + info.dataofs); int *in = (int *)(data + info.dataofs);
@ -784,6 +800,25 @@ static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int
} }
format = QAF_F32; format = QAF_F32;
} }
else if (info.format == 3 && info.bitwidth == 64) //signed doubles, converted to floats cos doubles is just silly.
{
if (bigendian)
{
size_t i = info.samples*info.numchannels;
qint64_t *in = (qint64_t*)(data + info.dataofs);
float *out = (short *)(data + info.dataofs);
union {
qint64_t i;
double d;
} s;
while(i --> 0)
{
s.i = LittleI64(in[i]);
out[i] = s.d;
}
}
format = QAF_F32;
}
#else #else
else if (info.format == 3 && info.bitwidth == 32) //signed floats else if (info.format == 3 && info.bitwidth == 32) //signed floats
{ {
@ -799,6 +834,25 @@ static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int
} }
format = QAF_S16; format = QAF_S16;
} }
else if (info.format == 3 && info.bitwidth == 64) //signed doubles
{
short *out = (short *)(data + info.dataofs);
qint64_t *in = (qint64_t *)(data + info.dataofs);
union {
qint64_t i;
double d;
} s;
size_t samples = info.samples*info.numchannels;
int t;
while(samples --> 0)
{ //in place size conversion, so we need to do it forwards.
s.i = LittleI64(*in++);
t = s.d * 32767;
t = bound(-32768, t, 32767);
*out++ = t;
}
format = QAF_S16;
}
#endif #endif
else else
{ {
@ -810,7 +864,7 @@ static qboolean QDECL S_LoadWavSound (sfx_t *s, qbyte *data, size_t datalen, int
case 6/*WAVE_FORMAT_ALAW*/: Con_Printf ("%s uses unsupported a-law format.\n", s->name); break; case 6/*WAVE_FORMAT_ALAW*/: Con_Printf ("%s uses unsupported a-law format.\n", s->name); break;
case 7/*WAVE_FORMAT_MULAW*/: Con_Printf ("%s uses unsupported mu-law format.\n", s->name); break; case 7/*WAVE_FORMAT_MULAW*/: Con_Printf ("%s uses unsupported mu-law format.\n", s->name); break;
case 0xfffe/*WAVE_FORMAT_EXTENSIBLE*/: case 0xfffe/*WAVE_FORMAT_EXTENSIBLE*/:
default: Con_Printf ("%s has an unsupported format (%#x).\n", s->name, info.format); break; default: Con_Printf ("%s has an unsupported format (%#"PRIX16").\n", s->name, info.format); break;
} }
return false; return false;
} }
@ -1246,12 +1300,28 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
return info; return info;
} }
ctx.data_p += 8; ctx.data_p += 8;
info.format = GetLittleShort(&ctx); info.format = (unsigned short)GetLittleShort(&ctx);
info.numchannels = GetLittleShort(&ctx); info.numchannels = (unsigned short)GetLittleShort(&ctx);
info.rate = GetLittleLong(&ctx); info.rate = GetLittleLong(&ctx);
ctx.data_p += 4+2; ctx.data_p += 4; //nAvgBytesPerSec
info.bitwidth = GetLittleShort(&ctx); ctx.data_p += 2; //nBlockAlign
info.bitwidth = (unsigned short)GetLittleShort(&ctx); //meant to be a multiple of 8, but when its not we will treat it as 'nValidBits' and assume the lower bits are padded to bytes.
if (info.format == 0xfffe)
{
if (GetLittleShort(&ctx) >= 22) //cbSize
{
ctx.data_p += 2; //wValidBitsPerSample. don't really care
ctx.data_p += 4; //dwChannelMask. don't really care.
if (!memcmp(ctx.data_p, "\x01\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71", 16))
info.format = 1; //pcm(regular ints)
else if (!memcmp(ctx.data_p, "\x03\x00\x00\x00\x00\x00\x10\x00\x80\x00\x00\xaa\x00\x38\x9b\x71", 16))
info.format = 3; //float
//else leave it unusable.
ctx.data_p += 16; //SubFormat. convert to the real format
}
}
// get cue chunk // get cue chunk
chunklen = FindChunk(&ctx, "cue "); chunklen = FindChunk(&ctx, "cue ");
@ -1286,7 +1356,7 @@ static wavinfo_t GetWavinfo (char *name, qbyte *wav, int wavlength)
} }
ctx.data_p += 8; ctx.data_p += 8;
samples = (chunklen<<3) / info.bitwidth / info.numchannels; samples = (chunklen<<3) / ((info.bitwidth+7)&~7) / info.numchannels;
if (info.samples) if (info.samples)
{ {