HD Packs: Save states now save audio state (for ogg bgm)

This commit is contained in:
Souryo 2017-08-20 19:03:16 -04:00
parent 7e50f2aee1
commit 2d53bc05a5
9 changed files with 85 additions and 14 deletions

View file

@ -551,6 +551,11 @@ void Console::SaveState(ostream &saveStream)
Instance->_apu->SaveSnapshot(&saveStream);
Instance->_controlManager->SaveSnapshot(&saveStream);
Instance->_mapper->SaveSnapshot(&saveStream);
if(Instance->_hdAudioDevice) {
Instance->_hdAudioDevice->SaveSnapshot(&saveStream);
} else {
Snapshotable::WriteEmptyBlock(&saveStream);
}
}
}
@ -567,6 +572,11 @@ void Console::LoadState(istream &loadStream)
Instance->_apu->LoadSnapshot(&loadStream);
Instance->_controlManager->LoadSnapshot(&loadStream);
Instance->_mapper->LoadSnapshot(&loadStream);
if(Instance->_hdAudioDevice) {
Instance->_hdAudioDevice->LoadSnapshot(&loadStream);
} else {
Snapshotable::SkipBlock(&loadStream);
}
MessageManager::SendNotification(ConsoleNotificationType::StateLoaded);
}
@ -636,11 +646,11 @@ bool Console::IsHdPpu()
void Console::LoadHdPack(VirtualFile &romFile, VirtualFile &patchFile)
{
_hdData.reset();
_hdAudioDevice.reset();
if(EmulationSettings::CheckFlag(EmulationFlags::UseHdPacks)) {
_hdData.reset(new HdPackData());
if(!HdPackLoader::LoadHdNesPack(romFile, *_hdData.get())) {
_hdData.reset();
_hdAudioDevice.reset();
} else {
auto result = _hdData->PatchesByHash.find(romFile.GetSha1Hash());
if(result != _hdData->PatchesByHash.end()) {

View file

@ -11,22 +11,43 @@ HdAudioDevice::HdAudioDevice(HdPackData * hdData)
_oggMixer = SoundMixer::GetOggMixer();
}
bool HdAudioDevice::PlayBgmTrack(uint8_t track)
void HdAudioDevice::StreamState(bool saving)
{
auto result = _hdData->BgmFilesById.find(_album * 256 + track);
int32_t trackOffset = 0;
if(saving) {
trackOffset = _oggMixer->GetBgmOffset();
if(trackOffset < 0) {
_lastBgmTrack = -1;
}
Stream(_album, _lastBgmTrack, trackOffset);
} else {
Stream(_album, _lastBgmTrack, trackOffset);
if(_lastBgmTrack != -1 && trackOffset > 0) {
PlayBgmTrack(_lastBgmTrack, trackOffset);
}
}
}
bool HdAudioDevice::PlayBgmTrack(uint8_t track, uint32_t startOffset)
{
int trackId = _album * 256 + track;
auto result = _hdData->BgmFilesById.find(trackId);
if(result != _hdData->BgmFilesById.end()) {
return !_oggMixer->Play(result->second, false);
if(_oggMixer->Play(result->second, false, startOffset)) {
_lastBgmTrack = trackId;
return true;
}
} else {
MessageManager::Log("[HDPack] Invalid album+track combination: " + std::to_string(_album) + ":" + std::to_string(track));
return false;
}
return false;
}
bool HdAudioDevice::PlaySfx(uint8_t sfxNumber)
{
auto result = _hdData->SfxFilesById.find(_album * 256 + sfxNumber);
if(result != _hdData->SfxFilesById.end()) {
return !_oggMixer->Play(result->second, true);
return !_oggMixer->Play(result->second, true, 0);
} else {
MessageManager::Log("[HDPack] Invalid album+sfx number combination: " + std::to_string(_album) + ":" + std::to_string(sfxNumber));
return false;
@ -98,7 +119,7 @@ void HdAudioDevice::WriteRAM(uint16_t addr, uint8_t value)
//Play BGM track (0-255 = track number)
//Stop the current BGM and starts a new track
case 5: _trackError = PlayBgmTrack(value); break;
case 5: _trackError = PlayBgmTrack(value, 0); break;
//Play sound effect (0-255 = sfx number)
//Plays a new sound effect (no limit to the number of simultaneous sound effects)

View file

@ -3,10 +3,11 @@
#include "IMemoryHandler.h"
#include "SoundMixer.h"
#include "OggMixer.h"
#include "Snapshotable.h"
struct HdPackData;
class HdAudioDevice : public IMemoryHandler
class HdAudioDevice : public IMemoryHandler, public Snapshotable
{
private:
HdPackData *_hdData;
@ -14,11 +15,15 @@ private:
uint8_t _flags;
bool _trackError;
OggMixer* _oggMixer;
int32_t _lastBgmTrack;
bool PlayBgmTrack(uint8_t track);
bool PlayBgmTrack(uint8_t track, uint32_t startOffset);
bool PlaySfx(uint8_t sfxNumber);
void ProcessControlFlags(uint8_t flags);
protected:
void StreamState(bool saving) override;
public:
HdAudioDevice(HdPackData *hdData);

View file

@ -80,11 +80,11 @@ void OggMixer::SetSampleRate(int sampleRate)
}
}
bool OggMixer::Play(string filename, bool isSfx)
bool OggMixer::Play(string filename, bool isSfx, uint32_t startOffset)
{
shared_ptr<OggReader> reader(new OggReader());
bool loop = !isSfx && (_options & (int)OggPlaybackOptions::Loop) != 0;
if(reader->Init(filename, loop, _sampleRate)) {
if(reader->Init(filename, loop, _sampleRate, startOffset)) {
if(isSfx) {
_sfx.push_back(reader);
} else {
@ -108,3 +108,12 @@ void OggMixer::ApplySamples(int16_t * buffer, size_t sampleCount)
}
_sfx.erase(std::remove_if(_sfx.begin(), _sfx.end(), [](const shared_ptr<OggReader>& o) { return o->IsPlaybackOver(); }), _sfx.end());
}
int OggMixer::GetBgmOffset()
{
if(_bgm) {
return _bgm->GetOffset();
} else {
return -1;
}
}

View file

@ -22,7 +22,7 @@ public:
void ApplySamples(int16_t* buffer, size_t sampleCount);
void Reset();
bool Play(string filename, bool isSfx);
bool Play(string filename, bool isSfx, uint32_t startOffset);
void SetPlaybackOptions(uint8_t options);
void SetPausedFlag(bool paused);
void StopBgm();
@ -31,4 +31,5 @@ public:
void SetSfxVolume(uint8_t volume);
bool IsBgmPlaying();
bool IsSfxPlaying();
int32_t GetBgmOffset();
};

View file

@ -22,7 +22,7 @@ OggReader::~OggReader()
}
}
bool OggReader::Init(string filename, bool loop, int sampleRate)
bool OggReader::Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset)
{
int error;
VirtualFile file = filename;
@ -32,6 +32,9 @@ bool OggReader::Init(string filename, bool loop, int sampleRate)
if(_vorbis) {
_loop = loop;
_oggSampleRate = stb_vorbis_get_info(_vorbis).sample_rate;
if(startOffset > 0) {
stb_vorbis_seek(_vorbis, startOffset);
}
blip_set_rates(_blipLeft, _oggSampleRate, sampleRate);
blip_set_rates(_blipRight, _oggSampleRate, sampleRate);
return true;
@ -100,3 +103,8 @@ void OggReader::ApplySamples(int16_t * buffer, size_t sampleCount, uint8_t volum
buffer[i] += (int16_t)(_outputBuffer[i] * (EmulationSettings::GetMasterVolume() * volume / 255 / 10));
}
}
uint32_t OggReader::GetOffset()
{
return stb_vorbis_get_file_offset(_vorbis);
}

View file

@ -31,9 +31,10 @@ public:
OggReader();
~OggReader();
bool Init(string filename, bool loop, int sampleRate);
bool Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset = 0);
bool IsPlaybackOver();
void SetSampleRate(int sampleRate);
void SetLoopFlag(bool loop);
void ApplySamples(int16_t* buffer, size_t sampleCount, uint8_t volume);
uint32_t GetOffset();
};

View file

@ -97,4 +97,17 @@ void Snapshotable::LoadSnapshot(istream* file)
if(_blockBuffer) {
throw new std::runtime_error("A call to StreamEndBlock is missing.");
}
}
void Snapshotable::WriteEmptyBlock(ostream* file)
{
int blockSize = 0;
file->write((char*)&blockSize, sizeof(blockSize));
}
void Snapshotable::SkipBlock(istream* file)
{
int blockSize = 0;
file->read((char*)&blockSize, sizeof(blockSize));
file->seekg(blockSize, ios::cur);
}

View file

@ -158,4 +158,7 @@ protected:
public:
void SaveSnapshot(ostream* file);
void LoadSnapshot(istream* file);
static void WriteEmptyBlock(ostream* file);
static void SkipBlock(istream* file);
};