mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-14 21:59:17 +00:00
TITANIC: Refactor CWaveFile audio stream generation
Wave files need to handle both stand-alone playback via an audio stream, as well as reading the raw data when merging instrument fragments in the music room.
This commit is contained in:
parent
c2b3abd676
commit
6618af29fa
@ -204,9 +204,9 @@ void QMixer::qsWaveMixPump() {
|
||||
if (sound._started && !_mixer->isSoundHandleActive(sound._soundHandle)) {
|
||||
if (sound._loops == -1 || sound._loops-- > 0) {
|
||||
// Need to loop the sound again
|
||||
sound._waveFile->_audioStream->rewind();
|
||||
sound._waveFile->audioStream()->rewind();
|
||||
_mixer->playStream(sound._waveFile->_soundType,
|
||||
&sound._soundHandle, sound._waveFile->_audioStream,
|
||||
&sound._soundHandle, sound._waveFile->audioStream(),
|
||||
-1, channel.getRawVolume(), 0, DisposeAfterUse::NO);
|
||||
} else {
|
||||
// Sound is finished
|
||||
@ -230,7 +230,7 @@ void QMixer::qsWaveMixPump() {
|
||||
|
||||
// Calculate an effective volume based on distance of source
|
||||
_mixer->playStream(sound._waveFile->_soundType,
|
||||
&sound._soundHandle, sound._waveFile->_audioStream,
|
||||
&sound._soundHandle, sound._waveFile->audioStream(),
|
||||
-1, channel.getRawVolume(), 0, DisposeAfterUse::NO);
|
||||
sound._started = true;
|
||||
}
|
||||
|
@ -28,14 +28,14 @@
|
||||
|
||||
namespace Titanic {
|
||||
|
||||
#define WAV_DATA_OFFSET 0x46
|
||||
|
||||
CWaveFile::CWaveFile() : _soundManager(nullptr), _audioStream(nullptr),
|
||||
_rawData(nullptr), _soundType(Audio::Mixer::kPlainSoundType) {
|
||||
_waveData(nullptr), _waveSize(0), _dataSize(0),
|
||||
_soundType(Audio::Mixer::kPlainSoundType) {
|
||||
setup();
|
||||
}
|
||||
|
||||
CWaveFile::CWaveFile(QSoundManager *owner) : _soundManager(owner), _audioStream(nullptr),
|
||||
_waveData(nullptr), _waveSize(0), _dataSize(0),
|
||||
_soundType(Audio::Mixer::kPlainSoundType) {
|
||||
setup();
|
||||
}
|
||||
@ -58,6 +58,8 @@ CWaveFile::~CWaveFile() {
|
||||
|
||||
if (_disposeAudioBuffer == DisposeAfterUse::YES && _audioBuffer)
|
||||
delete _audioBuffer;
|
||||
|
||||
delete[] _waveData;
|
||||
}
|
||||
|
||||
uint CWaveFile::getDurationTicks() const {
|
||||
@ -68,8 +70,7 @@ uint CWaveFile::getDurationTicks() const {
|
||||
// a desired size. Since I have no idea how the system API
|
||||
// method works, for now I'm using a simple ratio of a
|
||||
// sample output to input value
|
||||
uint dataSize = _dataSize - WAV_DATA_OFFSET;
|
||||
double newSize = (double)dataSize * (1475712.0 / 199836.0);
|
||||
double newSize = (double)_dataSize * (1475712.0 / 199836.0);
|
||||
return (uint)(newSize * 1000.0 / _audioStream->getRate());
|
||||
}
|
||||
|
||||
@ -81,17 +82,12 @@ bool CWaveFile::loadSound(const CString &name) {
|
||||
return false;
|
||||
|
||||
Common::SeekableReadStream *stream = file.readStream();
|
||||
uint dataSize = stream->size();
|
||||
_dataSize = dataSize - 44;
|
||||
uint size = stream->size();
|
||||
byte *data = new byte[size];
|
||||
stream->read(data, size);
|
||||
|
||||
_rawData = new byte[dataSize];
|
||||
stream->read(_rawData, dataSize);
|
||||
|
||||
_audioStream = Audio::makeWAVStream(
|
||||
new Common::MemoryReadStream(_rawData, dataSize, DisposeAfterUse::YES),
|
||||
DisposeAfterUse::YES);
|
||||
load(data, size);
|
||||
_soundType = Audio::Mixer::kSFXSoundType;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -102,12 +98,9 @@ bool CWaveFile::loadSpeech(CDialogueFile *dialogueFile, int speechIndex) {
|
||||
|
||||
byte *data = (byte *)malloc(res->_size);
|
||||
dialogueFile->read(res, data, res->_size);
|
||||
load(data, res->_size);
|
||||
|
||||
_dataSize = res->_size;
|
||||
_audioStream = Audio::makeWAVStream(new Common::MemoryReadStream(data, _dataSize, DisposeAfterUse::YES),
|
||||
DisposeAfterUse::YES);
|
||||
_soundType = Audio::Mixer::kSpeechSoundType;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -119,10 +112,13 @@ bool CWaveFile::loadMusic(const CString &name) {
|
||||
return false;
|
||||
|
||||
Common::SeekableReadStream *stream = file.readStream();
|
||||
_dataSize = stream->size();
|
||||
_audioStream = Audio::makeWAVStream(stream->readStream(_dataSize), DisposeAfterUse::YES);
|
||||
_soundType = Audio::Mixer::kMusicSoundType;
|
||||
uint size = stream->size();
|
||||
byte *data = new byte[size];
|
||||
stream->read(data, size);
|
||||
delete stream;
|
||||
|
||||
load(data, size);
|
||||
_soundType = Audio::Mixer::kMusicSoundType;
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -135,18 +131,44 @@ bool CWaveFile::loadMusic(CAudioBuffer *buffer, DisposeAfterUse::Flag disposeAft
|
||||
return true;
|
||||
}
|
||||
|
||||
uint CWaveFile::getFrequency() const {
|
||||
return _audioStream->getRate();
|
||||
void CWaveFile::load(byte *data, uint size) {
|
||||
_waveData = data;
|
||||
_waveSize = size;
|
||||
|
||||
// Parse the wave header
|
||||
Common::MemoryReadStream wavStream(data, size, DisposeAfterUse::NO);
|
||||
int rate;
|
||||
byte flags;
|
||||
Audio::loadWAVFromStream(wavStream, _dataSize, rate, flags);
|
||||
}
|
||||
|
||||
Audio::SeekableAudioStream *CWaveFile::audioStream() {
|
||||
if (!_audioStream) {
|
||||
// No stream yet, so create one and give it control of the raw wave data
|
||||
assert(_waveData);
|
||||
_audioStream = Audio::makeWAVStream(
|
||||
new Common::MemoryReadStream(_waveData, _waveSize, DisposeAfterUse::YES),
|
||||
DisposeAfterUse::YES);
|
||||
_waveData = nullptr;
|
||||
}
|
||||
|
||||
return _audioStream;
|
||||
}
|
||||
|
||||
|
||||
uint CWaveFile::getFrequency() {
|
||||
return audioStream()->getRate();
|
||||
}
|
||||
|
||||
void CWaveFile::reset() {
|
||||
_audioStream->rewind();
|
||||
audioStream()->rewind();
|
||||
}
|
||||
|
||||
const byte *CWaveFile::lock() {
|
||||
switch (_loadMode) {
|
||||
case LOADMODE_SCUMMVM:
|
||||
return _rawData + WAV_DATA_OFFSET;
|
||||
assert(_waveData);
|
||||
return _waveData;
|
||||
|
||||
default:
|
||||
return nullptr;
|
||||
|
@ -36,22 +36,29 @@ enum LoadMode { LOADMODE_AUDIO_BUFFER = 1, LOADMODE_SCUMMVM = 2 };
|
||||
class QSoundManager;
|
||||
|
||||
class CWaveFile {
|
||||
private:
|
||||
byte *_waveData;
|
||||
int _waveSize;
|
||||
int _dataSize;
|
||||
QSoundManager *_soundManager;
|
||||
Audio::SeekableAudioStream *_audioStream;
|
||||
Audio::SoundHandle _soundHandle;
|
||||
private:
|
||||
/**
|
||||
* Handles setup of fields shared by the constructors
|
||||
*/
|
||||
void setup();
|
||||
|
||||
/**
|
||||
* Gets passed the raw data for the wave file
|
||||
*/
|
||||
void load(byte *data, uint size);
|
||||
public:
|
||||
QSoundManager *_soundManager;
|
||||
byte *_rawData;
|
||||
Audio::SeekableAudioStream *_audioStream;
|
||||
Audio::SoundHandle _soundHandle;
|
||||
Audio::Mixer::SoundType _soundType;
|
||||
|
||||
LoadMode _loadMode;
|
||||
int _field4;
|
||||
int _field14;
|
||||
uint _dataSize;
|
||||
CAudioBuffer *_audioBuffer;
|
||||
DisposeAfterUse::Flag _disposeAudioBuffer;
|
||||
int _channel;
|
||||
@ -72,6 +79,11 @@ public:
|
||||
*/
|
||||
uint size() const { return _dataSize; }
|
||||
|
||||
/**
|
||||
* Returns a ScummVM Audio Stream for playback purposes
|
||||
*/
|
||||
Audio::SeekableAudioStream *audioStream();
|
||||
|
||||
/**
|
||||
* Tries to load the specified wave file sound
|
||||
*/
|
||||
@ -95,12 +107,14 @@ public:
|
||||
/**
|
||||
* Returns true if the wave file has data loaded
|
||||
*/
|
||||
bool isLoaded() const { return _audioStream != nullptr; }
|
||||
bool isLoaded() const {
|
||||
return _audioStream != nullptr || _waveData != nullptr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the frequency of the loaded wave file
|
||||
*/
|
||||
uint getFrequency() const;
|
||||
uint getFrequency();
|
||||
|
||||
/**
|
||||
* Resets the music stream
|
||||
|
Loading…
Reference in New Issue
Block a user