AUDIO: Update Vag/XA code from ScummVM

Looping sounds now work in EMI PS2
This commit is contained in:
Matthew Hoops 2011-08-28 20:13:11 -04:00
parent a8154e2a12
commit 03f13f8307
4 changed files with 81 additions and 60 deletions

View File

@ -20,79 +20,78 @@
*
*/
#include "audio/decoders/vag.h"
#include "audio/decoders/xa.h"
#include "audio/audiostream.h"
#include "common/stream.h"
namespace Audio {
class VagStream : public Audio::RewindableAudioStream {
class XAStream : public Audio::RewindableAudioStream {
public:
VagStream(Common::SeekableReadStream *stream, int rate);
~VagStream();
XAStream(Common::SeekableReadStream *stream, int rate, DisposeAfterUse::Flag disposeAfterUse);
~XAStream();
bool isStereo() const { return false; }
bool endOfData() const { return _stream->pos() == _stream->size(); }
bool endOfData() const { return _endOfData && _samplesRemaining == 0; }
int getRate() const { return _rate; }
int readBuffer(int16 *buffer, const int numSamples);
bool rewind();
private:
Common::SeekableReadStream *_stream;
DisposeAfterUse::Flag _disposeAfterUse;
void seekToPos(uint pos);
byte _predictor;
double _samples[28];
byte _samplesRemaining;
int _rate;
double _s1, _s2;
uint _loopPoint;
bool _endOfData;
};
VagStream::VagStream(Common::SeekableReadStream *stream, int rate) : _stream(stream) {
XAStream::XAStream(Common::SeekableReadStream *stream, int rate, DisposeAfterUse::Flag disposeAfterUse)
: _stream(stream), _disposeAfterUse(disposeAfterUse) {
_samplesRemaining = 0;
_predictor = 0;
_s1 = _s2 = 0.0;
_rate = rate;
_loopPoint = 0;
_endOfData = false;
}
VagStream::~VagStream() {
delete _stream;
XAStream::~XAStream() {
if (_disposeAfterUse == DisposeAfterUse::YES)
delete _stream;
}
static const double s_vagDataTable[5][2] =
{
{ 0.0, 0.0 },
{ 60.0 / 64.0, 0.0 },
{ 115.0 / 64.0, -52.0 / 64.0 },
{ 98.0 / 64.0, -55.0 / 64.0 },
{ 122.0 / 64.0, -60.0 / 64.0 }
};
static const double s_xaDataTable[5][2] = {
{ 0.0, 0.0 },
{ 60.0 / 64.0, 0.0 },
{ 115.0 / 64.0, -52.0 / 64.0 },
{ 98.0 / 64.0, -55.0 / 64.0 },
{ 122.0 / 64.0, -60.0 / 64.0 }
};
int VagStream::readBuffer(int16 *buffer, const int numSamples) {
int XAStream::readBuffer(int16 *buffer, const int numSamples) {
int32 samplesDecoded = 0;
if (_samplesRemaining) {
byte i = 0;
for (i = 28 - _samplesRemaining; i < 28 && samplesDecoded < numSamples; i++) {
_samples[i] = _samples[i] + _s1 * s_vagDataTable[_predictor][0] + _s2 * s_vagDataTable[_predictor][1];
_s2 = _s1;
_s1 = _samples[i];
int16 d = (int) (_samples[i] + 0.5);
buffer[samplesDecoded] = d;
samplesDecoded++;
}
#if 0
assert(i == 28); // We're screwed if this fails :P
#endif
// This might mean the file is corrupted, or that the stream has
// been closed.
if (i != 28) return 0;
_samplesRemaining = 0;
for (int i = 28 - _samplesRemaining; i < 28 && samplesDecoded < numSamples; i++) {
_samples[i] = _samples[i] + _s1 * s_xaDataTable[_predictor][0] + _s2 * s_xaDataTable[_predictor][1];
_s2 = _s1;
_s1 = _samples[i];
int16 d = (int) (_samples[i] + 0.5);
buffer[samplesDecoded] = d;
samplesDecoded++;
_samplesRemaining--;
}
if (endOfData())
return samplesDecoded;
while (samplesDecoded < numSamples) {
byte i = 0;
@ -100,8 +99,19 @@ int VagStream::readBuffer(int16 *buffer, const int numSamples) {
byte shift = _predictor & 0xf;
_predictor >>= 4;
if (_stream->readByte() == 7)
byte flags = _stream->readByte();
if (flags == 3) {
// Loop
seekToPos(_loopPoint);
continue;
} else if (flags == 6) {
// Set loop point
_loopPoint = _stream->pos() - 2;
} else if (flags == 7) {
// End of stream
_endOfData = true;
return samplesDecoded;
}
for (i = 0; i < 28; i += 2) {
byte d = _stream->readByte();
@ -116,7 +126,7 @@ int VagStream::readBuffer(int16 *buffer, const int numSamples) {
}
for (i = 0; i < 28 && samplesDecoded < numSamples; i++) {
_samples[i] = _samples[i] + _s1 * s_vagDataTable[_predictor][0] + _s2 * s_vagDataTable[_predictor][1];
_samples[i] = _samples[i] + _s1 * s_xaDataTable[_predictor][0] + _s2 * s_xaDataTable[_predictor][1];
_s2 = _s1;
_s1 = _samples[i];
int16 d = (int) (_samples[i] + 0.5);
@ -124,24 +134,31 @@ int VagStream::readBuffer(int16 *buffer, const int numSamples) {
samplesDecoded++;
}
if (i != 27)
if (i != 28)
_samplesRemaining = 28 - i;
if (_stream->pos() >= _stream->size())
_endOfData = true;
}
return samplesDecoded;
}
bool VagStream::rewind() {
_stream->seek(0);
_samplesRemaining = 0;
_predictor = 0;
_s1 = _s2 = 0.0;
bool XAStream::rewind() {
seekToPos(0);
return true;
}
RewindableAudioStream *makeVagStream(Common::SeekableReadStream *stream, int rate) {
return new VagStream(stream, rate);
void XAStream::seekToPos(uint pos) {
_stream->seek(pos);
_samplesRemaining = 0;
_predictor = 0;
_s1 = _s2 = 0.0;
_endOfData = false;
}
RewindableAudioStream *makeXAStream(Common::SeekableReadStream *stream, int rate, DisposeAfterUse::Flag disposeAfterUse) {
return new XAStream(stream, rate, disposeAfterUse);
}
} // End of namespace Audio

View File

@ -28,8 +28,10 @@
* - tinsel (PSX port of the game)
*/
#ifndef SOUND_VAG_H
#define SOUND_VAG_H
#ifndef AUDIO_DECODERS_XA_H
#define AUDIO_DECODERS_XA_H
#include "common/types.h"
namespace Common {
class SeekableReadStream;
@ -40,17 +42,19 @@ namespace Audio {
class RewindableAudioStream;
/**
* Takes an input stream containing Vag sound data and creates
* Takes an input stream containing XA ADPCM sound data and creates
* an RewindableAudioStream from that.
*
* @param stream the SeekableReadStream from which to read the ADPCM data
* @param stream the SeekableReadStream from which to read the XA ADPCM data
* @param rate the sampling rate
* @param disposeAfterUse whether to delete the stream after use.
* @return a new RewindableAudioStream, or NULL, if an error occurred
*/
RewindableAudioStream *makeVagStream(
RewindableAudioStream *makeXAStream(
Common::SeekableReadStream *stream,
int rate = 11025);
int rate,
DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
} // End of namespace Sword1
} // End of namespace Audio
#endif

View File

@ -13,8 +13,8 @@ MODULE_OBJS := \
decoders/flac.o \
decoders/mp3.o \
decoders/raw.o \
decoders/vag.o \
decoders/vorbis.o \
decoders/xa.o \
softsynth/adlib.o \
softsynth/cms.o \
softsynth/opl/dbopl.o \

View File

@ -21,7 +21,7 @@
*/
#include "audio/audiostream.h"
#include "audio/decoders/vag.h"
#include "audio/decoders/xa.h"
#include "common/memstream.h"
#include "common/textconsole.h"
#include "common/stream.h"
@ -127,14 +127,14 @@ SCXStream::SCXStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag d
rightStream->write(buf, _blockSize);
}
_xaStreams[0] = Audio::makeVagStream(new Common::MemoryReadStream(leftOut, channelSize[0], DisposeAfterUse::YES), _rate);
_xaStreams[1] = Audio::makeVagStream(new Common::MemoryReadStream(rightOut, channelSize[1], DisposeAfterUse::YES), _rate);
_xaStreams[0] = Audio::makeXAStream(new Common::MemoryReadStream(leftOut, channelSize[0], DisposeAfterUse::YES), _rate);
_xaStreams[1] = Audio::makeXAStream(new Common::MemoryReadStream(rightOut, channelSize[1], DisposeAfterUse::YES), _rate);
delete[] buf;
delete leftStream;
delete rightStream;
} else {
_xaStreams[0] = Audio::makeVagStream(stream->readStream(channelSize[0]), _rate);
_xaStreams[0] = Audio::makeXAStream(stream->readStream(channelSize[0]), _rate);
_xaStreams[1] = 0;
}