From 94eb8d2a7ff5ef9cc74a2cf6a293af2bd167bec7 Mon Sep 17 00:00:00 2001 From: sukibaby <163092272+sukibaby@users.noreply.github.com> Date: Tue, 4 Feb 2025 08:13:28 -0800 Subject: [PATCH] Vector based RageSoundMixBuffer Bringing in algorithm for std::copy, and vector for automatic memory management. Initializing the buffer with zeroes in the same operation as resizing the buffer. Going back to using an unsigned int for realsize, to prevent the buffer from becoming an unreasonably large size. The constructor and destructor can be empty since the vector's own destructor will take care of freeing allocated memory. The static_cast to an int in read(int16_t *pBuf) is changed to a static_cast to an int16_t, as audio data is expressed in 16 bit integers, and the fractional part is inherently rounded towards zero by truncation. --- src/RageSoundMixBuffer.cpp | 59 +++++++++++--------------------------- src/RageSoundMixBuffer.h | 42 +++++++++++---------------- 2 files changed, 32 insertions(+), 69 deletions(-) diff --git a/src/RageSoundMixBuffer.cpp b/src/RageSoundMixBuffer.cpp index 49f887ff20..84d571c504 100644 --- a/src/RageSoundMixBuffer.cpp +++ b/src/RageSoundMixBuffer.cpp @@ -1,29 +1,13 @@ #include "global.h" #include "RageSoundMixBuffer.h" -#include "RageUtil.h" #include #include -#include +#include +#include -RageSoundMixBuffer::RageSoundMixBuffer() -{ - m_pMixbuf = static_cast(std::malloc(BUF_SIZE * sizeof(float))); - if (m_pMixbuf == nullptr) - { - ASSERT_M(false, "Failed to allocate memory for the sound mixing buffer"); - } - m_iBufSize = BUF_SIZE; - std::memset(m_pMixbuf, 0, m_iBufSize * sizeof(float)); - m_iBufUsed = 0; - m_iOffset = 0; -} - - -RageSoundMixBuffer::~RageSoundMixBuffer() -{ - std::free(m_pMixbuf); -} +RageSoundMixBuffer::RageSoundMixBuffer() : m_iOffset(0) {} +RageSoundMixBuffer::~RageSoundMixBuffer() {} /* write() will start mixing iOffset samples into the buffer. Be careful; this is * measured in samples, not frames, so if the data is stereo, multiply by two. */ @@ -34,21 +18,10 @@ void RageSoundMixBuffer::SetWriteOffset( int iOffset ) void RageSoundMixBuffer::Extend(unsigned iSamples) { - const uint64_t realsize = static_cast(iSamples) + static_cast(m_iOffset); - if( m_iBufSize < realsize ) + const unsigned realsize = iSamples + m_iOffset; + if (m_pMixbuf.size() < realsize) { - m_pMixbuf = static_cast(std::realloc(m_pMixbuf, sizeof(float) * realsize)); - if (m_pMixbuf == nullptr) - { - ASSERT_M(false, "Failed to re-allocate memory for the sound mixing buffer."); - } - m_iBufSize = realsize; - } - - if( m_iBufUsed < realsize ) - { - std::memset(m_pMixbuf + m_iBufUsed, 0, (realsize - m_iBufUsed) * sizeof(float)); - m_iBufUsed = realsize; + m_pMixbuf.resize(realsize, 0.0f); } } @@ -61,7 +34,7 @@ void RageSoundMixBuffer::write( const float *pBuf, unsigned iSize, int iSourceSt Extend( iSize * iDestStride - (iDestStride-1) ); // Scale volume and add. - float *pDestBuf = m_pMixbuf+m_iOffset; + float *pDestBuf = &m_pMixbuf[m_iOffset]; while( iSize ) { @@ -74,27 +47,27 @@ void RageSoundMixBuffer::write( const float *pBuf, unsigned iSize, int iSourceSt void RageSoundMixBuffer::read( int16_t *pBuf ) { - for( unsigned iPos = 0; iPos < m_iBufUsed; ++iPos ) + for (unsigned iPos = 0; iPos < m_pMixbuf.size(); ++iPos) { float iOut = m_pMixbuf[iPos]; iOut = std::clamp( iOut, -1.0f, +1.0f ); - pBuf[iPos] = static_cast((iOut * 32767) + 0.5); + pBuf[iPos] = static_cast(iOut * INT16_MAX); } - m_iBufUsed = 0; + m_pMixbuf.clear(); } void RageSoundMixBuffer::read( float *pBuf ) { - std::memcpy( pBuf, m_pMixbuf, m_iBufUsed * sizeof(float) ); - m_iBufUsed = 0; + std::copy(m_pMixbuf.begin(), m_pMixbuf.end(), pBuf); + m_pMixbuf.clear(); } void RageSoundMixBuffer::read_deinterlace( float **pBufs, int channels ) { - for( unsigned i = 0; i < m_iBufUsed / channels; ++i ) - for( int ch = 0; ch < channels; ++ch ) + for (unsigned i = 0; i < m_pMixbuf.size() / channels; ++i) + for (int ch = 0; ch < channels; ++ch) pBufs[ch][i] = m_pMixbuf[channels * i + ch]; - m_iBufUsed = 0; + m_pMixbuf.clear(); } /* diff --git a/src/RageSoundMixBuffer.h b/src/RageSoundMixBuffer.h index b2d1b078b1..d080cc92bb 100644 --- a/src/RageSoundMixBuffer.h +++ b/src/RageSoundMixBuffer.h @@ -1,40 +1,30 @@ -/* RageSoundMixBuffer - Simple audio mixing. */ - -#ifndef RAGE_SOUND_MIX_BUFFER_H -#define RAGE_SOUND_MIX_BUFFER_H +#ifndef RAGESOUNDMIXBUFFER_H +#define RAGESOUNDMIXBUFFER_H +#include #include -class RageSoundMixBuffer -{ +class RageSoundMixBuffer { public: RageSoundMixBuffer(); ~RageSoundMixBuffer(); - // See how many samples we can stuff into 2MB. - static constexpr size_t BUF_SIZE = 2 * 1024 * 1024 / sizeof(float); - - // Mix the given buffer of samples. - void write( const float *pBuf, unsigned iSize, int iSourceStride = 1, int iDestStride = 1 ); - - // Extend the buffer as if write() was called with a buffer of silence. - void Extend( unsigned iSamples ); - - void read( int16_t *pBuf ); - void read( float *pBuf ); - void read_deinterlace( float **pBufs, int channels ); - float *read() { return m_pMixbuf; } - unsigned size() const { return m_iBufUsed; } - void SetWriteOffset( int iOffset ); + void SetWriteOffset(int iOffset); + void Extend(unsigned iSamples); + void write(const float* pBuf, unsigned iSize, int iSourceStride = 1, int iDestStride = 1); + void read(int16_t* pBuf); + void read(float* pBuf); + void read_deinterlace(float** pBufs, int channels); + inline int64_t size() const { return m_iBufUsed; } private: - float *m_pMixbuf; - uint64_t m_iBufSize; // actual allocated samples - uint64_t m_iBufUsed; // used samples - int m_iOffset; + std::vector m_pMixbuf; + int64_t m_iBufSize; + int64_t m_iBufUsed; + int64_t m_iOffset; }; -#endif +#endif // RAGESOUNDMIXBUFFER_H /* * Copyright (c) 2002-2004 Glenn Maynard