mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-27 14:57:56 +00:00
AUDIO: Update Vag/XA code from ScummVM
Looping sounds now work in EMI PS2
This commit is contained in:
parent
a8154e2a12
commit
03f13f8307
@ -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
|
@ -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
|
@ -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 \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user