aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2003-07-28 20:42:54 +0000
committerMax Horn2003-07-28 20:42:54 +0000
commit57a413f0288c8f9cedd2ac0bbb4b9ebdc937a0de (patch)
tree359397a14b01d10a478aaeb376677d7e267ca4aa /sound
parented6521f332db8557ba701add71f493fc3186fdb2 (diff)
downloadscummvm-rg350-57a413f0288c8f9cedd2ac0bbb4b9ebdc937a0de.tar.gz
scummvm-rg350-57a413f0288c8f9cedd2ac0bbb4b9ebdc937a0de.tar.bz2
scummvm-rg350-57a413f0288c8f9cedd2ac0bbb4b9ebdc937a0de.zip
experimental new rate conversion code (use SOX_HACK to en-/disable it); note that right now only the linear filter works, the high quality resample in resample.cpp is in flux; right now the top priority for me is to get MP3/Vorbis resampling working
svn-id: r9261
Diffstat (limited to 'sound')
-rw-r--r--sound/mixer.cpp122
-rw-r--r--sound/module.mk5
2 files changed, 123 insertions, 4 deletions
diff --git a/sound/mixer.cpp b/sound/mixer.cpp
index 83e48799db..8d8fe35308 100644
--- a/sound/mixer.cpp
+++ b/sound/mixer.cpp
@@ -26,6 +26,12 @@
#include "common/file.h"
#include "common/util.h"
+//#define SOX_HACK
+
+#ifdef SOX_HACK
+#include "rate.h"
+#endif
+
class Channel {
protected:
SoundMixer *_mixer;
@@ -59,6 +65,10 @@ public:
class ChannelRaw : public Channel {
byte *_ptr;
byte _flags;
+#ifdef SOX_HACK
+ RateConverter *_converter;
+ AudioInputStream *_input;
+#else
uint32 _pos;
uint32 _size;
uint32 _fpSpeed;
@@ -66,6 +76,7 @@ class ChannelRaw : public Channel {
uint32 _realSize, _rate;
byte *_loop_ptr;
uint32 _loop_size;
+#endif
public:
ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *sound, uint32 size, uint rate, byte flags, int id);
@@ -78,6 +89,10 @@ public:
};
class ChannelStream : public Channel {
+#ifdef SOX_HACK
+ RateConverter *_converter;
+ WrappedAudioInputStream *_input;
+#else
byte *_ptr;
byte *_endOfData;
byte *_endOfBuffer;
@@ -87,6 +102,7 @@ class ChannelStream : public Channel {
uint32 _bufferSize;
uint32 _rate;
byte _flags;
+#endif
bool _finished;
public:
@@ -421,6 +437,9 @@ void SoundMixer::setMusicVolume(int volume) {
_musicVolume = volume;
}
+#ifdef SOX_HACK
+#define clamped_add_16(a, b) clampedAdd(a, b)
+#else
/*
* Class that performs cubic interpolation on integer data.
* It is expected that the data is equidistant, i.e. all have the same
@@ -633,6 +652,7 @@ static int16 mixer_element_size[] = {
2, 2,
4, 4
};
+#endif
bool Channel::isActive() {
error("isActive should never be called on a non-MP3 mixer ");
@@ -646,6 +666,28 @@ ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *soun
_ptr = (byte *)sound;
_flags = flags;
+printf("ChannelRaw: flags 0x%x, input rate %d, output rate %d, size %d\n", flags, rate, mixer->getOutputRate(), size);
+//hexdump(_ptr, size);
+//puts("\n");
+
+#ifdef SOX_HACK
+
+ // Create the input stream
+ _input = makeLinearInputStream(flags, _ptr, size);
+ // TODO: add support for SoundMixer::FLAG_REVERSE_STEREO
+
+ // If rate conversion is necessary, create a converter
+// printf("inrate %d, outrate %d\n", rate, mixer->getOutputRate());
+ if (rate != mixer->getOutputRate()) {
+ _converter = new LinearRateConverter(rate, mixer->getOutputRate());
+ //_converter = new ResampleRateConverter(rate, mixer->getOutputRate(), 1);
+ } else {
+ if (flags & SoundMixer::FLAG_STEREO)
+ _converter = new CopyRateConverter<true>();
+ else
+ _converter = new CopyRateConverter<false>();
+ }
+#else
_pos = 0;
_fpPos = 0;
_fpSpeed = (1 << 16) * rate / mixer->getOutputRate();
@@ -666,14 +708,32 @@ ChannelRaw::ChannelRaw(SoundMixer *mixer, PlayingSoundHandle *handle, void *soun
_loop_ptr = _ptr;
_loop_size = _size;
}
+#endif
}
ChannelRaw::~ChannelRaw() {
+#ifdef SOX_HACK
+ delete _converter;
+ delete _input;
+#endif
if (_flags & SoundMixer::FLAG_AUTOFREE)
free(_ptr);
}
void ChannelRaw::mix(int16 *data, uint len) {
+#ifdef SOX_HACK
+ const int volume = _mixer->getVolume();
+ uint tmpLen = len;
+ if (_input->eof()) {
+ // TODO: call drain method
+ // TODO: Looping
+ destroy();
+ }
+
+ assert(_converter);
+ _converter->flow(*_input, data, &tmpLen, volume);
+
+#else
byte *s, *end;
if (len > _size)
@@ -697,6 +757,7 @@ void ChannelRaw::mix(int16 *data, uint len) {
destroy();
}
}
+#endif
}
#define WARP_WORKAROUND 50000
@@ -705,6 +766,30 @@ ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void
byte flags, uint32 buffer_size)
: Channel(mixer, handle) {
assert(size <= buffer_size);
+
+printf("ChannelStream: flags 0x%x, input rate %d, output rate %d, size %d\n", flags, rate, mixer->getOutputRate(), size);
+//hexdump(_ptr, size);
+//puts("\n");
+
+#ifdef SOX_HACK
+
+ // Create the input stream
+ _input = makeWrappedInputStream(flags, buffer_size);
+ _input->append((const byte *)sound, size);
+ // TODO: add support for SoundMixer::FLAG_REVERSE_STEREO
+
+ // If rate conversion is necessary, create a converter
+// printf("inrate %d, outrate %d\n", rate, mixer->getOutputRate());
+ if (rate != mixer->getOutputRate()) {
+ _converter = new LinearRateConverter(rate, mixer->getOutputRate());
+ //_converter = new ResampleRateConverter(rate, mixer->getOutputRate(), 1);
+ } else {
+ if (flags & SoundMixer::FLAG_STEREO)
+ _converter = new CopyRateConverter<true>();
+ else
+ _converter = new CopyRateConverter<false>();
+ }
+#else
_flags = flags;
_bufferSize = buffer_size;
_ptr = (byte *)malloc(_bufferSize + WARP_WORKAROUND);
@@ -714,21 +799,29 @@ ChannelStream::ChannelStream(SoundMixer *mixer, PlayingSoundHandle *handle, void
_pos = _ptr;
_fpPos = 0;
_fpSpeed = (1 << 16) * rate / mixer->getOutputRate();
- _finished = false;
// adjust the magnitude to prevent division error
while (size & 0xFFFF0000)
size >>= 1, rate = (rate >> 1) + 1;
_rate = rate;
+#endif
+ _finished = false;
}
ChannelStream::~ChannelStream() {
+#ifdef SOX_HACK
+ delete _converter;
+ delete _input;
+#else
free(_ptr);
+#endif
}
void ChannelStream::append(void *data, uint32 len) {
-
+#ifdef SOX_HACK
+ _input->append((const byte *)data, len);
+#else
if (_endOfData + len > _endOfBuffer) {
/* Wrap-around case */
uint32 size_to_end_of_buffer = _endOfBuffer - _endOfData;
@@ -748,10 +841,32 @@ void ChannelStream::append(void *data, uint32 len) {
memcpy(_endOfData, data, len);
_endOfData += len;
}
+#endif
}
void ChannelStream::mix(int16 *data, uint len) {
+#ifdef SOX_HACK
+ const int volume = _mixer->getVolume();
+ uint tmpLen = len;
+
+ if (_input->eof()) {
+ // TODO: call drain method
+ // Normally, the stream stays around even if all its data is used up.
+ // This is in case more data is streamed into it. To make the stream
+ // go away, one can either stop() it (which takes effect immediately,
+ // ignoring any remaining sound data), or finish() it, which means
+ // it will finish playing before it terminates itself.
+ if (_finished) {
+ destroy();
+ }
+
+ return;
+ }
+
+ assert(_converter);
+ _converter->flow(*_input, data, &tmpLen, volume);
+#else
if (_pos == _endOfData) {
// Normally, the stream stays around even if all its data is used up.
// This is in case more data is streamed into it. To make the stream
@@ -799,6 +914,7 @@ void ChannelStream::mix(int16 *data, uint len) {
mixProc(data, len, _pos, _fpPos, _fpSpeed, _mixer->getVolume(), _endOfData, (_flags & SoundMixer::FLAG_REVERSE_STEREO) ? true : false);
}
}
+#endif
}
#ifdef USE_MAD
@@ -1014,7 +1130,7 @@ void ChannelMP3CDMusic::mix(int16 *data, uint len) {
// Restream
mad_stream_buffer(&_stream, _ptr, _size + not_decoded);
if (mad_frame_decode(&_frame, &_stream) == -1) {
- debug(1, "Error decoding after restream %d !", _stream.error);
+ debug(1, "Error %d decoding after restream !", _stream.error);
}
} else if (!MAD_RECOVERABLE(_stream.error)) {
error("MAD frame decode error in MP3 CDMUSIC !");
diff --git a/sound/module.mk b/sound/module.mk
index 9d502ef665..5744a80156 100644
--- a/sound/module.mk
+++ b/sound/module.mk
@@ -1,12 +1,15 @@
MODULE := sound
MODULE_OBJS = \
+ sound/audiostream.o \
sound/fmopl.o \
sound/midiparser.o \
sound/midiparser_smf.o \
sound/midiparser_xmidi.o \
sound/mixer.o \
- sound/mpu401.o
+ sound/mpu401.o \
+ sound/rate.o
+# sound/resample.o
# Include common rules
include common.rules