diff --git a/Core/HdAudioDevice.cpp b/Core/HdAudioDevice.cpp index a4e38307..18e2f784 100644 --- a/Core/HdAudioDevice.cpp +++ b/Core/HdAudioDevice.cpp @@ -41,8 +41,9 @@ bool HdAudioDevice::PlayBgmTrack(uint8_t track, uint32_t startOffset) { int trackId = _album * 256 + track; auto result = _hdData->BgmFilesById.find(trackId); + auto result2 = _hdData->BgmLoopPointsById.find(trackId); if(result != _hdData->BgmFilesById.end()) { - if(_oggMixer->Play(result->second, false, startOffset)) { + if(_oggMixer->Play(result->second, false, startOffset, result2->second)) { _lastBgmTrack = trackId; return true; } @@ -56,7 +57,7 @@ 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, 0); + return !_oggMixer->Play(result->second, true, 0, 0); } else { MessageManager::Log("[HDPack] Invalid album+sfx number combination: " + std::to_string(_album) + ":" + std::to_string(sfxNumber)); return false; diff --git a/Core/HdData.h b/Core/HdData.h index cc002a1c..5db444bc 100644 --- a/Core/HdData.h +++ b/Core/HdData.h @@ -356,6 +356,7 @@ struct HdPackData std::unordered_map> TileByKey; std::unordered_map PatchesByHash; std::unordered_map BgmFilesById; + std::unordered_map BgmLoopPointsById; std::unordered_map SfxFilesById; vector Palette; diff --git a/Core/HdPackLoader.cpp b/Core/HdPackLoader.cpp index 5453d5c8..d933a32f 100644 --- a/Core/HdPackLoader.cpp +++ b/Core/HdPackLoader.cpp @@ -655,6 +655,12 @@ void HdPackLoader::ProcessBgmTag(vector &tokens) } else { _data->BgmFilesById[trackId] = FolderUtilities::CombinePath(_hdPackFolder, tokens[2]); } + if (tokens.size() >= 4) { + stringstream pt(tokens[3]); + uint32_t loopPoint; + pt >> loopPoint; + _data->BgmLoopPointsById[trackId] = loopPoint; + } } } diff --git a/Core/OggMixer.cpp b/Core/OggMixer.cpp index 0e4589fe..ca1600f0 100644 --- a/Core/OggMixer.cpp +++ b/Core/OggMixer.cpp @@ -80,11 +80,11 @@ void OggMixer::SetSampleRate(int sampleRate) } } -bool OggMixer::Play(string filename, bool isSfx, uint32_t startOffset) +bool OggMixer::Play(string filename, bool isSfx, uint32_t startOffset, uint32_t loopPoint) { shared_ptr reader(new OggReader()); bool loop = !isSfx && (_options & (int)OggPlaybackOptions::Loop) != 0; - if(reader->Init(filename, loop, _sampleRate, startOffset)) { + if(reader->Init(filename, loop, _sampleRate, startOffset, loopPoint)) { if(isSfx) { _sfx.push_back(reader); } else { diff --git a/Core/OggMixer.h b/Core/OggMixer.h index 2eb00058..4e4592ee 100644 --- a/Core/OggMixer.h +++ b/Core/OggMixer.h @@ -22,7 +22,7 @@ public: void ApplySamples(int16_t* buffer, size_t sampleCount, double masterVolumne); void Reset(uint32_t sampleRate); - bool Play(string filename, bool isSfx, uint32_t startOffset); + bool Play(string filename, bool isSfx, uint32_t startOffset, uint32_t loopPoint); void SetPlaybackOptions(uint8_t options); void SetPausedFlag(bool paused); void StopBgm(); diff --git a/Core/OggReader.cpp b/Core/OggReader.cpp index 86018f57..cbc17b86 100644 --- a/Core/OggReader.cpp +++ b/Core/OggReader.cpp @@ -22,21 +22,24 @@ OggReader::~OggReader() } } -bool OggReader::Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset) +bool OggReader::Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset, uint32_t loopPoint) { int error; VirtualFile file = filename; _fileData = vector(100000); if(file.ReadFile(_fileData)) { _vorbis = stb_vorbis_open_memory(_fileData.data(), (int)_fileData.size(), &error, nullptr); + if(_vorbis) { _loop = loop; + _loopPoint = loopPoint; _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; } } @@ -78,7 +81,7 @@ bool OggReader::LoadSamples() if(samplesReturned < OggReader::SamplesToRead) { if(_loop) { - stb_vorbis_seek_start(_vorbis); + stb_vorbis_seek(_vorbis, _loopPoint); LoadSamples(); } else { _done = true; diff --git a/Core/OggReader.h b/Core/OggReader.h index f3d84bc7..6c898e5c 100644 --- a/Core/OggReader.h +++ b/Core/OggReader.h @@ -15,6 +15,7 @@ private: bool _loop; bool _done; + uint32_t _loopPoint; blip_t* _blipLeft; blip_t* _blipRight; @@ -30,7 +31,7 @@ public: OggReader(); ~OggReader(); - bool Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset = 0); + bool Init(string filename, bool loop, uint32_t sampleRate, uint32_t startOffset = 0, uint32_t loopPoint = 0); bool IsPlaybackOver(); void SetSampleRate(int sampleRate); void SetLoopFlag(bool loop);