mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-22 18:37:01 +00:00
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
This commit is contained in:
parent
a932a74dcb
commit
1f58fea232
@ -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) {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user