aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2003-08-02 02:41:31 +0000
committerMax Horn2003-08-02 02:41:31 +0000
commit1f58fea23290eede7b3ae54e1b1eab4b3eb72b6f (patch)
tree3cb5a224087ee07c83cc1b78253a1aee41a5453b /sound
parenta932a74dcb8185bc0ddb8edbe98d6c64eb1a8f97 (diff)
downloadscummvm-rg350-1f58fea23290eede7b3ae54e1b1eab4b3eb72b6f.tar.gz
scummvm-rg350-1f58fea23290eede7b3ae54e1b1eab4b3eb72b6f.tar.bz2
scummvm-rg350-1f58fea23290eede7b3ae54e1b1eab4b3eb72b6f.zip
converted ChannelMP3 to use new rate conversion scheme, too. Only thing missing now is FLAG_REVERSE_STEREO support (and of course fixing regressions, and the long term goal is to make resample.cpp usable, too)
svn-id: r9395
Diffstat (limited to 'sound')
-rw-r--r--sound/audiostream.cpp38
-rw-r--r--sound/audiostream.h5
-rw-r--r--sound/mixer.cpp85
3 files changed, 74 insertions, 54 deletions
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp
index 8428de2d78..64dceb1cd6 100644
--- a/sound/audiostream.cpp
+++ b/sound/audiostream.cpp
@@ -161,15 +161,16 @@ void WrappedMemoryStream<stereo, is16Bit, isUnsigned>::append(const byte *data,
#ifdef USE_MAD
-#define MP3_BUFFER_SIZE 131072
-
/**
* Playback the MP3 data in the given file for the specified duration.
*
* @param file file containing the MP3 data
- * @param duration playback duration in frames (1/75th of a second), 0 means playback until EOF
+ * @param duration playback duration in frames (1/75th of a second), 0 means
+ * playback until EOF
+ * @param size optional, if non-zero this limits playback based on the
+ * number of input bytes rather then a duration
*/
-MP3InputStream::MP3InputStream(File *file, mad_timer_t duration) {
+MP3InputStream::MP3InputStream(File *file, mad_timer_t duration, uint size) {
// duration == 0 means: play everything till end of file
_isStereo = false;
@@ -177,6 +178,7 @@ MP3InputStream::MP3InputStream(File *file, mad_timer_t duration) {
_file = file;
_rate = 0;
_posInFrame = 0;
+ _bufferSize = size ? size : (128 * 1024); // Default buffer size is 128K
_duration = duration;
@@ -184,9 +186,15 @@ MP3InputStream::MP3InputStream(File *file, mad_timer_t duration) {
mad_frame_init(&_frame);
mad_synth_init(&_synth);
- _ptr = (byte *)malloc(MP3_BUFFER_SIZE + MAD_BUFFER_GUARD);
-
+ _ptr = (byte *)malloc(_bufferSize + MAD_BUFFER_GUARD);
+
_initialized = init();
+
+ // If a size is specified, we do not perform any further read operations
+ if (size) {
+ _file = 0;
+ }
+
}
MP3InputStream::~MP3InputStream() {
@@ -201,7 +209,7 @@ bool MP3InputStream::init() {
// TODO
// Read in the first chunk of the MP3 file
- _size = _file->read(_ptr, MP3_BUFFER_SIZE);
+ _size = _file->read(_ptr, _bufferSize);
if (_size <= 0) {
warning("MP3InputStream: Failed to read MP3 data");
return false;
@@ -244,19 +252,22 @@ void MP3InputStream::refill() {
if (_stream.error == MAD_ERROR_BUFLEN) {
int offset;
+ if (!_file)
+ _size = -1;
+
// Give up immediately if we are at the EOF already
if (_size <= 0)
return;
if (!_stream.next_frame) {
offset = 0;
- memset(_ptr, 0, MP3_BUFFER_SIZE + MAD_BUFFER_GUARD);
+ memset(_ptr, 0, _bufferSize + MAD_BUFFER_GUARD);
} else {
offset = _stream.bufend - _stream.next_frame;
memcpy(_ptr, _stream.next_frame, offset);
}
// Read in more data from the input file
- _size = _file->read(_ptr + offset, MP3_BUFFER_SIZE - offset);
+ _size = _file->read(_ptr + offset, _bufferSize - offset);
// Nothing read -> EOF -> bail out
if (_size <= 0) {
@@ -286,8 +297,10 @@ void MP3InputStream::refill() {
}
bool MP3InputStream::eof() const {
- // Time over -> input steam ends
- if (mad_timer_compare(_duration, mad_timer_zero) <= 0)
+ // Time over -> input steam ends. Unless _file is 0, which
+ // means that playback is based on the number of input bytes
+ // rather than a duration.
+ if (_file && mad_timer_compare(_duration, mad_timer_zero) <= 0)
return true;
return (_posInFrame >= _synth.pcm.length);
}
@@ -307,8 +320,9 @@ static inline int scale_sample(mad_fixed_t sample) {
}
int16 MP3InputStream::read() {
- if (_size < 0 || _posInFrame >= _synth.pcm.length) // EOF
+ if (_size < 0 || _posInFrame >= _synth.pcm.length) { // EOF
return 0;
+ }
int16 sample;
if (_isStereo) {
diff --git a/sound/audiostream.h b/sound/audiostream.h
index 722006e625..110dee789d 100644
--- a/sound/audiostream.h
+++ b/sound/audiostream.h
@@ -51,6 +51,8 @@ public:
//virtual int size() const = 0;
virtual bool isStereo() const = 0;
virtual bool eof() const = 0;
+
+ virtual int getRate() const { return -1; }
};
class WrappedAudioInputStream : public AudioInputStream {
@@ -75,6 +77,7 @@ class MP3InputStream : public AudioInputStream {
struct mad_frame _frame;
struct mad_synth _synth;
uint32 _posInFrame;
+ uint32 _bufferSize;
int _size;
bool _isStereo;
int _curChannel;
@@ -87,7 +90,7 @@ class MP3InputStream : public AudioInputStream {
bool init();
void refill();
public:
- MP3InputStream(File *file, mad_timer_t duration);
+ MP3InputStream(File *file, mad_timer_t duration, uint size = 0);
~MP3InputStream();
int16 read();
bool eof() const;
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index 18111ad971..1a978c3316 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -37,6 +37,10 @@ class Channel {
protected:
SoundMixer *_mixer;
PlayingSoundHandle *_handle;
+#ifdef SOX_HACK
+ RateConverter *_converter;
+ AudioInputStream *_input;
+#endif
public:
int _id;
Channel(SoundMixer *mixer, PlayingSoundHandle *handle)
@@ -44,6 +48,8 @@ public:
assert(mixer);
}
virtual ~Channel() {
+ delete _converter;
+ delete _input;
if (_handle)
*_handle = 0;
}
@@ -65,10 +71,7 @@ public:
class ChannelRaw : public Channel {
byte *_ptr;
byte _flags;
-#ifdef SOX_HACK
- RateConverter *_converter;
- AudioInputStream *_input;
-#else
+#ifndef SOX_HACK
uint32 _pos;
uint32 _size;
uint32 _fpSpeed;
@@ -89,10 +92,7 @@ public:
};
class ChannelStream : public Channel {
-#ifdef SOX_HACK
- RateConverter *_converter;
- WrappedAudioInputStream *_input;
-#else
+#ifndef SOX_HACK
byte *_ptr;
byte *_endOfData;
byte *_endOfBuffer;
@@ -134,8 +134,12 @@ public:
~ChannelMP3Common();
};
+#ifdef SOX_HACK
+class ChannelMP3 : public Channel {
+#else
class ChannelMP3 : public ChannelMP3Common {
uint32 _position;
+#endif
public:
ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, uint size);
@@ -146,8 +150,6 @@ public:
#ifdef SOX_HACK
class ChannelMP3CDMusic : public Channel {
- RateConverter *_converter;
- MP3InputStream *_input;
#else
class ChannelMP3CDMusic : public ChannelMP3Common {
uint32 _bufferSize;
@@ -157,7 +159,6 @@ class ChannelMP3CDMusic : public ChannelMP3Common {
public:
ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, mad_timer_t duration);
- ~ChannelMP3CDMusic();
void mix(int16 *data, uint len);
bool isMusicChannel() { return true; }
@@ -167,10 +168,7 @@ public:
#ifdef USE_VORBIS
class ChannelVorbis : public Channel {
-#ifdef SOX_HACK
- RateConverter *_converter;
- AudioInputStream *_input;
-#else
+#ifndef SOX_HACK
OggVorbis_File *_ov_file;
int _end_pos;
#endif
@@ -178,7 +176,6 @@ class ChannelVorbis : public Channel {
public:
ChannelVorbis(SoundMixer *mixer, PlayingSoundHandle *handle, OggVorbis_File *ov_file, int duration, bool is_cd_track);
- ~ChannelVorbis();
void mix(int16 *data, uint len);
bool isMusicChannel() {
@@ -702,10 +699,6 @@ ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *soun
}
ChannelRaw::~ChannelRaw() {
-#ifdef SOX_HACK
- delete _converter;
- delete _input;
-#endif
if (_flags & SoundMixer::FLAG_AUTOFREE)
free(_ptr);
}
@@ -762,7 +755,7 @@ ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void
// Create the input stream
_input = makeWrappedInputStream(flags, buffer_size);
- _input->append((const byte *)sound, size);
+ ((WrappedAudioInputStream *)_input)->append((const byte *)sound, size);
// TODO: add support for SoundMixer::FLAG_REVERSE_STEREO
// Get a rate converter instance
@@ -791,17 +784,14 @@ ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void
}
ChannelStream::~ChannelStream() {
-#ifdef SOX_HACK
- delete _converter;
- delete _input;
-#else
+#ifndef SOX_HACK
free(_ptr);
#endif
}
void ChannelStream::append(void *data, uint32 len) {
#ifdef SOX_HACK
- _input->append((const byte *)data, len);
+ ((WrappedAudioInputStream *)_input)->append((const byte *)data, len);
#else
if (_endOfData + len > _endOfBuffer) {
/* Wrap-around case */
@@ -936,6 +926,17 @@ static inline int scale_sample(mad_fixed_t sample) {
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
+#ifdef SOX_HACK
+ChannelMP3::ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, uint size)
+ : Channel(mixer, handle) {
+ // Create the input stream
+ _input = new MP3InputStream(file, mad_timer_zero, size);
+
+ // Get a rate converter instance
+//printf("ChannelMP3: inrate %d, outrate %d, stereo %d\n", _input->getRate(), mixer->getOutputRate(), _input->isStereo());
+ _converter = makeRateConverter(_input->getRate(), mixer->getOutputRate(), _input->isStereo());
+}
+#else
ChannelMP3::ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, uint size)
: ChannelMP3Common(mixer, handle) {
_posInFrame = 0xFFFFFFFF;
@@ -944,8 +945,23 @@ ChannelMP3::ChannelMP3(SoundMixer *mixer, PlayingSoundHandle *handle, File *file
_size = file->read(_ptr, size);
}
+#endif
void ChannelMP3::mix(int16 *data, uint len) {
+#ifdef SOX_HACK
+ assert(_input);
+ assert(_converter);
+
+ if (_input->eof()) {
+ // TODO: call drain method
+ destroy();
+ return;
+ }
+
+ const int volume = _mixer->getVolume();
+ st_size_t tmpLen = len;
+ _converter->flow(*_input, data, &tmpLen, volume);
+#else
const int volume = _mixer->getVolume();
// Exit if all data is used up (this also covers the case were reading from the file failed).
@@ -990,6 +1006,7 @@ void ChannelMP3::mix(int16 *data, uint len) {
_posInFrame = 0;
_position = _stream.next_frame - _ptr;
}
+#endif
}
#define MP3CD_BUFFERING_SIZE 131072
@@ -998,7 +1015,7 @@ void ChannelMP3::mix(int16 *data, uint len) {
ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *handle, File *file, mad_timer_t duration)
: Channel(mixer, handle) {
// Create the input stream
- _input = new MP3InputStream(file, duration);
+ _input = new MP3InputStream(file, duration, 0);
// Get a rate converter instance
//printf("ChannelMP3CDMusic: inrate %d, outrate %d, stereo %d\n", _input->getRate(), mixer->getOutputRate(), _input->isStereo());
@@ -1014,13 +1031,6 @@ ChannelMP3CDMusic::ChannelMP3CDMusic(SoundMixer *mixer, PlayingSoundHandle *hand
}
#endif
-ChannelMP3CDMusic::~ChannelMP3CDMusic() {
-#ifdef SOX_HACK
- delete _converter;
- delete _input;
-#endif
-}
-
void ChannelMP3CDMusic::mix(int16 *data, uint len) {
#ifdef SOX_HACK
assert(_input);
@@ -1171,13 +1181,6 @@ ChannelVorbis::ChannelVorbis(SoundMixer *mixer, PlayingSoundHandle *handle, OggV
_is_cd_track = is_cd_track;
}
-ChannelVorbis::~ChannelVorbis() {
-#ifdef SOX_HACK
- delete _converter;
- delete _input;
-#endif
-}
-
#ifdef CHUNKSIZE
#define VORBIS_TREMOR
#endif