diff --git a/CHANGELOG.md b/CHANGELOG.md index afbd9ada..d9c69d9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,11 +6,11 @@ Written by D.P.C.M. Version 0.5.2.9 -Last updated: January 06, 2026 +Last updated: January 07, 2026 --- -## Unreleased - 2026-01-06 +## Unreleased - 2026-01-07 ### Important changes @@ -22,7 +22,11 @@ Last updated: January 06, 2026 ### Bug fixes -- ... +- Revert "Fix C-0 not previewing DPCM sample" (@damifortune @Gumball2415 #383 #394) + - This reverts commit ac2648491c25473f0cc8c01ce8ef4cb09e9332c1. + - There doesn't seem to be any bug at the time of its writing upon further scrutiny. +- Separate tempo state updating from channel state updating (@JG540 @Gumball2415 #382 #384 #394) +- Set `m_iSpeed` to default when groove is enabled (@TakuikaNinja @Gumball2415 #379 #394) ### Internal diff --git a/Source/InstrumentEditorDPCM.cpp b/Source/InstrumentEditorDPCM.cpp index 49b58bfe..63c914e5 100644 --- a/Source/InstrumentEditorDPCM.cpp +++ b/Source/InstrumentEditorDPCM.cpp @@ -436,7 +436,7 @@ void CInstrumentEditorDPCM::OnNMClickTable(NMHDR *pNMHDR, LRESULT *pResult) m_iSelectedKey = GET_NOTE(pTableListCtrl->GetSelectionMark()) - 1; // // // m_iOctave = GET_OCTAVE(pTableListCtrl->GetSelectionMark()); - int Sample = m_pInstrument->GetSampleIndex(m_iOctave, m_iSelectedKey); + int Sample = m_pInstrument->GetSampleIndex(m_iOctave, m_iSelectedKey) - 1; int Pitch = m_pInstrument->GetSamplePitch(m_iOctave, m_iSelectedKey); int Delta = m_pInstrument->GetSampleDeltaValue(m_iOctave, m_iSelectedKey); diff --git a/Source/SoundGen.cpp b/Source/SoundGen.cpp index 04570aa1..06d6a865 100644 --- a/Source/SoundGen.cpp +++ b/Source/SoundGen.cpp @@ -32,7 +32,6 @@ #include "FamiTracker.h" #include "FamiTrackerTypes.h" #include "FTMComponentInterface.h" // // // -#include "ChannelState.h" // // // #include "FamiTrackerDoc.h" #include "FamiTrackerView.h" #include "VisualizerWnd.h" @@ -1527,32 +1526,41 @@ void CSoundGen::ApplyGlobalState() // // // int Frame = IsPlaying() ? GetPlayerFrame() : m_pTrackerView->GetSelectedFrame(); int Row = IsPlaying() ? GetPlayerRow() : m_pTrackerView->GetSelectedRow(); if (stFullState *State = m_pDocument->RetrieveSoundState(GetPlayerTrack(), Frame, Row, -1)) { - if (State->Tempo != -1) - m_iTempo = State->Tempo; - if (State->GroovePos >= 0) { - m_iGroovePosition = State->GroovePos; - if (State->Speed >= 0) - m_iGrooveIndex = State->Speed; - if (m_pDocument->GetGroove(m_iGrooveIndex) != NULL) - m_iSpeed = m_pDocument->GetGroove(m_iGrooveIndex)->GetEntry(m_iGroovePosition); - } - else { - if (State->Speed >= 0) - m_iSpeed = State->Speed; - m_iGrooveIndex = -1; - } - m_iLastHighlight = m_pDocument->GetHighlightAt(GetPlayerTrack(), Frame, Row).First; + ApplyGlobalTempoState(State); SetupSpeed(); + m_iLastHighlight = m_pDocument->GetHighlightAt(GetPlayerTrack(), Frame, Row).First; + for (int i = 0; i < m_pDocument->GetChannelCount(); i++) { for (int j = 0; j < sizeof(m_pTrackerChannels) / sizeof(CTrackerChannel*); ++j) // // // pick this out later if (m_pChannels[j] && m_pTrackerChannels[j]->GetID() == State->State[i].ChannelIndex) { m_pChannels[j]->ApplyChannelState(&State->State[i]); break; } } + delete State; } } +// Separate updating groove, tempo and speed +// to allow ResetTempo() to get the most recent state without updating the channel state +void CSoundGen::ApplyGlobalTempoState(stFullState *pState) +{ + if (pState->Tempo != -1) + m_iTempo = pState->Tempo; + if (pState->GroovePos >= 0) { + m_iGroovePosition = pState->GroovePos; + if (pState->Speed >= 0) + m_iGrooveIndex = pState->Speed; + if (m_pDocument->GetGroove(m_iGrooveIndex) != NULL) + m_iSpeed = m_pDocument->GetGroove(m_iGrooveIndex)->GetEntry(m_iGroovePosition); + } + else { + if (pState->Speed >= 0) + m_iSpeed = pState->Speed; + m_iGrooveIndex = -1; + } +} + /*! \brief Obtains a human-readable form of a channel state object. \warning The output of this method is neither guaranteed nor required to match that of CChannelHandler::GetStateString. @@ -1858,10 +1866,23 @@ void CSoundGen::ResetTempo() m_iTempoAccum = 0; - if (theApp.GetSettings()->General.bRetrieveChanState) // // // - ApplyGlobalState(); - // Legacy behavior + if (theApp.GetSettings()->General.bRetrieveChanState) { // !! !! + // Calling on ApplyGlobalState() causes crackly audio on FDS + // May have something to do with conflicting stFullState pointers? haven't investigated + // So we do a reduced version here where we don't update the channel handlers. + int Frame = IsPlaying() ? GetPlayerFrame() : m_pTrackerView->GetSelectedFrame(); + int Row = IsPlaying() ? GetPlayerRow() : m_pTrackerView->GetSelectedRow(); + if (stFullState *State = m_pDocument->RetrieveSoundState(GetPlayerTrack(), Frame, Row, -1)) { + ApplyGlobalTempoState(State); + // Set m_iSpeed to avoid division by zero in SetupSpeed() + if (m_pDocument->GetSongGroove(m_iPlayTrack) && m_pDocument->GetGroove(m_iSpeed) == NULL) + m_iSpeed = DEFAULT_SPEED; + m_iLastHighlight = m_pDocument->GetHighlightAt(GetPlayerTrack(), Frame, Row).First; + delete State; + } + } else { + // Legacy behavior if (m_pDocument->GetSongGroove(m_iPlayTrack) && m_pDocument->GetGroove(m_iSpeed) != NULL) { // // // m_iGrooveIndex = m_iSpeed; m_iGroovePosition = 0; @@ -1873,8 +1894,8 @@ void CSoundGen::ResetTempo() if (m_pDocument->GetSongGroove(m_iPlayTrack)) m_iSpeed = DEFAULT_SPEED; } - SetupSpeed(); } + SetupSpeed(); m_bUpdateRow = false; } diff --git a/Source/SoundGen.h b/Source/SoundGen.h index 8b2e2377..810ad5f5 100644 --- a/Source/SoundGen.h +++ b/Source/SoundGen.h @@ -32,6 +32,7 @@ #include // // // #include "Common.h" #include "FamiTrackerTypes.h" +#include "ChannelState.h" // // // #include #include @@ -321,6 +322,7 @@ class CSoundGen : IAudioCallback void PlayerSkipTo(int Row); void ApplyGlobalState(); // // // + void ApplyGlobalTempoState(stFullState *pState); public: static const double NEW_VIBRATO_DEPTH[];