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:
Max Horn 2003-08-02 02:41:31 +00:00
parent a932a74dcb
commit 1f58fea232
3 changed files with 74 additions and 54 deletions

View File

@ -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) {

View File

@ -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;

View File

@ -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