Wave decoder cleanup
git-svn-id: svn://svn.code.sf.net/p/sc2/code/trunk@2707 8092fc87-c524-0410-9efc-e669fe64eaf9
This commit is contained in:
@@ -28,33 +28,36 @@
|
||||
#include "libs/log.h"
|
||||
#include "wav.h"
|
||||
|
||||
#define RIFF 0x46464952 /* "RIFF" */
|
||||
#define WAVE 0x45564157 /* "WAVE" */
|
||||
#define FMT 0x20746D66 /* "fmt " */
|
||||
#define DATA 0x61746164 /* "data" */
|
||||
#define wave_MAKE_ID(x1, x2, x3, x4) \
|
||||
(((x4) << 24) | ((x3) << 16) | ((x2) << 8) | (x1))
|
||||
|
||||
#define wave_RiffID wave_MAKE_ID('R', 'I', 'F', 'F')
|
||||
#define wave_WaveID wave_MAKE_ID('W', 'A', 'V', 'E')
|
||||
#define wave_FmtID wave_MAKE_ID('f', 'm', 't', ' ')
|
||||
#define wave_DataID wave_MAKE_ID('d', 'a', 't', 'a')
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 Id;
|
||||
sint32 Size;
|
||||
uint32 Type;
|
||||
} WAVFileHdr_Struct;
|
||||
uint32 id;
|
||||
sint32 size;
|
||||
uint32 type;
|
||||
} wave_FileHeader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16 Format;
|
||||
uint16 Channels;
|
||||
uint32 SamplesPerSec;
|
||||
uint32 BytesPerSec;
|
||||
uint16 BlockAlign;
|
||||
uint16 BitsPerSample;
|
||||
} WAVFmtHdr_Struct;
|
||||
uint16 format;
|
||||
uint16 channels;
|
||||
uint32 samplesPerSec;
|
||||
uint32 bytesPerSec;
|
||||
uint16 blockAlign;
|
||||
uint16 bitsPerSample;
|
||||
} wave_FormatHeader;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32 Id;
|
||||
uint32 Size;
|
||||
} WAVChunkHdr_Struct;
|
||||
uint32 id;
|
||||
uint32 size;
|
||||
} wave_ChunkHeader;
|
||||
|
||||
|
||||
#define THIS_PTR TFB_SoundDecoder* This
|
||||
@@ -96,7 +99,7 @@ typedef struct tfb_wavesounddecoder
|
||||
// private
|
||||
sint32 last_error;
|
||||
uio_Stream *fp;
|
||||
WAVFmtHdr_Struct FmtHdr;
|
||||
wave_FormatHeader fmtHdr;
|
||||
uint32 data_ofs;
|
||||
uint32 data_size;
|
||||
uint32 max_pcm;
|
||||
@@ -159,53 +162,61 @@ wava_Term (THIS_PTR)
|
||||
}
|
||||
|
||||
static bool
|
||||
wava_readFileHeader (TFB_WaveSoundDecoder* wava, WAVFileHdr_Struct* hdr)
|
||||
read_le_16 (uio_Stream *fp, uint16 *v)
|
||||
{
|
||||
if (!uio_fread (&hdr->Id, 4, 1, wava->fp) ||
|
||||
!uio_fread (&hdr->Size, 4, 1, wava->fp) ||
|
||||
!uio_fread (&hdr->Type, 4, 1, wava->fp))
|
||||
if (!uio_fread (v, sizeof(*v), 1, fp))
|
||||
return false;
|
||||
*v = UQM_SwapLE16 (*v);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
read_le_32 (uio_Stream *fp, uint32 *v)
|
||||
{
|
||||
if (!uio_fread (v, sizeof(*v), 1, fp))
|
||||
return false;
|
||||
*v = UQM_SwapLE32 (*v);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
wava_readFileHeader (TFB_WaveSoundDecoder* wava, wave_FileHeader* hdr)
|
||||
{
|
||||
if (!read_le_32 (wava->fp, &hdr->id) ||
|
||||
!read_le_32 (wava->fp, &hdr->size) ||
|
||||
!read_le_32 (wava->fp, &hdr->type))
|
||||
{
|
||||
wava->last_error = errno;
|
||||
return false;
|
||||
}
|
||||
hdr->Id = UQM_SwapLE32 (hdr->Id);
|
||||
hdr->Size = UQM_SwapLE32 (hdr->Size);
|
||||
hdr->Type = UQM_SwapLE32 (hdr->Type);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
wava_readChunkHeader (TFB_WaveSoundDecoder* wava, WAVChunkHdr_Struct* chunk)
|
||||
wava_readChunkHeader (TFB_WaveSoundDecoder* wava, wave_ChunkHeader* chunk)
|
||||
{
|
||||
if (!uio_fread (&chunk->Id, 4, 1, wava->fp) ||
|
||||
!uio_fread (&chunk->Size, 4, 1, wava->fp))
|
||||
if (!read_le_32 (wava->fp, &chunk->id) ||
|
||||
!read_le_32 (wava->fp, &chunk->size))
|
||||
{
|
||||
wava->last_error = errno;
|
||||
return false;
|
||||
|
||||
chunk->Id = UQM_SwapLE32 (chunk->Id);
|
||||
chunk->Size = UQM_SwapLE32 (chunk->Size);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool
|
||||
wava_readFormatHeader (TFB_WaveSoundDecoder* wava, WAVFmtHdr_Struct* fmt)
|
||||
wava_readFormatHeader (TFB_WaveSoundDecoder* wava, wave_FormatHeader* fmt)
|
||||
{
|
||||
if (!uio_fread (&fmt->Format, 2, 1, wava->fp) ||
|
||||
!uio_fread (&fmt->Channels, 2, 1, wava->fp) ||
|
||||
!uio_fread (&fmt->SamplesPerSec, 4, 1, wava->fp) ||
|
||||
!uio_fread (&fmt->BytesPerSec, 4, 1, wava->fp) ||
|
||||
!uio_fread (&fmt->BlockAlign, 2, 1, wava->fp) ||
|
||||
!uio_fread (&fmt->BitsPerSample, 2, 1, wava->fp))
|
||||
if (!read_le_16 (wava->fp, &fmt->format) ||
|
||||
!read_le_16 (wava->fp, &fmt->channels) ||
|
||||
!read_le_32 (wava->fp, &fmt->samplesPerSec) ||
|
||||
!read_le_32 (wava->fp, &fmt->bytesPerSec) ||
|
||||
!read_le_16 (wava->fp, &fmt->blockAlign) ||
|
||||
!read_le_16 (wava->fp, &fmt->bitsPerSample))
|
||||
{
|
||||
wava->last_error = errno;
|
||||
return false;
|
||||
|
||||
fmt->Format = UQM_SwapLE16 (fmt->Format);
|
||||
fmt->Channels = UQM_SwapLE16 (fmt->Channels);
|
||||
fmt->SamplesPerSec = UQM_SwapLE32 (fmt->SamplesPerSec);
|
||||
fmt->BytesPerSec = UQM_SwapLE32 (fmt->BytesPerSec);
|
||||
fmt->BlockAlign = UQM_SwapLE16 (fmt->BlockAlign);
|
||||
fmt->BitsPerSample = UQM_SwapLE16 (fmt->BitsPerSample);
|
||||
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -213,8 +224,8 @@ static bool
|
||||
wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
||||
{
|
||||
TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This;
|
||||
WAVFileHdr_Struct FileHdr;
|
||||
WAVChunkHdr_Struct ChunkHdr;
|
||||
wave_FileHeader fileHdr;
|
||||
wave_ChunkHeader chunkHdr;
|
||||
|
||||
wava->fp = uio_fopen (dir, filename, "rb");
|
||||
if (!wava->fp)
|
||||
@@ -227,52 +238,53 @@ wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
||||
wava->data_ofs = 0;
|
||||
|
||||
// read wave header
|
||||
if (!wava_readFileHeader (wava, &FileHdr))
|
||||
if (!wava_readFileHeader (wava, &fileHdr))
|
||||
{
|
||||
wava->last_error = errno;
|
||||
wava_Close (This);
|
||||
return false;
|
||||
}
|
||||
if (FileHdr.Id != RIFF || FileHdr.Type != WAVE)
|
||||
if (fileHdr.id != wave_RiffID || fileHdr.type != wave_WaveID)
|
||||
{
|
||||
log_add (log_Warning, "wava_Open(): "
|
||||
"not a wave file, ID 0x%08x, Type 0x%08x",
|
||||
FileHdr.Id, FileHdr.Type);
|
||||
fileHdr.id, fileHdr.type);
|
||||
wava_Close (This);
|
||||
return false;
|
||||
}
|
||||
|
||||
for (FileHdr.Size = ((FileHdr.Size + 1) & ~1) - 4; FileHdr.Size != 0;
|
||||
FileHdr.Size -= (((ChunkHdr.Size + 1) & ~1) + 8))
|
||||
for (fileHdr.size = ((fileHdr.size + 1) & ~1) - 4; fileHdr.size != 0;
|
||||
fileHdr.size -= (((chunkHdr.size + 1) & ~1) + 8))
|
||||
{
|
||||
if (!wava_readChunkHeader (wava, &ChunkHdr))
|
||||
if (!wava_readChunkHeader (wava, &chunkHdr))
|
||||
{
|
||||
wava->last_error = errno;
|
||||
wava_Close (This);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (ChunkHdr.Id == FMT)
|
||||
if (chunkHdr.id == wave_FmtID)
|
||||
{
|
||||
if (!wava_readFormatHeader (wava, &wava->FmtHdr))
|
||||
if (!wava_readFormatHeader (wava, &wava->fmtHdr))
|
||||
{
|
||||
wava->last_error = errno;
|
||||
wava_Close (This);
|
||||
return false;
|
||||
}
|
||||
uio_fseek (wava->fp, ChunkHdr.Size - 16, SEEK_CUR);
|
||||
uio_fseek (wava->fp, chunkHdr.size - 16, SEEK_CUR);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ChunkHdr.Id == DATA)
|
||||
if (chunkHdr.id == wave_DataID)
|
||||
{
|
||||
wava->data_size = ChunkHdr.Size;
|
||||
wava->data_size = chunkHdr.size;
|
||||
wava->data_ofs = uio_ftell (wava->fp);
|
||||
}
|
||||
uio_fseek (wava->fp, ChunkHdr.Size, SEEK_CUR);
|
||||
uio_fseek (wava->fp, chunkHdr.size, SEEK_CUR);
|
||||
}
|
||||
|
||||
uio_fseek (wava->fp, ChunkHdr.Size & 1, SEEK_CUR);
|
||||
// 2-align the file ptr
|
||||
// XXX: I do not think this is necessary in WAVE files;
|
||||
// possibly a remnant of ported AIFF reader
|
||||
uio_fseek (wava->fp, chunkHdr.size & 1, SEEK_CUR);
|
||||
}
|
||||
|
||||
if (!wava->data_size || !wava->data_ofs)
|
||||
@@ -283,29 +295,34 @@ wava_Open (THIS_PTR, uio_DirHandle *dir, const char *filename)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (wava->FmtHdr.Format == 0x0001)
|
||||
{
|
||||
This->format = (wava->FmtHdr.Channels == 1 ?
|
||||
(wava->FmtHdr.BitsPerSample == 8 ?
|
||||
wava_formats->mono8 : wava_formats->mono16)
|
||||
:
|
||||
(wava->FmtHdr.BitsPerSample == 8 ?
|
||||
wava_formats->stereo8 : wava_formats->stereo16)
|
||||
);
|
||||
This->frequency = wava->FmtHdr.SamplesPerSec;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (wava->fmtHdr.format != 0x0001)
|
||||
{ // not a PCM format
|
||||
log_add (log_Warning, "wava_Open(): unsupported format %x",
|
||||
wava->FmtHdr.Format);
|
||||
wava->fmtHdr.format);
|
||||
wava_Close (This);
|
||||
return false;
|
||||
}
|
||||
if (wava->fmtHdr.channels != 1 && wava->fmtHdr.channels != 2)
|
||||
{
|
||||
log_add (log_Warning, "wava_Open(): unsupported number of channels %u",
|
||||
(unsigned)wava->fmtHdr.channels);
|
||||
wava_Close (This);
|
||||
return false;
|
||||
}
|
||||
|
||||
This->format = (wava->fmtHdr.channels == 1 ?
|
||||
(wava->fmtHdr.bitsPerSample == 8 ?
|
||||
wava_formats->mono8 : wava_formats->mono16)
|
||||
:
|
||||
(wava->fmtHdr.bitsPerSample == 8 ?
|
||||
wava_formats->stereo8 : wava_formats->stereo16)
|
||||
);
|
||||
This->frequency = wava->fmtHdr.samplesPerSec;
|
||||
|
||||
uio_fseek (wava->fp, wava->data_ofs, SEEK_SET);
|
||||
wava->max_pcm = wava->data_size / wava->FmtHdr.BlockAlign;
|
||||
wava->max_pcm = wava->data_size / wava->fmtHdr.blockAlign;
|
||||
wava->cur_pcm = 0;
|
||||
This->length = (float) wava->max_pcm / wava->FmtHdr.SamplesPerSec;
|
||||
This->length = (float) wava->max_pcm / wava->fmtHdr.samplesPerSec;
|
||||
wava->last_error = 0;
|
||||
|
||||
return true;
|
||||
@@ -329,14 +346,14 @@ wava_Decode (THIS_PTR, void* buf, sint32 bufsize)
|
||||
TFB_WaveSoundDecoder* wava = (TFB_WaveSoundDecoder*) This;
|
||||
uint32 dec_pcm;
|
||||
|
||||
dec_pcm = bufsize / wava->FmtHdr.BlockAlign;
|
||||
dec_pcm = bufsize / wava->fmtHdr.blockAlign;
|
||||
if (dec_pcm > wava->max_pcm - wava->cur_pcm)
|
||||
dec_pcm = wava->max_pcm - wava->cur_pcm;
|
||||
|
||||
dec_pcm = uio_fread (buf, wava->FmtHdr.BlockAlign, dec_pcm, wava->fp);
|
||||
dec_pcm = uio_fread (buf, wava->fmtHdr.blockAlign, dec_pcm, wava->fp);
|
||||
wava->cur_pcm += dec_pcm;
|
||||
|
||||
return dec_pcm * wava->FmtHdr.BlockAlign;
|
||||
return dec_pcm * wava->fmtHdr.blockAlign;
|
||||
}
|
||||
|
||||
static uint32
|
||||
@@ -348,7 +365,7 @@ wava_Seek (THIS_PTR, uint32 pcm_pos)
|
||||
pcm_pos = wava->max_pcm;
|
||||
wava->cur_pcm = pcm_pos;
|
||||
uio_fseek (wava->fp,
|
||||
wava->data_ofs + pcm_pos * wava->FmtHdr.BlockAlign,
|
||||
wava->data_ofs + pcm_pos * wava->fmtHdr.blockAlign,
|
||||
SEEK_SET);
|
||||
|
||||
return pcm_pos;
|
||||
|
||||
Reference in New Issue
Block a user