Add option to specify loop start in bgm tag

This commit is contained in:
mkwong98 2020-11-15 01:59:13 +08:00
parent 81b9ee5f72
commit 37e1b8dfec
7 changed files with 20 additions and 8 deletions

View file

@ -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;

View file

@ -356,6 +356,7 @@ struct HdPackData
std::unordered_map<HdTileKey, vector<HdPackTileInfo*>> TileByKey;
std::unordered_map<string, string> PatchesByHash;
std::unordered_map<int, string> BgmFilesById;
std::unordered_map<int, uint32_t> BgmLoopPointsById;
std::unordered_map<int, string> SfxFilesById;
vector<uint32_t> Palette;

View file

@ -655,6 +655,12 @@ void HdPackLoader::ProcessBgmTag(vector<string> &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;
}
}
}

View file

@ -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<OggReader> 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 {

View file

@ -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();

View file

@ -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<uint8_t>(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;

View file

@ -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);