From 1bd23712e1d99d5693e62d08ba4d96795dffa44f Mon Sep 17 00:00:00 2001 From: graemephi Date: Sat, 3 Aug 2024 23:08:20 +0100 Subject: [PATCH] SpeedChange: Add mid side encoding Also some TWEAKS to make it SOUND GOOD --- .../Sound/RageSoundReader_SpeedChange.cpp | 46 +++++++++++++++++-- .../Sound/RageSoundReader_SpeedChange.h | 3 ++ 2 files changed, 46 insertions(+), 3 deletions(-) diff --git a/src/RageUtil/Sound/RageSoundReader_SpeedChange.cpp b/src/RageUtil/Sound/RageSoundReader_SpeedChange.cpp index f7221267b6..8258fd3a40 100644 --- a/src/RageUtil/Sound/RageSoundReader_SpeedChange.cpp +++ b/src/RageUtil/Sound/RageSoundReader_SpeedChange.cpp @@ -1,14 +1,17 @@ #include "Etterna/Globals/global.h" +#include "Etterna/Singletons/PrefsManager.h" #include "RageSoundReader_SpeedChange.h" #include "RageUtil/Utils/RageUtil.h" #include -static const int WINDOW_SIZE_MS = 30; +static Preference g_StepmaniaUnpitchRates("StepmaniaUnpitchRates", false); RageSoundReader_SpeedChange::RageSoundReader_SpeedChange( RageSoundReader* pSource) : RageSoundReader_Filter(pSource) + , m_iWindowSize(g_StepmaniaUnpitchRates ? 30 : 70) + , m_bMidSideEncoding(!g_StepmaniaUnpitchRates) { m_Channels.resize(pSource->GetNumChannels()); m_fSpeedRatio = m_fTrailingSpeedRatio = 1.0f; @@ -31,7 +34,7 @@ RageSoundReader_SpeedChange::SetSpeedRatio(float fRatio) int RageSoundReader_SpeedChange::GetWindowSizeFrames() const { - return (WINDOW_SIZE_MS * GetSampleRate()) / 1000; + return (m_iWindowSize * GetSampleRate()) / 1000; } void @@ -121,6 +124,22 @@ RageSoundReader_SpeedChange::FillData(int iMaxFrames) } delete[] pTempBuffer; + if (m_Channels.size() == 2 && m_bMidSideEncoding) { + // Encode as mid/side + ChannelInfo& left = m_Channels[0]; + ChannelInfo& right = m_Channels[1]; + float* pLeft = &left.m_DataBuffer[m_iDataBufferAvailFrames]; + float* pRight = &right.m_DataBuffer[m_iDataBufferAvailFrames]; + for (int j = 0; j < iGotFrames; ++j) { + float mid = *pLeft + *pRight; + float side = *pLeft - *pRight; + *pLeft = mid; + *pRight = side; + pLeft++; + pRight++; + } + } + m_iDataBufferAvailFrames += iGotFrames; } return m_iDataBufferAvailFrames; @@ -288,17 +307,38 @@ RageSoundReader_SpeedChange::Read(float* pBuf, int iFrames) int iFramesRead = iFramesAvail; int iWindowSizeFrames = GetWindowSizeFrames(); + float *pBufLeftRight = pBuf; + while (iFramesAvail--) { for (size_t i = 0; i < m_Channels.size(); ++i) { ChannelInfo& c = m_Channels[i]; float i1 = c.m_DataBuffer[c.m_iCorrelatedPos + m_iPos]; float i2 = c.m_DataBuffer[c.m_iLastCorrelatedPos + m_iPos]; - *pBuf++ = SCALE(m_iPos, 0, iWindowSizeFrames, i2, i1); + if (m_bMidSideEncoding) { + float t = (float)m_iPos / (float)iWindowSizeFrames; + // Approx quick cosine fade to minimise swhipping sounds on percussion + t = 1.0f - t*t*(3 - 2*t); + t = 1.0f - t*t*t*t; + *pBuf++ = lerp(t, i2, i1); + } else { + *pBuf++ = SCALE(m_iPos, 0, iWindowSizeFrames, i2, i1); + } } ++m_iPos; } + if (m_Channels.size() == 2 && m_bMidSideEncoding) { + // Decode back to left/right + while (pBufLeftRight != pBuf) { + float left = pBufLeftRight[0] + pBufLeftRight[1]; + float right = pBufLeftRight[0] - pBufLeftRight[1]; + pBufLeftRight[0] = 0.5f * left; + pBufLeftRight[1] = 0.5f * right; + pBufLeftRight += 2; + } + } + return iFramesRead; } } diff --git a/src/RageUtil/Sound/RageSoundReader_SpeedChange.h b/src/RageUtil/Sound/RageSoundReader_SpeedChange.h index 52e2067bcd..25f9f637bd 100644 --- a/src/RageUtil/Sound/RageSoundReader_SpeedChange.h +++ b/src/RageUtil/Sound/RageSoundReader_SpeedChange.h @@ -60,6 +60,9 @@ class RageSoundReader_SpeedChange : public RageSoundReader_Filter float m_fSpeedRatio; float m_fTrailingSpeedRatio; float m_fErrorFrames; + + const int m_iWindowSize; + const bool m_bMidSideEncoding; }; #endif