mirror of
https://github.com/Shpoike/Quakespasm.git
synced 2025-02-15 16:41:22 +00:00
* snd_codec: store the samplebits value in the snd_info_t struct,
and add a new blocksize field to it which the flac decoder can use. updated decoder sources for the snd_info_t changes, where I made minor tidy-ups too, tightening several format checks and fixing a few gotchas in snd_wave.c and snd_mem.c. * snd_flac.c: adjusted for snd_info_t changes. no longed storing metadata->data.stream_info in our private data, but just storing a pointer to the stream->info structure. No longer checking the metadata total_samples field (the FLAC__StreamMetadata_StreamInfo doesn't seem to have any alignment or pack attributes and I don't safe with its offset across different compilers), but added check to make sure that we hit and parsed a STREAMINFO metadata instead, and our new state seems just fine for validating the file. git-svn-id: http://svn.code.sf.net/p/quakespasm/code/trunk/quakespasm@859 af15c1b1-3010-417e-b628-4374ebc0bcbd
This commit is contained in:
parent
a99bea5110
commit
aad0ec327a
7 changed files with 51 additions and 35 deletions
|
@ -29,9 +29,10 @@
|
||||||
typedef struct snd_info_s
|
typedef struct snd_info_s
|
||||||
{
|
{
|
||||||
int rate;
|
int rate;
|
||||||
int width;
|
int bits, width;
|
||||||
int channels;
|
int channels;
|
||||||
int samples;
|
int samples;
|
||||||
|
int blocksize;
|
||||||
int size;
|
int size;
|
||||||
int dataofs;
|
int dataofs;
|
||||||
} snd_info_t;
|
} snd_info_t;
|
||||||
|
|
|
@ -68,7 +68,7 @@
|
||||||
typedef struct {
|
typedef struct {
|
||||||
FLAC__StreamDecoder *decoder;
|
FLAC__StreamDecoder *decoder;
|
||||||
fshandle_t *file;
|
fshandle_t *file;
|
||||||
FLAC__StreamMetadata_StreamInfo info;
|
snd_info_t *info;
|
||||||
byte *buffer;
|
byte *buffer;
|
||||||
int size, pos, error;
|
int size, pos, error;
|
||||||
} flacfile_t;
|
} flacfile_t;
|
||||||
|
@ -144,26 +144,25 @@ flac_write_func (const FLAC__StreamDecoder *decoder,
|
||||||
void *client_data)
|
void *client_data)
|
||||||
{
|
{
|
||||||
flacfile_t *ff = (flacfile_t *) client_data;
|
flacfile_t *ff = (flacfile_t *) client_data;
|
||||||
int bps = ff->info.bits_per_sample / 8;
|
|
||||||
|
|
||||||
if (!ff->buffer) {
|
if (!ff->buffer) {
|
||||||
#if 1 /*!defined(CODECS_USE_ZONE)*/
|
#if 1 /*!defined(CODECS_USE_ZONE)*/
|
||||||
ff->buffer = (byte *) malloc (ff->info.max_blocksize * ff->info.channels * bps);
|
ff->buffer = (byte *) malloc (ff->info->blocksize * ff->info->channels * ff->info->width);
|
||||||
if (!ff->buffer) {
|
if (!ff->buffer) {
|
||||||
ff->error = -1; /* needn't set this here, but... */
|
ff->error = -1; /* needn't set this here, but... */
|
||||||
Con_Printf("Insufficient memory for fLaC audio\n");
|
Con_Printf("Insufficient memory for fLaC audio\n");
|
||||||
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
return FLAC__STREAM_DECODER_WRITE_STATUS_ABORT;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
ff->buffer = (byte *) Z_Malloc (ff->info.max_blocksize * ff->info.channels * bps);
|
ff->buffer = (byte *) Z_Malloc (ff->info->blocksize * ff->info->channels * ff->info->width);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (ff->info.channels == 1)
|
if (ff->info->channels == 1)
|
||||||
{
|
{
|
||||||
unsigned i;
|
unsigned i;
|
||||||
const FLAC__int32 *in = buffer[0];
|
const FLAC__int32 *in = buffer[0];
|
||||||
|
|
||||||
if (ff->info.bits_per_sample == 8)
|
if (ff->info->bits == 8)
|
||||||
{
|
{
|
||||||
byte *out = ff->buffer;
|
byte *out = ff->buffer;
|
||||||
for (i = 0; i < frame->header.blocksize; i++)
|
for (i = 0; i < frame->header.blocksize; i++)
|
||||||
|
@ -182,7 +181,7 @@ flac_write_func (const FLAC__StreamDecoder *decoder,
|
||||||
const FLAC__int32 *li = buffer[0];
|
const FLAC__int32 *li = buffer[0];
|
||||||
const FLAC__int32 *ri = buffer[1];
|
const FLAC__int32 *ri = buffer[1];
|
||||||
|
|
||||||
if (ff->info.bits_per_sample == 8)
|
if (ff->info->bits == 8)
|
||||||
{
|
{
|
||||||
char *lo = (char *) ff->buffer + 0;
|
char *lo = (char *) ff->buffer + 0;
|
||||||
char *ro = (char *) ff->buffer + 1;
|
char *ro = (char *) ff->buffer + 1;
|
||||||
|
@ -204,7 +203,7 @@ flac_write_func (const FLAC__StreamDecoder *decoder,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ff->size = frame->header.blocksize * bps * ff->info.channels;
|
ff->size = frame->header.blocksize * ff->info->width * ff->info->channels;
|
||||||
ff->pos = 0;
|
ff->pos = 0;
|
||||||
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
|
||||||
}
|
}
|
||||||
|
@ -215,7 +214,14 @@ flac_meta_func (const FLAC__StreamDecoder *decoder,
|
||||||
{
|
{
|
||||||
flacfile_t *ff = (flacfile_t *) client_data;
|
flacfile_t *ff = (flacfile_t *) client_data;
|
||||||
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
|
if (metadata->type == FLAC__METADATA_TYPE_STREAMINFO)
|
||||||
ff->info = metadata->data.stream_info;
|
{
|
||||||
|
ff->info->rate = metadata->data.stream_info.sample_rate;
|
||||||
|
ff->info->bits = metadata->data.stream_info.bits_per_sample;
|
||||||
|
ff->info->width = ff->info->bits / 8;
|
||||||
|
ff->info->channels = metadata->data.stream_info.channels;
|
||||||
|
ff->info->blocksize = metadata->data.stream_info.max_blocksize;
|
||||||
|
ff->info->dataofs = 0; /* got the STREAMINFO metadata */
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -248,7 +254,9 @@ static snd_stream_t *S_FLAC_CodecOpenStream (const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->priv = ff;
|
stream->priv = ff;
|
||||||
|
ff->info = & stream->info;
|
||||||
ff->file = & stream->fh;
|
ff->file = & stream->fh;
|
||||||
|
ff->info->dataofs = -1; /* check for STREAMINFO metadata existence */
|
||||||
|
|
||||||
#ifdef LEGACY_FLAC
|
#ifdef LEGACY_FLAC
|
||||||
FLAC__seekable_stream_decoder_set_error_callback (ff->decoder, flac_error_func);
|
FLAC__seekable_stream_decoder_set_error_callback (ff->decoder, flac_error_func);
|
||||||
|
@ -280,32 +288,31 @@ static snd_stream_t *S_FLAC_CodecOpenStream (const char *filename)
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = FLAC__stream_decoder_process_until_end_of_metadata (ff->decoder);
|
rc = FLAC__stream_decoder_process_until_end_of_metadata (ff->decoder);
|
||||||
if (rc == false)
|
if (rc == false || ff->error)
|
||||||
{
|
{
|
||||||
rc = FLAC__stream_decoder_get_state(ff->decoder);
|
rc = FLAC__stream_decoder_get_state(ff->decoder);
|
||||||
Con_Printf("%s not a valid fLaC file? (error %i)\n",
|
Con_Printf("%s not a valid flac file? (decoder state %i)\n",
|
||||||
filename, rc);
|
filename, rc);
|
||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
if (ff->error) /* set by flac_error_func(). can we hit it here?? */
|
|
||||||
goto _fail;
|
|
||||||
|
|
||||||
if (ff->info.total_samples == 0)
|
if (ff->info->dataofs < 0)
|
||||||
{
|
{
|
||||||
Con_Printf("Zero sample count in %s\n", filename);
|
Con_Printf("%s has no STREAMINFO\n", filename);
|
||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
if (ff->info.channels != 1 && ff->info.channels != 2)
|
if (ff->info->bits != 8 && ff->info->bits != 16)
|
||||||
|
{
|
||||||
|
Con_Printf("%s is not 8 or 16 bit\n", filename);
|
||||||
|
goto _fail;
|
||||||
|
}
|
||||||
|
if (ff->info->channels != 1 && ff->info->channels != 2)
|
||||||
{
|
{
|
||||||
Con_Printf("Unsupported number of channels %d in %s\n",
|
Con_Printf("Unsupported number of channels %d in %s\n",
|
||||||
ff->info.channels, filename);
|
ff->info->channels, filename);
|
||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->info.rate = ff->info.sample_rate;
|
|
||||||
stream->info.width = ff->info.bits_per_sample / 8;
|
|
||||||
stream->info.channels = ff->info.channels;
|
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
_fail:
|
_fail:
|
||||||
if (ff->decoder)
|
if (ff->decoder)
|
||||||
|
|
|
@ -297,7 +297,10 @@ wavinfo_t GetWavinfo (const char *name, byte *wav, int wavlength)
|
||||||
info.channels = GetLittleShort();
|
info.channels = GetLittleShort();
|
||||||
info.rate = GetLittleLong();
|
info.rate = GetLittleLong();
|
||||||
data_p += 4 + 2;
|
data_p += 4 + 2;
|
||||||
info.width = GetLittleShort() / 8;
|
i = GetLittleShort();
|
||||||
|
if (i != 8 && i != 16)
|
||||||
|
return info;
|
||||||
|
info.width = i / 8;
|
||||||
|
|
||||||
// get cue chunk
|
// get cue chunk
|
||||||
FindChunk("cue ");
|
FindChunk("cue ");
|
||||||
|
|
|
@ -139,19 +139,23 @@ static snd_stream_t *S_MP3_CodecOpenStream (const char *filename)
|
||||||
switch (encoding)
|
switch (encoding)
|
||||||
{
|
{
|
||||||
case MPG123_ENC_UNSIGNED_8:
|
case MPG123_ENC_UNSIGNED_8:
|
||||||
|
stream->info.bits = 8;
|
||||||
stream->info.width = 1;
|
stream->info.width = 1;
|
||||||
break;
|
break;
|
||||||
case MPG123_ENC_SIGNED_8:
|
case MPG123_ENC_SIGNED_8:
|
||||||
/* unsupported: force mpg123 to convert */
|
/* unsupported: force mpg123 to convert */
|
||||||
|
stream->info.bits = 8;
|
||||||
stream->info.width = 1;
|
stream->info.width = 1;
|
||||||
encoding = MPG123_ENC_UNSIGNED_8;
|
encoding = MPG123_ENC_UNSIGNED_8;
|
||||||
break;
|
break;
|
||||||
case MPG123_ENC_SIGNED_16:
|
case MPG123_ENC_SIGNED_16:
|
||||||
|
stream->info.bits = 16;
|
||||||
stream->info.width = 2;
|
stream->info.width = 2;
|
||||||
break;
|
break;
|
||||||
case MPG123_ENC_UNSIGNED_16:
|
case MPG123_ENC_UNSIGNED_16:
|
||||||
default:
|
default:
|
||||||
/* unsupported: force mpg123 to convert */
|
/* unsupported: force mpg123 to convert */
|
||||||
|
stream->info.bits = 16;
|
||||||
stream->info.width = 2;
|
stream->info.width = 2;
|
||||||
encoding = MPG123_ENC_SIGNED_16;
|
encoding = MPG123_ENC_SIGNED_16;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -141,6 +141,7 @@ static snd_stream_t *S_OPUS_CodecOpenStream (const char *filename)
|
||||||
stream->info.rate = 48000;
|
stream->info.rate = 48000;
|
||||||
stream->info.channels = op_info->channel_count;
|
stream->info.channels = op_info->channel_count;
|
||||||
/* op_read() yields 16-bit output using native endian ordering: */
|
/* op_read() yields 16-bit output using native endian ordering: */
|
||||||
|
stream->info.bits = 16;
|
||||||
stream->info.width = 2;
|
stream->info.width = 2;
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
|
|
||||||
/* Vorbis codec can return the samples in a number of different
|
/* Vorbis codec can return the samples in a number of different
|
||||||
* formats, we use the standard signed short format. */
|
* formats, we use the standard signed short format. */
|
||||||
|
#define VORBIS_SAMPLEBITS 16
|
||||||
#define VORBIS_SAMPLEWIDTH 2
|
#define VORBIS_SAMPLEWIDTH 2
|
||||||
#define VORBIS_SIGNED_DATA 1
|
#define VORBIS_SIGNED_DATA 1
|
||||||
|
|
||||||
|
@ -87,6 +88,7 @@ static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
ovFile = (OggVorbis_File *) Z_Malloc(sizeof(OggVorbis_File));
|
ovFile = (OggVorbis_File *) Z_Malloc(sizeof(OggVorbis_File));
|
||||||
|
stream->priv = ovFile;
|
||||||
res = OV_OPEN_CALLBACKS(&stream->fh, ovFile, NULL, 0, ovc_qfs);
|
res = OV_OPEN_CALLBACKS(&stream->fh, ovFile, NULL, 0, ovc_qfs);
|
||||||
if (res != 0)
|
if (res != 0)
|
||||||
{
|
{
|
||||||
|
@ -95,8 +97,6 @@ static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename)
|
||||||
goto _fail;
|
goto _fail;
|
||||||
}
|
}
|
||||||
|
|
||||||
stream->priv = ovFile;
|
|
||||||
|
|
||||||
if (!ov_seekable(ovFile))
|
if (!ov_seekable(ovFile))
|
||||||
{
|
{
|
||||||
Con_Printf("Stream %s not seekable.\n", filename);
|
Con_Printf("Stream %s not seekable.\n", filename);
|
||||||
|
@ -128,6 +128,7 @@ static snd_stream_t *S_VORBIS_CodecOpenStream (const char *filename)
|
||||||
|
|
||||||
stream->info.rate = ovf_info->rate;
|
stream->info.rate = ovf_info->rate;
|
||||||
stream->info.channels = ovf_info->channels;
|
stream->info.channels = ovf_info->channels;
|
||||||
|
stream->info.bits = VORBIS_SAMPLEBITS;
|
||||||
stream->info.width = VORBIS_SAMPLEWIDTH;
|
stream->info.width = VORBIS_SAMPLEWIDTH;
|
||||||
|
|
||||||
return stream;
|
return stream;
|
||||||
|
|
|
@ -117,7 +117,6 @@ static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *inf
|
||||||
{
|
{
|
||||||
char dump[16];
|
char dump[16];
|
||||||
int wav_format;
|
int wav_format;
|
||||||
int bits;
|
|
||||||
int fmtlen = 0;
|
int fmtlen = 0;
|
||||||
|
|
||||||
if (fread(dump, 1, 12, file) < 12 ||
|
if (fread(dump, 1, 12, file) < 12 ||
|
||||||
|
@ -147,15 +146,15 @@ static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *inf
|
||||||
info->rate = FGetLittleLong(file);
|
info->rate = FGetLittleLong(file);
|
||||||
FGetLittleLong(file);
|
FGetLittleLong(file);
|
||||||
FGetLittleShort(file);
|
FGetLittleShort(file);
|
||||||
bits = FGetLittleShort(file);
|
info->bits = FGetLittleShort(file);
|
||||||
|
|
||||||
if (bits != 8 && bits != 16)
|
if (info->bits != 8 && info->bits != 16)
|
||||||
{
|
{
|
||||||
Con_Printf("%s is not 8 or 16 bit\n", name);
|
Con_Printf("%s is not 8 or 16 bit\n", name);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->width = bits / 8;
|
info->width = info->bits / 8;
|
||||||
info->dataofs = 0;
|
info->dataofs = 0;
|
||||||
|
|
||||||
/* Skip the rest of the format chunk if required */
|
/* Skip the rest of the format chunk if required */
|
||||||
|
@ -172,6 +171,12 @@ static qboolean WAV_ReadRIFFHeader(const char *name, FILE *file, snd_info_t *inf
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (info->channels != 1 && info->channels != 2)
|
||||||
|
{
|
||||||
|
Con_Printf("Unsupported number of channels %d in %s\n",
|
||||||
|
info->channels, name);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
info->samples = (info->size / info->width) / info->channels;
|
info->samples = (info->size / info->width) / info->channels;
|
||||||
if (info->samples == 0)
|
if (info->samples == 0)
|
||||||
{
|
{
|
||||||
|
@ -204,12 +209,6 @@ snd_stream_t *S_WAV_CodecOpenStream(const char *filename)
|
||||||
* file by ourselves from now on. */
|
* file by ourselves from now on. */
|
||||||
if (!WAV_ReadRIFFHeader(filename, stream->fh.file, &stream->info))
|
if (!WAV_ReadRIFFHeader(filename, stream->fh.file, &stream->info))
|
||||||
goto _fail;
|
goto _fail;
|
||||||
if (stream->info.channels != 1 && stream->info.channels != 2)
|
|
||||||
{
|
|
||||||
Con_Printf("Unsupported number of channels %d in %s\n",
|
|
||||||
stream->info.channels, filename);
|
|
||||||
goto _fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
stream->fh.start = ftell(stream->fh.file); /* reset to data position */
|
stream->fh.start = ftell(stream->fh.file); /* reset to data position */
|
||||||
if (stream->fh.start - start + stream->info.size > stream->fh.length)
|
if (stream->fh.start - start + stream->info.size > stream->fh.length)
|
||||||
|
|
Loading…
Reference in a new issue