* 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:
sezero 2013-07-22 11:41:14 +00:00
parent a99bea5110
commit aad0ec327a
7 changed files with 51 additions and 35 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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 ");

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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)