From f89d4736c61e88d9b68ca90aaa7fc50c19b9b908 Mon Sep 17 00:00:00 2001 From: Valley Bell Date: Fri, 22 Dec 2023 12:47:26 +0100 Subject: [PATCH] player: add time measurement options --- player.cpp | 14 +++++++++++--- player/droplayer.cpp | 5 +++++ player/droplayer.hpp | 1 + player/gymplayer.cpp | 5 +++++ player/gymplayer.hpp | 1 + player/playera.cpp | 35 ++++++++++++++++++++++++----------- player/playera.hpp | 11 +++++++++-- player/playerbase.cpp | 7 ++++++- player/playerbase.hpp | 1 + player/s98player.cpp | 5 +++++ player/s98player.hpp | 1 + player/vgmplayer.cpp | 5 +++++ player/vgmplayer.hpp | 1 + vgm2wav.cpp | 2 +- 14 files changed, 76 insertions(+), 18 deletions(-) diff --git a/player.cpp b/player.cpp index 5557e5ab..15dab14c 100644 --- a/player.cpp +++ b/player.cpp @@ -95,6 +95,7 @@ static UINT32 masterVol = 0x10000; // fixed point 16.16 static UINT8 showTags = 1; static bool showFileInfo = false; static UINT8 logLevel = DEVLOG_INFO; +static UINT8 pbTimeMode = PLAYTIME_LOOP_INCL | PLAYTIME_TIME_FILE; static PlayerA mainPlr; @@ -364,7 +365,7 @@ int main(int argc, char* argv[]) pState = "Playing"; if (vgmPcmStrms == NULL || vgmPcmStrms->empty()) { - printf("%s %.2f / %.2f ... \r", pState, mainPlr.GetCurTime(1), mainPlr.GetTotalTime(1)); + printf("%s %.2f / %.2f ... \r", pState, mainPlr.GetCurTime(pbTimeMode), mainPlr.GetTotalTime(pbTimeMode)); } else { @@ -377,7 +378,7 @@ int main(int argc, char* argv[]) if (pbMode.length() == 1) pbMode = ""; printf("%s %.2f / %.2f [%02X / %02X at %4.1f KHz%s] ... \r", - pState, mainPlr.GetCurTime(1), mainPlr.GetTotalTime(1), + pState, mainPlr.GetCurTime(pbTimeMode), mainPlr.GetTotalTime(pbTimeMode), 1 + strmDev->lastItem, strmDev->maxItems, strmDev->freq / 1000.0, pbMode.c_str()); } @@ -509,6 +510,7 @@ Sound Chip ID: T param - show tags (0/D/OFF - off, 1/E/ON - on) FI param - show file information (see above) LL param - set log level (0..5 = off/error/warn/info/debug/trace, see emu/EmuStructs.h) + TD param - set time display mode (bit mask: 0/1 = exclude/include loops, 0/2 = file/playback time, 4 = with fade time) Q - quit P - player configuration SPD param - set playback speed (1.0 = 100%) @@ -913,7 +915,7 @@ static void DoChipControlMode(PlayerBase* player) char* tokenStr; // Tags / FileInfo - printf("Command [T/FI/LL data]: "); + printf("Command [T/FI/LL/TD data]: "); fgets(line, 0x80, stdin); StripNewline(line); @@ -951,6 +953,12 @@ static void DoChipControlMode(PlayerBase* player) if (endPtr > tokenStr) logLevel = newLevel; } + else if (! strcmp(line, "TD")) + { + UINT8 newTimeMode = (UINT8)strtoul(tokenStr, &endPtr, 0); + if (endPtr > tokenStr) + pbTimeMode = newTimeMode; + } else if (! strcmp(line, "Q")) mode = -1; else diff --git a/player/droplayer.cpp b/player/droplayer.cpp index 77ebbdf2..86006bb6 100644 --- a/player/droplayer.cpp +++ b/player/droplayer.cpp @@ -541,6 +541,11 @@ UINT8 DROPlayer::SetSampleRate(UINT32 sampleRate) return 0x00; } +double DROPlayer::GetPlaybackSpeed(void) const +{ + return _playOpts.genOpts.pbSpeed / (double)0x10000; +} + UINT8 DROPlayer::SetPlaybackSpeed(double speed) { _playOpts.genOpts.pbSpeed = (UINT32)(0x10000 * speed); diff --git a/player/droplayer.hpp b/player/droplayer.hpp index 827805e4..bfc65b67 100644 --- a/player/droplayer.hpp +++ b/player/droplayer.hpp @@ -113,6 +113,7 @@ class DROPlayer : public PlayerBase //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); UINT32 Tick2Sample(UINT32 ticks) const; diff --git a/player/gymplayer.cpp b/player/gymplayer.cpp index d5afb8d1..59850c96 100644 --- a/player/gymplayer.cpp +++ b/player/gymplayer.cpp @@ -485,6 +485,11 @@ UINT8 GYMPlayer::SetSampleRate(UINT32 sampleRate) return 0x00; } +double GYMPlayer::GetPlaybackSpeed(void) const +{ + return _playOpts.genOpts.pbSpeed / (double)0x10000; +} + UINT8 GYMPlayer::SetPlaybackSpeed(double speed) { _playOpts.genOpts.pbSpeed = (UINT32)(0x10000 * speed); diff --git a/player/gymplayer.hpp b/player/gymplayer.hpp index 364eab0e..98208f69 100644 --- a/player/gymplayer.hpp +++ b/player/gymplayer.hpp @@ -89,6 +89,7 @@ class GYMPlayer : public PlayerBase //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); UINT32 Tick2Sample(UINT32 ticks) const; diff --git a/player/playera.cpp b/player/playera.cpp index 73a3a34e..6305a8b3 100644 --- a/player/playera.cpp +++ b/player/playera.cpp @@ -300,29 +300,42 @@ UINT32 PlayerA::GetCurPos(UINT8 unit) const return _player->GetCurPos(unit); } -double PlayerA::GetCurTime(UINT8 includeLoops) const +double PlayerA::GetCurTime(UINT8 flags) const { if (_player == NULL) return -1.0; + // using samples here, as it may be more accurate than the (possibly low-resolution) ticks double ticks = _player->Sample2Second(_player->GetCurPos(PLAYPOS_SAMPLE)); - if (! includeLoops) - { - UINT32 curLoop = _player->GetCurLoop(); - if (curLoop > 0) - ticks -= _player->Tick2Second(_player->GetLoopTicks() * curLoop); - } + UINT32 curLoop = _player->GetCurLoop(); + if (! (flags & PLAYTIME_LOOP_INCL) && curLoop > 0) + ticks -= _player->Tick2Second(_player->GetLoopTicks() * curLoop); + + if (! (flags & PLAYTIME_TIME_PBK)) + ticks *= _player->GetPlaybackSpeed(); return ticks; } -double PlayerA::GetTotalTime(UINT8 includeLoops) const +double PlayerA::GetTotalTime(UINT8 flags) const { if (_player == NULL) return -1.0; - if (includeLoops) - return _player->Tick2Second(_player->GetTotalPlayTicks(_config.loopCount)); + + double ticks; + if (flags & PLAYTIME_LOOP_INCL) + ticks = _player->Tick2Second(_player->GetTotalPlayTicks(_config.loopCount)); else - return _player->Tick2Second(_player->GetTotalPlayTicks(1)); + ticks = _player->Tick2Second(_player->GetTotalPlayTicks(1)); + + // Fade and silence time are unaffected by playback speed and thus must be applied before speed scaling. + if ((flags & PLAYTIME_WITH_FADE) && _player->GetLoopTicks() > 0) + ticks += _player->Sample2Second(GetFadeSamples()); + if (flags & PLAYTIME_WITH_SLNC) + ticks += _player->Sample2Second(GetEndSilenceSamples()); + + if (! (flags & PLAYTIME_TIME_PBK)) + ticks *= _player->GetPlaybackSpeed(); + return ticks; } UINT32 PlayerA::GetCurLoop(void) const diff --git a/player/playera.hpp b/player/playera.hpp index 4c0507e9..04e34ba8 100644 --- a/player/playera.hpp +++ b/player/playera.hpp @@ -10,6 +10,13 @@ #define PLAYSTATE_FADE 0x10 // is fading #define PLAYSTATE_FIN 0x20 // finished playing (file end + fading + trailing silence) +#define PLAYTIME_LOOP_EXCL 0x00 // excluding loops, jumps back in time when the file loops +#define PLAYTIME_LOOP_INCL 0x01 // including loops, no jumping back +#define PLAYTIME_TIME_FILE 0x00 // file time, progresses slower/faster when playback speed is adjusted +#define PLAYTIME_TIME_PBK 0x02 // playback time, file duration will be longer/shorter when playback speed is adjusted +#define PLAYTIME_WITH_FADE 0x10 // include fade out time (looping songs only) +#define PLAYTIME_WITH_SLNC 0x20 // include silence after songs + // TODO: find a proper name for this class class PlayerA { @@ -54,8 +61,8 @@ class PlayerA void SetLogCallback(PLAYER_LOG_CB cbFunc, void* cbParam); UINT8 GetState(void) const; UINT32 GetCurPos(UINT8 unit) const; - double GetCurTime(UINT8 includeLoops) const; - double GetTotalTime(UINT8 includeLoops) const; + double GetCurTime(UINT8 flags) const; + double GetTotalTime(UINT8 flags) const; UINT32 GetCurLoop(void) const; double GetLoopTime(void) const; PlayerBase* GetPlayer(void); diff --git a/player/playerbase.cpp b/player/playerbase.cpp index 0dc6b828..e728bfd4 100644 --- a/player/playerbase.cpp +++ b/player/playerbase.cpp @@ -64,9 +64,14 @@ UINT8 PlayerBase::SetSampleRate(UINT32 sampleRate) return 0x00; } +double PlayerBase::GetPlaybackSpeed(void) const +{ + return -1; // not implemented +} + UINT8 PlayerBase::SetPlaybackSpeed(double speed) { - return 0xFF; // not yet supported + return 0xFF; // not implemented } void PlayerBase::SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam) diff --git a/player/playerbase.hpp b/player/playerbase.hpp index e811d2c3..4995f4aa 100644 --- a/player/playerbase.hpp +++ b/player/playerbase.hpp @@ -130,6 +130,7 @@ class PlayerBase virtual UINT32 GetSampleRate(void) const; virtual UINT8 SetSampleRate(UINT32 sampleRate); + virtual double GetPlaybackSpeed(void) const; virtual UINT8 SetPlaybackSpeed(double speed); virtual void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); virtual void SetFileReqCallback(PLAYER_FILEREQ_CB cbFunc, void* cbParam); diff --git a/player/s98player.cpp b/player/s98player.cpp index 92a901e7..a8049bb6 100644 --- a/player/s98player.cpp +++ b/player/s98player.cpp @@ -739,6 +739,11 @@ UINT8 S98Player::SetSampleRate(UINT32 sampleRate) return 0x00; } +double S98Player::GetPlaybackSpeed(void) const +{ + return _playOpts.genOpts.pbSpeed / (double)0x10000; +} + UINT8 S98Player::SetPlaybackSpeed(double speed) { _playOpts.genOpts.pbSpeed = (UINT32)(0x10000 * speed); diff --git a/player/s98player.hpp b/player/s98player.hpp index 11e33316..49660561 100644 --- a/player/s98player.hpp +++ b/player/s98player.hpp @@ -89,6 +89,7 @@ class S98Player : public PlayerBase //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); UINT32 Tick2Sample(UINT32 ticks) const; diff --git a/player/vgmplayer.cpp b/player/vgmplayer.cpp index 591511bf..ea6e2e00 100644 --- a/player/vgmplayer.cpp +++ b/player/vgmplayer.cpp @@ -737,6 +737,11 @@ UINT8 VGMPlayer::SetSampleRate(UINT32 sampleRate) return 0x00; } +double VGMPlayer::GetPlaybackSpeed(void) const +{ + return _playOpts.genOpts.pbSpeed / (double)0x10000; +} + UINT8 VGMPlayer::SetPlaybackSpeed(double speed) { _playOpts.genOpts.pbSpeed = (UINT32)(0x10000 * speed); diff --git a/player/vgmplayer.hpp b/player/vgmplayer.hpp index 74f1d80d..c5d3c6ba 100644 --- a/player/vgmplayer.hpp +++ b/player/vgmplayer.hpp @@ -167,6 +167,7 @@ class VGMPlayer : public PlayerBase //UINT32 GetSampleRate(void) const; UINT8 SetSampleRate(UINT32 sampleRate); + double GetPlaybackSpeed(void) const; UINT8 SetPlaybackSpeed(double speed); //void SetEventCallback(PLAYER_EVENT_CB cbFunc, void* cbParam); //void SetFileReqCallback(PLAYER_FILEREQ_CB cbFunc, void* cbParam); diff --git a/vgm2wav.cpp b/vgm2wav.cpp index 50f3c67c..ef2d3000 100644 --- a/vgm2wav.cpp +++ b/vgm2wav.cpp @@ -611,7 +611,7 @@ static void frames_to_little_endian(UINT8 *data, unsigned int frame_count) { repack_int24le(&data[3], &data[3]); break; } - defafult: /* 16 */ { + default: /* 16 */ { repack_int16le(&data[0], &data[0]); repack_int16le(&data[2], &data[2]); break;