diff --git a/stepmania/src/RageSoundReader.h b/stepmania/src/RageSoundReader.h new file mode 100644 index 0000000000..b3a1ad27b0 --- /dev/null +++ b/stepmania/src/RageSoundReader.h @@ -0,0 +1,25 @@ +#ifndef RAGE_SOUND_READER_H +#define RAGE_SOUND_READER_H + +/* A sound reader is a source for a RageSound. It's usually just a convenience + * wrapper around SDL_Sound. */ +class SoundReader { + mutable string error; + +protected: + void SetError(string e) const { error = e; } + +public: + virtual bool Open(CString filename) = 0; + virtual int GetLength() const = 0; /* ms */ + virtual int GetLength_Fast() const { return GetLength(); } /* ms */ + virtual int SetPosition_Accurate(int ms) = 0; + virtual int SetPosition_Fast(int ms) { return SetPosition_Accurate(ms); } + virtual int Read(char *buf, unsigned len) = 0; + virtual ~SoundReader() { } + + bool Error() const { return !error.empty(); } + string GetError() const { return error; } +}; + +#endif diff --git a/stepmania/src/RageSoundReader_SDL_Sound.cpp b/stepmania/src/RageSoundReader_SDL_Sound.cpp new file mode 100644 index 0000000000..874892cd42 --- /dev/null +++ b/stepmania/src/RageSoundReader_SDL_Sound.cpp @@ -0,0 +1,144 @@ +#include "stdafx.h" + +/* + * Known problems: + * I hear a click in one speaker at the beginning of some MP3s. This is probably + * something wrong with my SDL_sound MAD wrapper ... + */ + +#ifdef _DEBUG +#pragma comment(lib, "SDL_sound-1.0.0/lib/sdl_sound_static_d.lib") +#else +#pragma comment(lib, "SDL_sound-1.0.0/lib/sdl_sound_static.lib") +#endif + +#include "RageSoundReader_SDL_Sound.h" + +const int channels = 2; +const int samplesize = 2 * channels; /* 16-bit */ +const int samplerate = 44100; + +/* The amount of data to read from SDL_sound at once. */ +const int read_block_size = 1024; + +bool SoundReader_SDL_Sound::Open(CString filename) +{ + inbuf = NULL; + avail = 0; + + Sound_AudioInfo sound_desired; + sound_desired.channels = channels; + sound_desired.format = AUDIO_S16SYS; + sound_desired.rate = samplerate; + + Sample = Sound_NewSampleFromFile(filename.GetString(), + &sound_desired, read_block_size); + + if(Sample) + return true; + + SetError(Sound_GetError()); + return false; +} + +int SoundReader_SDL_Sound::GetLength() const +{ + int len = Sound_Length(Sample); + if(len == -1 && Sample->flags & SOUND_SAMPLEFLAG_EAGAIN) { + /* This indicates the length check will take a little while; call + * it again to confirm. */ + len = Sound_Length(Sample); + } + + if(len < 0) + { + SetError(Sound_GetError()); + return -1; + } + + return len; +} + +int SoundReader_SDL_Sound::GetLength_Fast() const +{ + int ret = Sound_Length(Sample); + + Sound_Rewind(Sample); + return ret; +} + +int SoundReader_SDL_Sound::SetPosition(int ms, bool accurate) +{ + if(ms == 0) + { + Sound_Rewind(Sample); + return 0; + } + + int ret; + if(accurate) + ret = Sound_AccurateSeek(Sample, ms); + else + ret = Sound_FastSeek(Sample, ms); + + if(Sample->flags & SOUND_SAMPLEFLAG_ERROR) + { + SetError(Sound_GetError()); + return -1; + } + + /* If the seek function returned false but didn't set error, it's a + * recoverable error. We probably seeked past end of file. */ + if(!ret) + { + /* Past EOF. Rewind. */ + Sound_Rewind(Sample); + return 0; + } + + + return ms; +} + +int SoundReader_SDL_Sound::Read(char *buf, unsigned len) +{ + int bytes_read = 0; + while(len) + { + if(!avail) + { + /* Don't read at all if we've already hit EOF (it'll whine). */ + if(Sample->flags & SOUND_SAMPLEFLAG_EOF) + return bytes_read; /* EOF */ + + int cnt = Sound_Decode(Sample); + + if(Sample->flags & SOUND_SAMPLEFLAG_EOF) + return bytes_read; /* EOF */ + + if(Sample->flags & SOUND_SAMPLEFLAG_ERROR) + { + SetError(Sound_GetError()); + return -1; + } + + avail = cnt; + inbuf = (const char *) Sample->buffer; + } + + unsigned size = min(avail, len); + memcpy(buf, inbuf, size); + buf += size; + len -= size; + inbuf += size; + avail -= size; + bytes_read += size; + } + + return bytes_read; +} + +SoundReader_SDL_Sound::~SoundReader_SDL_Sound() +{ + Sound_FreeSample(Sample); +} diff --git a/stepmania/src/RageSoundReader_SDL_Sound.h b/stepmania/src/RageSoundReader_SDL_Sound.h new file mode 100644 index 0000000000..5e0fd5504b --- /dev/null +++ b/stepmania/src/RageSoundReader_SDL_Sound.h @@ -0,0 +1,23 @@ +#ifndef RAGE_SOUND_READER_SDL_SOUND +#define RAGE_SOUND_READER_SDL_SOUND + +#include "RageSoundReader.h" +#include "SDL_sound-1.0.0/SDL_sound.h" + +class SoundReader_SDL_Sound: public SoundReader { + Sound_Sample *Sample; + const char *inbuf; + unsigned avail; + int SetPosition(int ms, bool accurate); + +public: + bool Open(CString filename); + int GetLength() const; + int GetLength_Fast() const; + int SetPosition_Accurate(int ms) { return SetPosition(ms, true); } + int SetPosition_Fast(int ms) { return SetPosition(ms, false); } + int Read(char *buf, unsigned len); + ~SoundReader_SDL_Sound(); +}; + +#endif