use RageFile
This commit is contained in:
@@ -23,13 +23,11 @@
|
|||||||
* This file written by Ryan C. Gordon. ([email protected])
|
* This file written by Ryan C. Gordon. ([email protected])
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <global.h>
|
#include "global.h"
|
||||||
#include "RageSoundReader_WAV.h"
|
#include "RageSoundReader_WAV.h"
|
||||||
#include "RageLog.h"
|
#include "RageLog.h"
|
||||||
#include "RageUtil.h"
|
#include "RageUtil.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <SDL_endian.h>
|
#include <SDL_endian.h>
|
||||||
|
|
||||||
#define BAIL_IF_MACRO(c, e, r) if (c) { SetError(e); return r; }
|
#define BAIL_IF_MACRO(c, e, r) if (c) { SetError(e); return r; }
|
||||||
@@ -64,24 +62,24 @@ Uint32 RageSoundReader_WAV::ConvertBytePosToMs(int BytesPerSample, int channels,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Better than SDL_ReadLE16, since you can detect i/o errors... */
|
/* Better than SDL_ReadLE16, since you can detect i/o errors... */
|
||||||
bool RageSoundReader_WAV::read_le16(FILE *rw, Sint16 *si16) const
|
bool RageSoundReader_WAV::read_le16( RageFile &f, Sint16 *si16 ) const
|
||||||
{
|
{
|
||||||
int rc = fread( si16, sizeof (Sint16), 1, rw );
|
const int ret = f.Read( si16, sizeof(Sint16) );
|
||||||
if( rc != 1 )
|
if( ret != sizeof(Sint16) )
|
||||||
{
|
{
|
||||||
SetError( feof(rw)? "end of file": strerror(errno) );
|
SetError( ret >= 0? "end of file": f.GetError().c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*si16 = SDL_SwapLE16( *si16 );
|
*si16 = SDL_SwapLE16( *si16 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RageSoundReader_WAV::read_le16(FILE *rw, Uint16 *ui16) const
|
bool RageSoundReader_WAV::read_le16( RageFile &f, Uint16 *ui16 ) const
|
||||||
{
|
{
|
||||||
int rc = fread( ui16, sizeof (Uint16), 1, rw );
|
const int ret = f.Read( ui16, sizeof(Uint16) );
|
||||||
if( rc != 1 )
|
if( ret != sizeof(Uint16) )
|
||||||
{
|
{
|
||||||
SetError( feof(rw)? "end of file": strerror(errno) );
|
SetError( ret >= 0? "end of file": f.GetError().c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*ui16 = SDL_SwapLE16(*ui16);
|
*ui16 = SDL_SwapLE16(*ui16);
|
||||||
@@ -90,36 +88,36 @@ bool RageSoundReader_WAV::read_le16(FILE *rw, Uint16 *ui16) const
|
|||||||
|
|
||||||
|
|
||||||
/* Better than SDL_ReadLE32, since you can detect i/o errors... */
|
/* Better than SDL_ReadLE32, since you can detect i/o errors... */
|
||||||
bool RageSoundReader_WAV::read_le32(FILE *rw, Sint32 *si32) const
|
bool RageSoundReader_WAV::read_le32( RageFile &f, Sint32 *si32 ) const
|
||||||
{
|
{
|
||||||
int rc = fread( si32, sizeof (Sint32), 1, rw );
|
const int ret = f.Read( si32, sizeof(Sint32) );
|
||||||
if( rc != 1 )
|
if( ret != sizeof(Sint32) )
|
||||||
{
|
{
|
||||||
SetError( feof(rw)? "end of file": strerror(errno) );
|
SetError( ret >= 0? "end of file": f.GetError().c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*si32 = SDL_SwapLE32( *si32 );
|
*si32 = SDL_SwapLE32( *si32 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RageSoundReader_WAV::read_le32(FILE *rw, Uint32 *ui32) const
|
bool RageSoundReader_WAV::read_le32( RageFile &f, Uint32 *ui32 ) const
|
||||||
{
|
{
|
||||||
int rc = fread( ui32, sizeof (Uint32), 1, rw );
|
const int ret = f.Read( ui32, sizeof(Uint32) );
|
||||||
if( rc != 1 )
|
if( ret != sizeof(Uint32) )
|
||||||
{
|
{
|
||||||
SetError( feof(rw)? "end of file": strerror(errno) );
|
SetError( ret >= 0? "end of file": f.GetError().c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*ui32 = SDL_SwapLE32( *ui32 );
|
*ui32 = SDL_SwapLE32( *ui32 );
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RageSoundReader_WAV::read_uint8(FILE *rw, Uint8 *ui8) const
|
bool RageSoundReader_WAV::read_uint8( RageFile &f, Uint8 *ui8 ) const
|
||||||
{
|
{
|
||||||
int rc = fread( ui8, sizeof (Uint8), 1, rw );
|
const int ret = f.Read( ui8, sizeof(Uint8) );
|
||||||
if( rc != 1 )
|
if( ret != sizeof(Uint8) )
|
||||||
{
|
{
|
||||||
SetError( feof(rw)? "end of file": strerror(errno) );
|
SetError( ret >= 0? "end of file": f.GetError().c_str() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@@ -169,10 +167,10 @@ bool RageSoundReader_WAV::read_fmt_chunk()
|
|||||||
|
|
||||||
int RageSoundReader_WAV::read_sample_fmt_normal(char *buf, unsigned len)
|
int RageSoundReader_WAV::read_sample_fmt_normal(char *buf, unsigned len)
|
||||||
{
|
{
|
||||||
int ret = fread( buf, 1, len, this->rw );
|
const int ret = this->rw.Read( buf, len );
|
||||||
if (ret == -1)
|
if( ret == -1 )
|
||||||
{
|
{
|
||||||
SetError( strerror(errno) );
|
SetError( ret >= 0? "end of file": rw.GetError().c_str() );
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -185,11 +183,11 @@ int RageSoundReader_WAV::seek_sample_fmt_normal( Uint32 ms )
|
|||||||
const int offset = ConvertMsToBytePos( BytesPerSample, Channels, ms);
|
const int offset = ConvertMsToBytePos( BytesPerSample, Channels, ms);
|
||||||
const int pos = (int) (this->fmt.data_starting_offset + offset);
|
const int pos = (int) (this->fmt.data_starting_offset + offset);
|
||||||
|
|
||||||
int rc = fseek( this->rw, pos, SEEK_SET );
|
const int ret = this->rw.Seek( pos );
|
||||||
BAIL_IF_MACRO(rc == -1, strerror(errno), -1);
|
BAIL_IF_MACRO( ret == -1, this->rw.GetError(), -1 );
|
||||||
|
|
||||||
/* If we seek past end of ifle, leave the cursor there, so subsequent reads will return EOF. */
|
/* If we seek past end of ifle, leave the cursor there, so subsequent reads will return EOF. */
|
||||||
if( pos >= (int) GetFileSizeInBytes( filename ) )
|
if( pos >= this->rw.GetFileSize() )
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
return ms;
|
return ms;
|
||||||
@@ -197,10 +195,9 @@ int RageSoundReader_WAV::seek_sample_fmt_normal( Uint32 ms )
|
|||||||
|
|
||||||
int RageSoundReader_WAV::get_length_fmt_adpcm() const
|
int RageSoundReader_WAV::get_length_fmt_adpcm() const
|
||||||
{
|
{
|
||||||
int ret = fseek(this->rw, 0, SEEK_END);
|
this->rw.Rewind();
|
||||||
BAIL_IF_MACRO( ret == -1, strerror(errno), -1 );
|
|
||||||
|
|
||||||
int offset = ftell( this->rw );
|
int offset = this->rw.Tell();
|
||||||
offset -= fmt.data_starting_offset;
|
offset -= fmt.data_starting_offset;
|
||||||
|
|
||||||
/* pcm bytes per block */
|
/* pcm bytes per block */
|
||||||
@@ -209,7 +206,7 @@ int RageSoundReader_WAV::get_length_fmt_adpcm() const
|
|||||||
const int byteno = blockno * bpb;
|
const int byteno = blockno * bpb;
|
||||||
|
|
||||||
/* Seek back to the beginning of the last frame and find out how long it really is. */
|
/* Seek back to the beginning of the last frame and find out how long it really is. */
|
||||||
fseek( this->rw, blockno * fmt.wBlockAlign + fmt.data_starting_offset, SEEK_SET );
|
this->rw.Seek( blockno * fmt.wBlockAlign + fmt.data_starting_offset );
|
||||||
|
|
||||||
/* Don't mess up this->adpcm; we'll put the cursor back as if nothing happened. */
|
/* Don't mess up this->adpcm; we'll put the cursor back as if nothing happened. */
|
||||||
adpcm_t tmp_adpcm(adpcm);
|
adpcm_t tmp_adpcm(adpcm);
|
||||||
@@ -223,10 +220,7 @@ int RageSoundReader_WAV::get_length_fmt_adpcm() const
|
|||||||
|
|
||||||
int RageSoundReader_WAV::get_length_fmt_normal() const
|
int RageSoundReader_WAV::get_length_fmt_normal() const
|
||||||
{
|
{
|
||||||
int ret = fseek( this->rw, 0, SEEK_END );
|
const int offset = this->rw.GetFileSize();
|
||||||
BAIL_IF_MACRO( ret == -1, strerror(errno), -1 );
|
|
||||||
int offset = ftell( this->rw );
|
|
||||||
|
|
||||||
return ConvertBytePosToMs( BytesPerSample, Channels, offset - this->fmt.data_starting_offset);
|
return ConvertBytePosToMs( BytesPerSample, Channels, offset - this->fmt.data_starting_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -364,8 +358,8 @@ int RageSoundReader_WAV::seek_sample_fmt_adpcm( Uint32 ms )
|
|||||||
const int skipsize = (offset / bpb) * this->fmt.wBlockAlign;
|
const int skipsize = (offset / bpb) * this->fmt.wBlockAlign;
|
||||||
|
|
||||||
const int pos = skipsize + this->fmt.data_starting_offset;
|
const int pos = skipsize + this->fmt.data_starting_offset;
|
||||||
int rc = fseek(this->rw, pos, SEEK_SET);
|
int rc = this->rw.Seek( pos );
|
||||||
BAIL_IF_MACRO(rc == -1, strerror(errno), -1);
|
BAIL_IF_MACRO(rc == -1, this->rw.GetError(), -1);
|
||||||
|
|
||||||
/* The offset we need is in this block, so we need to decode to there. */
|
/* The offset we need is in this block, so we need to decode to there. */
|
||||||
rc = offset % bpb; /* bytes into this block we need to decode */
|
rc = offset % bpb; /* bytes into this block we need to decode */
|
||||||
@@ -402,7 +396,7 @@ int RageSoundReader_WAV::seek_sample_fmt_adpcm( Uint32 ms )
|
|||||||
/* Locate a chunk by ID. */
|
/* Locate a chunk by ID. */
|
||||||
int RageSoundReader_WAV::find_chunk( Uint32 id, Sint32 &size )
|
int RageSoundReader_WAV::find_chunk( Uint32 id, Sint32 &size )
|
||||||
{
|
{
|
||||||
Uint32 pos = ftell(rw);
|
Uint32 pos = this->rw.Tell();
|
||||||
while (1)
|
while (1)
|
||||||
{
|
{
|
||||||
Uint32 id_ = 0;
|
Uint32 id_ = 0;
|
||||||
@@ -418,10 +412,10 @@ int RageSoundReader_WAV::find_chunk( Uint32 id, Sint32 &size )
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
pos += (sizeof (Uint32) * 2) + size;
|
pos += (sizeof (Uint32) * 2) + size;
|
||||||
int ret = fseek(rw, pos, SEEK_SET);
|
int ret = this->rw.Seek( pos );
|
||||||
if( ret == -1 )
|
if( ret == -1 )
|
||||||
{
|
{
|
||||||
SetError( strerror(errno) );
|
SetError( this->rw.GetError() );
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -449,7 +443,7 @@ SoundReader_FileReader::OpenResult RageSoundReader_WAV::WAV_open_internal()
|
|||||||
|
|
||||||
Sint32 NextChunk;
|
Sint32 NextChunk;
|
||||||
BAIL_IF_MACRO(!find_chunk(fmtID, NextChunk), "No format chunk.", OPEN_MATCH_BUT_FAIL);
|
BAIL_IF_MACRO(!find_chunk(fmtID, NextChunk), "No format chunk.", OPEN_MATCH_BUT_FAIL);
|
||||||
NextChunk += ftell(rw);
|
NextChunk += this->rw.Tell();
|
||||||
BAIL_IF_MACRO(!read_fmt_chunk(), "Can't read format chunk.", OPEN_MATCH_BUT_FAIL);
|
BAIL_IF_MACRO(!read_fmt_chunk(), "Can't read format chunk.", OPEN_MATCH_BUT_FAIL);
|
||||||
|
|
||||||
/* I think multi-channel WAVs are possible, but I've never even seen one. */
|
/* I think multi-channel WAVs are possible, but I've never even seen one. */
|
||||||
@@ -493,12 +487,12 @@ SoundReader_FileReader::OpenResult RageSoundReader_WAV::WAV_open_internal()
|
|||||||
if( Channels == 1 )
|
if( Channels == 1 )
|
||||||
Input_Buffer_Ratio *= 2;
|
Input_Buffer_Ratio *= 2;
|
||||||
|
|
||||||
fseek(rw, NextChunk, SEEK_SET );
|
this->rw.Seek( NextChunk );
|
||||||
|
|
||||||
Sint32 DataSize;
|
Sint32 DataSize;
|
||||||
BAIL_IF_MACRO(!find_chunk(dataID, DataSize), "No data chunk.", OPEN_MATCH_BUT_FAIL);
|
BAIL_IF_MACRO(!find_chunk(dataID, DataSize), "No data chunk.", OPEN_MATCH_BUT_FAIL);
|
||||||
|
|
||||||
fmt.data_starting_offset = ftell(rw);
|
fmt.data_starting_offset = this->rw.Tell();
|
||||||
fmt.adpcm_sample_frame_size = BytesPerSample * Channels;
|
fmt.adpcm_sample_frame_size = BytesPerSample * Channels;
|
||||||
|
|
||||||
return OPEN_OK;
|
return OPEN_OK;
|
||||||
@@ -510,10 +504,9 @@ SoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( CString filename_
|
|||||||
Close();
|
Close();
|
||||||
Input_Buffer_Ratio = 1;
|
Input_Buffer_Ratio = 1;
|
||||||
filename = filename_;
|
filename = filename_;
|
||||||
rw = fopen(filename, "rb");
|
if( !this->rw.Open( filename ) )
|
||||||
if( !rw )
|
|
||||||
{
|
{
|
||||||
SetError( ssprintf("Couldn't open file: %s", strerror(errno)) );
|
SetError( ssprintf("Couldn't open file: %s", this->rw.GetError().c_str()) );
|
||||||
return OPEN_NO_MATCH;
|
return OPEN_NO_MATCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -529,9 +522,7 @@ SoundReader_FileReader::OpenResult RageSoundReader_WAV::Open( CString filename_
|
|||||||
|
|
||||||
void RageSoundReader_WAV::Close()
|
void RageSoundReader_WAV::Close()
|
||||||
{
|
{
|
||||||
if( rw )
|
this->rw.Close();
|
||||||
fclose( rw );
|
|
||||||
rw = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -612,7 +603,7 @@ int RageSoundReader_WAV::SetPosition(int ms)
|
|||||||
|
|
||||||
int RageSoundReader_WAV::GetLength() const
|
int RageSoundReader_WAV::GetLength() const
|
||||||
{
|
{
|
||||||
const int origpos = ftell( this->rw );
|
const int origpos = this->rw.Tell();
|
||||||
|
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
switch (this->fmt.wFormatTag)
|
switch (this->fmt.wFormatTag)
|
||||||
@@ -625,15 +616,14 @@ int RageSoundReader_WAV::GetLength() const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
int rc = fseek( this->rw, origpos, SEEK_SET );
|
int rc = this->rw.Seek( origpos );
|
||||||
BAIL_IF_MACRO( rc == -1, strerror(errno), -1 );
|
BAIL_IF_MACRO( rc == -1, this->rw.GetError(), -1 );
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
RageSoundReader_WAV::RageSoundReader_WAV()
|
RageSoundReader_WAV::RageSoundReader_WAV()
|
||||||
{
|
{
|
||||||
rw = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundReader *RageSoundReader_WAV::Copy() const
|
SoundReader *RageSoundReader_WAV::Copy() const
|
||||||
|
|||||||
@@ -3,10 +3,11 @@
|
|||||||
|
|
||||||
#include "RageSoundReader_FileReader.h"
|
#include "RageSoundReader_FileReader.h"
|
||||||
#include "SDL_utils.h"
|
#include "SDL_utils.h"
|
||||||
|
#include "RageFile.h"
|
||||||
|
|
||||||
class RageSoundReader_WAV: public SoundReader_FileReader
|
class RageSoundReader_WAV: public SoundReader_FileReader
|
||||||
{
|
{
|
||||||
FILE *rw;
|
mutable RageFile rw;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
Sint16 wFormatTag;
|
Sint16 wFormatTag;
|
||||||
@@ -52,11 +53,11 @@ class RageSoundReader_WAV: public SoundReader_FileReader
|
|||||||
enum { CONV_NONE, CONV_8BIT_TO_16BIT, CONV_16LSB_TO_16SYS } Conversion;
|
enum { CONV_NONE, CONV_8BIT_TO_16BIT, CONV_16LSB_TO_16SYS } Conversion;
|
||||||
|
|
||||||
int read_sample_fmt_normal( char *buf, unsigned len );
|
int read_sample_fmt_normal( char *buf, unsigned len );
|
||||||
bool read_le16( FILE *rw, Sint16 *si16 ) const;
|
bool read_le16( RageFile &f, Sint16 *si16 ) const;
|
||||||
bool read_le16( FILE *rw, Uint16 *ui16 ) const;
|
bool read_le16( RageFile &f, Uint16 *ui16 ) const;
|
||||||
bool read_le32( FILE *rw, Sint32 *si32 ) const;
|
bool read_le32( RageFile &f, Sint32 *si32 ) const;
|
||||||
bool read_le32( FILE *rw, Uint32 *ui32 ) const;
|
bool read_le32( RageFile &f, Uint32 *ui32 ) const;
|
||||||
bool read_uint8( FILE *rw, Uint8 *ui8 ) const;
|
bool read_uint8( RageFile &f, Uint8 *ui8 ) const;
|
||||||
|
|
||||||
bool read_adpcm_block_headers( adpcm_t &out ) const;
|
bool read_adpcm_block_headers( adpcm_t &out ) const;
|
||||||
bool decode_adpcm_sample_frame();
|
bool decode_adpcm_sample_frame();
|
||||||
|
|||||||
Reference in New Issue
Block a user