Switch to floating-point sound internally.
This allows us to change the volume of sounds in filters ("volume",
"fade" properties) without quantizing the audio prematurely. Previously,
we had a hack to apply volume changes as a mixing-time step. This
can be done at any point in the filter chain now.
This also means we only need to worry about clipping at the very
last mixing step, instead of at every place we change sound.
Dithering for 16-bit audio and more intelligent gain control
is possible, as we have full-resolution, unclipped sound at the
mixing phase.
We support high resolution source sounds; both Vorbis and MAD
supply more than 16 bits.
Several filters, such as resampling, are easier to implement as
floats; these no longer need to convert back and forth.
Negatives:
- More memory use. The main case of this is in RageSoundReader_Preload,
which will be fixed: we can preload in 16-bit without losing most of the
above.
- Some extra overhead for accessing more memory.
This commit is contained in:
@@ -14,7 +14,6 @@ RageSoundMixBuffer::RageSoundMixBuffer()
|
||||
m_iBufSize = m_iBufUsed = 0;
|
||||
m_pMixbuf = NULL;
|
||||
m_iOffset = 0;
|
||||
SetVolume( 1.0f );
|
||||
#ifdef USE_VEC
|
||||
g_bVector = Vector::CheckForVector();
|
||||
#endif
|
||||
@@ -25,11 +24,6 @@ RageSoundMixBuffer::~RageSoundMixBuffer()
|
||||
free( m_pMixbuf );
|
||||
}
|
||||
|
||||
void RageSoundMixBuffer::SetVolume( float f )
|
||||
{
|
||||
m_iVolumeFactor = int(256*f);
|
||||
}
|
||||
|
||||
/* 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. */
|
||||
void RageSoundMixBuffer::SetWriteOffset( int iOffset )
|
||||
@@ -42,18 +36,18 @@ void RageSoundMixBuffer::Extend( unsigned iSamples )
|
||||
const unsigned realsize = iSamples+m_iOffset;
|
||||
if( m_iBufSize < realsize )
|
||||
{
|
||||
m_pMixbuf = (int32_t *) realloc( m_pMixbuf, sizeof(int32_t) * realsize );
|
||||
m_pMixbuf = (float *) realloc( m_pMixbuf, sizeof(float) * realsize );
|
||||
m_iBufSize = realsize;
|
||||
}
|
||||
|
||||
if( m_iBufUsed < realsize )
|
||||
{
|
||||
memset( m_pMixbuf + m_iBufUsed, 0, (realsize - m_iBufUsed) * sizeof(int32_t) );
|
||||
memset( m_pMixbuf + m_iBufUsed, 0, (realsize - m_iBufUsed) * sizeof(float) );
|
||||
m_iBufUsed = realsize;
|
||||
}
|
||||
}
|
||||
|
||||
void RageSoundMixBuffer::write( const int16_t *pBuf, unsigned iSize, int iSourceStride, int iDestStride )
|
||||
void RageSoundMixBuffer::write( const float *pBuf, unsigned iSize, int iSourceStride, int iDestStride )
|
||||
{
|
||||
if( iSize == 0 )
|
||||
return;
|
||||
@@ -63,17 +57,19 @@ void RageSoundMixBuffer::write( const int16_t *pBuf, unsigned iSize, int iSource
|
||||
Extend( iSize * iDestStride - (iDestStride-1) );
|
||||
|
||||
/* Scale volume and add. */
|
||||
int32_t *pDestBuf = m_pMixbuf+m_iOffset;
|
||||
#ifdef USE_VEC
|
||||
float *pDestBuf = m_pMixbuf+m_iOffset;
|
||||
|
||||
/* #ifdef USE_VEC
|
||||
if( g_bVector && iSourceStride == 1 && iDestStride == 1 )
|
||||
{
|
||||
Vector::FastSoundWrite( pDestBuf, pBuf, iSize, m_iVolumeFactor );
|
||||
Vector::FastSoundWrite( pDestBuf, pBuf, iSize, 1 );
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#endif */
|
||||
|
||||
while( iSize )
|
||||
{
|
||||
*pDestBuf += *pBuf * m_iVolumeFactor;
|
||||
*pDestBuf += *pBuf;
|
||||
pBuf += iSourceStride;
|
||||
pDestBuf += iDestStride;
|
||||
--iSize;
|
||||
@@ -92,8 +88,9 @@ void RageSoundMixBuffer::read( int16_t *pBuf )
|
||||
#endif
|
||||
for( unsigned iPos = 0; iPos < m_iBufUsed; ++iPos )
|
||||
{
|
||||
int32_t iOut = (m_pMixbuf[iPos]) / 256;
|
||||
pBuf[iPos] = (int16_t) clamp( iOut, -32768, 32767 );
|
||||
float iOut = m_pMixbuf[iPos];
|
||||
iOut = clamp( iOut, -1.0f, +1.0f );
|
||||
pBuf[iPos] = lrintf(iOut * 32767);
|
||||
}
|
||||
m_iBufUsed = 0;
|
||||
}
|
||||
@@ -108,11 +105,9 @@ void RageSoundMixBuffer::read( float *pBuf )
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
const int iMinimum = -32768 * 256;
|
||||
const int iMaximum = 32767 * 256;
|
||||
|
||||
for( unsigned pos = 0; pos < m_iBufUsed; ++pos )
|
||||
pBuf[pos] = SCALE( (float)m_pMixbuf[pos], iMinimum, iMaximum, -1.0f, 1.0f );
|
||||
pBuf[pos] = m_pMixbuf[pos];
|
||||
|
||||
m_iBufUsed = 0;
|
||||
}
|
||||
|
||||
@@ -10,22 +10,21 @@ public:
|
||||
~RageSoundMixBuffer();
|
||||
|
||||
/* Mix the given buffer of samples. */
|
||||
void write( const int16_t *buf, unsigned size, int iSourceStride = 1, int iDestStride = 1 );
|
||||
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 );
|
||||
float *read() { return m_pMixbuf; }
|
||||
unsigned size() const { return m_iBufUsed; }
|
||||
void SetVolume( float f );
|
||||
void SetWriteOffset( int iOffset );
|
||||
|
||||
private:
|
||||
int32_t *m_pMixbuf;
|
||||
float *m_pMixbuf;
|
||||
unsigned m_iBufSize; /* actual allocated samples */
|
||||
unsigned m_iBufUsed; /* used samples */
|
||||
int m_iVolumeFactor; /* vol * 256 */
|
||||
int m_iOffset;
|
||||
};
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
REGISTER_CLASS_TRAITS( RageSoundReader, pCopy->Copy() );
|
||||
|
||||
/* Read(), handling the STREAM_LOOPED and empty return cases. */
|
||||
int RageSoundReader::RetriedRead( int16_t *pBuffer, int iFrames, int *iSourceFrame, float *fRate )
|
||||
int RageSoundReader::RetriedRead( float *pBuffer, int iFrames, int *iSourceFrame, float *fRate )
|
||||
{
|
||||
if( iFrames == 0 )
|
||||
return 0;
|
||||
|
||||
@@ -9,7 +9,7 @@ public:
|
||||
virtual int GetLength() const = 0; /* ms */
|
||||
virtual int GetLength_Fast() const { return GetLength(); } /* ms */
|
||||
virtual int SetPosition( int iSample ) = 0;
|
||||
virtual int Read( int16_t *pBuf, int iFrames ) = 0;
|
||||
virtual int Read( float *pBuf, int iFrames ) = 0;
|
||||
virtual ~RageSoundReader() { }
|
||||
virtual RageSoundReader *Copy() const = 0;
|
||||
virtual int GetSampleRate() const = 0;
|
||||
@@ -40,7 +40,7 @@ public:
|
||||
virtual float GetStreamToSourceRatio() const = 0;
|
||||
|
||||
virtual RString GetError() const = 0;
|
||||
int RetriedRead( int16_t *pBuffer, int iFrames, int *iSourceFrame = NULL, float *fRate = NULL );
|
||||
int RetriedRead( float *pBuffer, int iFrames, int *iSourceFrame = NULL, float *fRate = NULL );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -299,7 +299,7 @@ float RageSoundReader_Chain::GetStreamToSourceRatio() const
|
||||
|
||||
/* As we iterate through the sound tree, we'll find that we need data from different
|
||||
* sounds; a sound may be needed by more than one other sound. */
|
||||
int RageSoundReader_Chain::Read( int16_t *pBuffer, int iFrames )
|
||||
int RageSoundReader_Chain::Read( float *pBuffer, int iFrames )
|
||||
{
|
||||
while( m_iNextSound < m_aSounds.size() && m_iCurrentFrame == m_aSounds[m_iNextSound].GetOffsetFrame(m_iActualSampleRate) )
|
||||
{
|
||||
@@ -339,14 +339,14 @@ int RageSoundReader_Chain::Read( int16_t *pBuffer, int iFrames )
|
||||
{
|
||||
/* If we have more sounds ahead of us, pretend we read the entire block, since
|
||||
* there's silence in between. Otherwise, we're at EOF. */
|
||||
memset( pBuffer, 0, iFrames * m_iChannels * sizeof(int16_t) );
|
||||
memset( pBuffer, 0, iFrames * m_iChannels * sizeof(float) );
|
||||
m_iCurrentFrame += iFrames;
|
||||
return iFrames;
|
||||
}
|
||||
|
||||
RageSoundMixBuffer mix;
|
||||
/* Read iFrames from each sound. */
|
||||
int16_t Buffer[2048];
|
||||
float Buffer[2048];
|
||||
iFrames = min( iFrames, (int) (ARRAYLEN(Buffer) / m_iChannels) );
|
||||
for( unsigned i = 0; i < m_apActiveSounds.size(); )
|
||||
{
|
||||
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
int GetLength() const;
|
||||
int GetLength_Fast() const;
|
||||
int SetPosition( int iFrame );
|
||||
int Read( int16_t *pBuf, int iFrames );
|
||||
int Read( float *pBuf, int iFrames );
|
||||
int GetSampleRate() const { return m_iActualSampleRate; }
|
||||
unsigned GetNumChannels() const { return m_iChannels; }
|
||||
bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
@@ -77,7 +77,7 @@ public:
|
||||
|
||||
/* m_sBuffer[0] corresponds to frame number m_iBufferPositionFrames. */
|
||||
int m_iBufferPositionFrames;
|
||||
vector<int16_t> m_sBuffer;
|
||||
vector<float> m_sBuffer;
|
||||
};
|
||||
|
||||
int RageSoundReader_Split::GetLength() const { return m_pImpl->m_pSource->GetLength(); }
|
||||
@@ -132,13 +132,13 @@ bool RageSoundReader_Split::SetProperty( const RString &sProperty, float fValue
|
||||
return m_pImpl->m_pSource->SetProperty( sProperty, fValue );
|
||||
}
|
||||
|
||||
int RageSoundReader_Split::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_Split::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
m_iRequestFrames = iFrames;
|
||||
int iRet = m_pImpl->ReadBuffer();
|
||||
|
||||
int iSamplesAvailable = m_pImpl->m_sBuffer.size();
|
||||
const int16_t *pSrc = &m_pImpl->m_sBuffer[0];
|
||||
const float *pSrc = &m_pImpl->m_sBuffer[0];
|
||||
if( m_pImpl->m_iBufferPositionFrames < m_iPositionFrame )
|
||||
{
|
||||
int iSkipFrames = m_iPositionFrame - m_pImpl->m_iBufferPositionFrames;
|
||||
|
||||
@@ -17,7 +17,7 @@ public:
|
||||
virtual int GetLength() const;
|
||||
virtual int GetLength_Fast() const;
|
||||
virtual int SetPosition( int iFrame );
|
||||
virtual int Read( int16_t *pBuf, int iFrames );
|
||||
virtual int Read( float *pBuf, int iFrames );
|
||||
virtual int GetSampleRate() const;
|
||||
virtual unsigned GetNumChannels() const;
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
@@ -48,7 +48,7 @@ int RageSoundReader_Extend::GetEndFrame() const
|
||||
return m_iStartFrames + m_iLengthFrames;
|
||||
}
|
||||
|
||||
int RageSoundReader_Extend::GetData( int16_t *pBuffer, int iFrames )
|
||||
int RageSoundReader_Extend::GetData( float *pBuffer, int iFrames )
|
||||
{
|
||||
int iFramesToRead = iFrames;
|
||||
if( m_iLengthFrames != -1 )
|
||||
@@ -66,7 +66,7 @@ int RageSoundReader_Extend::GetData( int16_t *pBuffer, int iFrames )
|
||||
iFramesToRead = min( iFramesToRead, -m_iPositionFrames );
|
||||
|
||||
m_iPositionFrames += iFramesToRead;
|
||||
memset( pBuffer, 0, iFramesToRead * sizeof(int16_t) * this->GetNumChannels() );
|
||||
memset( pBuffer, 0, iFramesToRead * sizeof(float) * this->GetNumChannels() );
|
||||
return iFramesToRead;
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ int RageSoundReader_Extend::GetData( int16_t *pBuffer, int iFrames )
|
||||
return iRet;
|
||||
}
|
||||
|
||||
int RageSoundReader_Extend::Read( int16_t *pBuffer, int iFrames )
|
||||
int RageSoundReader_Extend::Read( float *pBuffer, int iFrames )
|
||||
{
|
||||
int iFramesRead = GetData( pBuffer, iFrames );
|
||||
if( iFramesRead == RageSoundReader::END_OF_FILE )
|
||||
@@ -91,7 +91,7 @@ int RageSoundReader_Extend::Read( int16_t *pBuffer, int iFrames )
|
||||
iFramesRead = iFrames;
|
||||
if( m_StopMode != M_CONTINUE )
|
||||
iFramesRead = min( GetEndFrame() - m_iPositionFrames, iFramesRead );
|
||||
memset( pBuffer, 0, iFramesRead * sizeof(int16_t) * this->GetNumChannels() );
|
||||
memset( pBuffer, 0, iFramesRead * sizeof(float) * this->GetNumChannels() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ class RageSoundReader_Extend: public RageSoundReader_Filter
|
||||
public:
|
||||
RageSoundReader_Extend( RageSoundReader *pSource );
|
||||
virtual int SetPosition( int iFrame );
|
||||
virtual int Read( int16_t *pBuffer, int iFrames );
|
||||
virtual int Read( float *pBuffer, int iFrames );
|
||||
virtual int GetNextSourceFrame() const;
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
@@ -19,7 +19,7 @@ public:
|
||||
|
||||
private:
|
||||
int GetEndFrame() const;
|
||||
int GetData( int16_t *pBuffer, int iFrames );
|
||||
int GetData( float *pBuffer, int iFrames );
|
||||
|
||||
int m_iPositionFrames;
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
virtual int GetLength() const { return m_pSource->GetLength(); }
|
||||
virtual int GetLength_Fast() const { return m_pSource->GetLength_Fast(); }
|
||||
virtual int SetPosition( int iFrame ) { return m_pSource->SetPosition( iFrame ); }
|
||||
virtual int Read( int16_t *pBuf, int iFrames ) { return m_pSource->Read( pBuf, iFrames ); }
|
||||
virtual int Read( float *pBuf, int iFrames ) { return m_pSource->Read( pBuf, iFrames ); }
|
||||
virtual int GetSampleRate() const { return m_pSource->GetSampleRate(); }
|
||||
virtual unsigned GetNumChannels() const { return m_pSource->GetNumChannels(); }
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue ) { return m_pSource->SetProperty( sProperty, fValue ); }
|
||||
|
||||
@@ -204,7 +204,8 @@ struct madlib_t
|
||||
bitrate = 0;
|
||||
}
|
||||
|
||||
uint8_t inbuf[16384], outbuf[8192];
|
||||
uint8_t inbuf[16384];
|
||||
float outbuf[8192];
|
||||
int outpos;
|
||||
unsigned outleft;
|
||||
|
||||
@@ -268,7 +269,7 @@ struct madlib_t
|
||||
|
||||
|
||||
|
||||
static signed int scale(mad_fixed_t sample)
|
||||
static float scale(mad_fixed_t sample)
|
||||
{
|
||||
/* round */
|
||||
sample += (1L << (MAD_F_FRACBITS - 16));
|
||||
@@ -279,8 +280,7 @@ static signed int scale(mad_fixed_t sample)
|
||||
else if (sample < -MAD_F_ONE)
|
||||
sample = -MAD_F_ONE;
|
||||
|
||||
/* quantize */
|
||||
return sample >> (MAD_F_FRACBITS + 1 - 16);
|
||||
return (double) sample / (1<<MAD_F_FRACBITS);
|
||||
}
|
||||
|
||||
static int get_this_frame_byte( const madlib_t *mad )
|
||||
@@ -542,9 +542,9 @@ void RageSoundReader_MP3::synth_output()
|
||||
{
|
||||
for(int chan = 0; chan < this->Channels; ++chan)
|
||||
{
|
||||
short Sample = (short) scale(mad->Synth.pcm.samples[chan][i]);
|
||||
*((short *) (mad->outbuf + mad->outleft)) = Sample;
|
||||
mad->outleft += 2;
|
||||
float Sample = scale(mad->Synth.pcm.samples[chan][i]);
|
||||
mad->outbuf[mad->outleft] = Sample;
|
||||
++mad->outleft;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -743,7 +743,7 @@ static void mono_to_stereo( char *dst, const char *src, unsigned len )
|
||||
}
|
||||
}
|
||||
|
||||
int RageSoundReader_MP3::Read( int16_t *buf, int iFrames )
|
||||
int RageSoundReader_MP3::Read( float *buf, int iFrames )
|
||||
{
|
||||
int iFramesWritten = 0;
|
||||
|
||||
@@ -751,17 +751,17 @@ int RageSoundReader_MP3::Read( int16_t *buf, int iFrames )
|
||||
{
|
||||
if( mad->outleft > 0 )
|
||||
{
|
||||
int iFramesToCopy = min( iFrames, int(mad->outleft / (sizeof(int16_t) * GetNumChannels())) );
|
||||
int iFramesToCopy = min( iFrames, int(mad->outleft / GetNumChannels()) );
|
||||
const int iSamplesToCopy = iFramesToCopy * GetNumChannels();
|
||||
const int iBytesToCopy = iSamplesToCopy * sizeof(int16_t);
|
||||
const int iBytesToCopy = iSamplesToCopy * sizeof(float);
|
||||
|
||||
memcpy( buf, mad->outbuf + mad->outpos, iBytesToCopy );
|
||||
|
||||
buf += iSamplesToCopy;
|
||||
iFrames -= iFramesToCopy;
|
||||
iFramesWritten += iFramesToCopy;
|
||||
mad->outpos += iBytesToCopy;
|
||||
mad->outleft -= iBytesToCopy;
|
||||
mad->outpos += iSamplesToCopy;
|
||||
mad->outleft -= iSamplesToCopy;
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -936,10 +936,9 @@ int RageSoundReader_MP3::SetPosition_hard( int iFrame )
|
||||
|
||||
int samples = mad_timer_count( skip, (mad_units) SampleRate );
|
||||
|
||||
/* Skip 'samples' samples; each sample is 2 * channels bytes, since
|
||||
* we're currently always using AUDIO_S16SYS. */
|
||||
mad->outpos = samples * 2 * this->Channels;
|
||||
mad->outleft -= samples * 2 * this->Channels;
|
||||
/* Skip 'samples' samples. */
|
||||
mad->outpos = samples * this->Channels;
|
||||
mad->outleft -= samples * this->Channels;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1052,7 +1051,7 @@ bool RageSoundReader_MP3::SetProperty( const RString &sProperty, float fValue )
|
||||
int RageSoundReader_MP3::GetNextSourceFrame() const
|
||||
{
|
||||
int iFrame = mad_timer_count( mad->Timer, mad_units(mad->Frame.header.samplerate) );
|
||||
iFrame += mad->outpos / (sizeof(int16_t) * this->Channels);
|
||||
iFrame += mad->outpos / this->Channels;
|
||||
return iFrame;
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
int GetLength() const { return GetLengthConst(false); }
|
||||
int GetLength_Fast() const { return GetLengthConst(true); }
|
||||
int SetPosition( int iSample );
|
||||
int Read( int16_t *pBuf, int iFrames );
|
||||
int Read( float *pBuf, int iFrames );
|
||||
unsigned GetNumChannels() const { return Channels; }
|
||||
int GetSampleRate() const { return SampleRate; }
|
||||
int GetNextSourceFrame() const;
|
||||
|
||||
@@ -9,7 +9,7 @@ RageSoundReader_Pan::RageSoundReader_Pan( RageSoundReader *pSource ):
|
||||
}
|
||||
|
||||
|
||||
int RageSoundReader_Pan::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_Pan::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
iFrames = m_pSource->Read( pBuf, iFrames );
|
||||
if( iFrames < 0 )
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
RageSoundReader_Pan( RageSoundReader *pSource );
|
||||
RageSoundReader_Pan *Copy() const { return new RageSoundReader_Pan(*this); }
|
||||
virtual unsigned GetNumChannels() const;
|
||||
virtual int Read( int16_t *pBuf, int iFrames );
|
||||
virtual int Read( float *pBuf, int iFrames );
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
private:
|
||||
|
||||
@@ -40,7 +40,7 @@ RageSoundReader_PitchChange::RageSoundReader_PitchChange( const RageSoundReader_
|
||||
m_fLastSetPitchRatio = cpy.m_fLastSetPitchRatio;
|
||||
}
|
||||
|
||||
int RageSoundReader_PitchChange::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_PitchChange::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
/* m_pSpeedChange->NextReadWillStep is true if speed changes will be applied
|
||||
* immediately on the next Read(). When this is true, apply the ratio to the
|
||||
|
||||
@@ -13,7 +13,7 @@ public:
|
||||
RageSoundReader_PitchChange( RageSoundReader *pSource );
|
||||
RageSoundReader_PitchChange( const RageSoundReader_PitchChange &cpy );
|
||||
|
||||
virtual int Read( int16_t *pBuf, int iFrames );
|
||||
virtual int Read( float *pBuf, int iFrames );
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
void SetSpeedRatio( float fRatio ) { m_fSpeedRatio = fRatio; }
|
||||
|
||||
@@ -15,7 +15,7 @@ RageSoundReader_PostBuffering::RageSoundReader_PostBuffering( RageSoundReader *p
|
||||
}
|
||||
|
||||
|
||||
int RageSoundReader_PostBuffering::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_PostBuffering::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
iFrames = m_pSource->Read( pBuf, iFrames );
|
||||
if( iFrames < 0 )
|
||||
|
||||
@@ -10,7 +10,7 @@ class RageSoundReader_PostBuffering: public RageSoundReader_Filter
|
||||
public:
|
||||
RageSoundReader_PostBuffering( RageSoundReader *pSource );
|
||||
RageSoundReader_PostBuffering *Copy() const { return new RageSoundReader_PostBuffering(*this); }
|
||||
virtual int Read( int16_t *pBuf, int iFrames );
|
||||
virtual int Read( float *pBuf, int iFrames );
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
private:
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
#include "RageSoundReader_Preload.h"
|
||||
#include "RageUtil.h"
|
||||
|
||||
#define samplesize (sizeof(int16_t) * m_iChannels) /* 16-bit */
|
||||
#define samplesize (sizeof(float) * m_iChannels) /* 16-bit */
|
||||
|
||||
/* If a sound is smaller than this, we'll load it entirely into memory. */
|
||||
const unsigned max_prebuf_size = 1024*256;
|
||||
@@ -61,7 +61,7 @@ bool RageSoundReader_Preload::Open( RageSoundReader *pSource )
|
||||
if( pSource->GetStreamToSourceRatio() != m_fRate )
|
||||
return false; /* Don't bother trying to preload it. */
|
||||
|
||||
int16_t buffer[1024];
|
||||
float buffer[1024];
|
||||
int iCnt = pSource->Read( buffer, ARRAYSIZE(buffer) / m_iChannels );
|
||||
|
||||
if( iCnt == END_OF_FILE )
|
||||
@@ -110,7 +110,7 @@ int RageSoundReader_Preload::GetNextSourceFrame() const
|
||||
return lrintf(m_iPosition * m_fRate);
|
||||
}
|
||||
|
||||
int RageSoundReader_Preload::Read( int16_t *pBuffer, int iFrames )
|
||||
int RageSoundReader_Preload::Read( float *pBuffer, int iFrames )
|
||||
{
|
||||
const int iSizeFrames = m_Buffer->size() / samplesize;
|
||||
const int iFramesAvail = iSizeFrames - m_iPosition;
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
int GetLength() const;
|
||||
int GetLength_Fast() const;
|
||||
int SetPosition( int iFrame );
|
||||
int Read( int16_t *pBuffer, int iLength );
|
||||
int Read( float *pBuffer, int iLength );
|
||||
int GetSampleRate() const { return m_iSampleRate; }
|
||||
unsigned GetNumChannels() const { return m_iChannels; }
|
||||
int GetNextSourceFrame() const;
|
||||
|
||||
@@ -647,7 +647,7 @@ int RageSoundReader_Resample_Good::SetPosition( int iFrame )
|
||||
return m_pSource->SetPosition( iFrame );
|
||||
}
|
||||
|
||||
int RageSoundReader_Resample_Good::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_Resample_Good::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
int iChannels = m_apResamplers.size();
|
||||
|
||||
@@ -663,7 +663,7 @@ int RageSoundReader_Resample_Good::Read( int16_t *pBuf, int iFrames )
|
||||
|
||||
{
|
||||
int iFramesNeeded = m_apResamplers[0]->NumInputsForOutputSamples(iFrames);
|
||||
int16_t *pTmpBuf = (int16_t *) alloca( iFramesNeeded * sizeof(int16_t) * iChannels );
|
||||
float *pTmpBuf = (float *) alloca( iFramesNeeded * sizeof(float) * iChannels );
|
||||
ASSERT( pTmpBuf );
|
||||
int iFramesIn = m_pSource->Read( pTmpBuf, iFramesNeeded );
|
||||
if( iFramesIn < 0 )
|
||||
@@ -676,7 +676,7 @@ int RageSoundReader_Resample_Good::Read( int16_t *pBuf, int iFrames )
|
||||
for( int iChannel = 0; iChannel < iChannels; ++iChannel )
|
||||
{
|
||||
{
|
||||
int16_t *pBufIn = pTmpBuf + iChannel;
|
||||
float *pBufIn = pTmpBuf + iChannel;
|
||||
float *pBufOut = pFloatBuf;
|
||||
for( int i = 0; i < iSamplesIn; i += iChannels )
|
||||
*(pBufOut++) = (float) pBufIn[i];
|
||||
@@ -685,10 +685,10 @@ int RageSoundReader_Resample_Good::Read( int16_t *pBuf, int iFrames )
|
||||
int iGotFrames = m_apResamplers[iChannel]->Run( pFloatBuf, iFramesIn, pFloatOut, iFrames );
|
||||
ASSERT( iGotFrames <= iFrames );
|
||||
|
||||
int16_t *pBufOut = pBuf + iChannel;
|
||||
float *pBufOut = pBuf + iChannel;
|
||||
for( int i = 0; i < iGotFrames; ++i )
|
||||
{
|
||||
*pBufOut = int16_t(lrintf(clamp(pFloatOut[i], -32768, 32767)));
|
||||
*pBufOut = pFloatOut[i];
|
||||
pBufOut += iChannels;
|
||||
}
|
||||
if( iChannel == 0 )
|
||||
|
||||
@@ -15,7 +15,7 @@ public:
|
||||
RageSoundReader_Resample_Good( RageSoundReader *pSource, int iSampleRate );
|
||||
RageSoundReader_Resample_Good( const RageSoundReader_Resample_Good &cpy );
|
||||
int SetPosition( int iFrame );
|
||||
int Read( int16_t *pBuf, int iFrames );
|
||||
int Read( float *pBuf, int iFrames );
|
||||
virtual ~RageSoundReader_Resample_Good();
|
||||
RageSoundReader_Resample_Good *Copy() const;
|
||||
bool SetProperty( const RString &sProperty, float fValue );
|
||||
|
||||
@@ -44,7 +44,7 @@ void RageSoundReader_SpeedChange::Reset()
|
||||
m_fErrorFrames = 0;
|
||||
}
|
||||
|
||||
static int FindClosestMatch( const int16_t *pBuffer, int iBufferSize, const int16_t *pCorrelateBuffer, int iCorrelateBufferSize, int iStride )
|
||||
static int FindClosestMatch( const float *pBuffer, int iBufferSize, const float *pCorrelateBuffer, int iCorrelateBufferSize, int iStride )
|
||||
{
|
||||
if( iBufferSize <= iCorrelateBufferSize )
|
||||
return 0;
|
||||
@@ -55,20 +55,20 @@ static int FindClosestMatch( const int16_t *pBuffer, int iBufferSize, const int1
|
||||
|
||||
int iBufferDistanceToSearch = iBufferSize - iCorrelateBufferSize;
|
||||
int iBestOffset = 0;
|
||||
int iBestScore = 0;
|
||||
int fBestScore = 0;
|
||||
for( int i = 0; i < iBufferDistanceToSearch; i += iStride )
|
||||
{
|
||||
int iScore = 0;
|
||||
const int16_t *pFrames = pBuffer + i;
|
||||
float fScore = 0;
|
||||
const float *pFrames = pBuffer + i;
|
||||
for( int j = 0; j < iCorrelateBufferSize; j += iStride )
|
||||
{
|
||||
int iDiff = pFrames[j] - pCorrelateBuffer[j];
|
||||
iScore += abs(iDiff);
|
||||
float fDiff = pFrames[j] - pCorrelateBuffer[j];
|
||||
fScore += fabsf(fDiff);
|
||||
}
|
||||
|
||||
if( i == 0 || iScore < iBestScore )
|
||||
if( i == 0 || fScore < fBestScore )
|
||||
{
|
||||
iBestScore = iScore;
|
||||
fBestScore = fScore;
|
||||
iBestOffset = i;
|
||||
}
|
||||
}
|
||||
@@ -85,11 +85,11 @@ int RageSoundReader_SpeedChange::FillData( int iMaxFrames )
|
||||
while( iMaxFrames > 0 )
|
||||
{
|
||||
int iFramesToRead = iMaxFrames - m_iDataBufferAvailFrames;
|
||||
int iBytesToRead = iFramesToRead * m_Channels.size() * sizeof(int16_t);
|
||||
int iBytesToRead = iFramesToRead * m_Channels.size() * sizeof(float);
|
||||
if( iBytesToRead <= 0 )
|
||||
return m_iDataBufferAvailFrames;
|
||||
|
||||
int16_t *pTempBuffer = (int16_t *) alloca( iBytesToRead );
|
||||
float *pTempBuffer = (float *) alloca( iBytesToRead );
|
||||
int iGotFrames = m_pSource->Read( pTempBuffer, iFramesToRead );
|
||||
if( iGotFrames < 0 )
|
||||
{
|
||||
@@ -105,8 +105,8 @@ int RageSoundReader_SpeedChange::FillData( int iMaxFrames )
|
||||
if( (int) c.m_DataBuffer.size() < iMaxFrames )
|
||||
c.m_DataBuffer.resize( iMaxFrames );
|
||||
|
||||
const int16_t *pIn = pTempBuffer + i;
|
||||
int16_t *pOut = &c.m_DataBuffer[m_iDataBufferAvailFrames];
|
||||
const float *pIn = pTempBuffer + i;
|
||||
float *pOut = &c.m_DataBuffer[m_iDataBufferAvailFrames];
|
||||
for( int j = 0; j < iGotFrames; ++j )
|
||||
{
|
||||
*pOut = *pIn;
|
||||
@@ -133,7 +133,7 @@ void RageSoundReader_SpeedChange::EraseData( int iFramesToDelete )
|
||||
{
|
||||
ChannelInfo &c = m_Channels[i];
|
||||
if( iFramesToMove )
|
||||
memmove( &c.m_DataBuffer[0], &c.m_DataBuffer[iFramesToDelete], iFramesToMove * sizeof(int16_t) );
|
||||
memmove( &c.m_DataBuffer[0], &c.m_DataBuffer[iFramesToDelete], iFramesToMove * sizeof(float) );
|
||||
ASSERT( c.m_iCorrelatedPos >= iFramesToDelete );
|
||||
c.m_iCorrelatedPos -= iFramesToDelete;
|
||||
}
|
||||
@@ -233,7 +233,7 @@ int RageSoundReader_SpeedChange::GetCursorAvail() const
|
||||
return iCursorAvail;
|
||||
}
|
||||
|
||||
int RageSoundReader_SpeedChange::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_SpeedChange::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
while( 1 )
|
||||
{
|
||||
@@ -269,9 +269,9 @@ int RageSoundReader_SpeedChange::Read( int16_t *pBuf, int iFrames )
|
||||
for( size_t i = 0; i < m_Channels.size(); ++i )
|
||||
{
|
||||
ChannelInfo &c = m_Channels[i];
|
||||
int i1 = c.m_DataBuffer[c.m_iCorrelatedPos+m_iPos];
|
||||
int i2 = c.m_DataBuffer[c.m_iLastCorrelatedPos+m_iPos];
|
||||
*pBuf++ = int16_t( SCALE( m_iPos, 0, iWindowSizeFrames, i2, i1 ) );
|
||||
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 );
|
||||
}
|
||||
|
||||
++m_iPos;
|
||||
|
||||
@@ -11,7 +11,7 @@ public:
|
||||
RageSoundReader_SpeedChange( RageSoundReader *pSource );
|
||||
|
||||
virtual int SetPosition( int iFrame );
|
||||
virtual int Read( int16_t *pBuf, int iFrames );
|
||||
virtual int Read( float *pBuf, int iFrames );
|
||||
virtual RageSoundReader_SpeedChange *Copy() const { return new RageSoundReader_SpeedChange(*this); }
|
||||
virtual bool SetProperty( const RString &sProperty, float fValue );
|
||||
virtual int GetNextSourceFrame() const;
|
||||
@@ -40,7 +40,7 @@ protected:
|
||||
int m_iDataBufferAvailFrames;
|
||||
struct ChannelInfo
|
||||
{
|
||||
vector<int16_t> m_DataBuffer;
|
||||
vector<float> m_DataBuffer;
|
||||
int m_iCorrelatedPos;
|
||||
int m_iLastCorrelatedPos;
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ RageSoundReader_ThreadedBuffer::RageSoundReader_ThreadedBuffer( RageSoundReader
|
||||
m_iSampleRate = pSource->GetSampleRate();
|
||||
m_iChannels = pSource->GetNumChannels();
|
||||
|
||||
int iFrameSize = sizeof(int16_t) * this->GetNumChannels();
|
||||
int iFrameSize = sizeof(float) * this->GetNumChannels();
|
||||
m_DataBuffer.reserve( g_iStreamingBufferFrames * iFrameSize, iFrameSize );
|
||||
|
||||
m_bEOF = false;
|
||||
@@ -279,7 +279,7 @@ int RageSoundReader_ThreadedBuffer::FillBlock()
|
||||
{
|
||||
/* We own m_pSource, even after unlocking, because m_bFilling is true. */
|
||||
unsigned iBufSize;
|
||||
int16_t *pBuf = m_DataBuffer.get_write_pointer( &iBufSize );
|
||||
float *pBuf = m_DataBuffer.get_write_pointer( &iBufSize );
|
||||
ASSERT( (iBufSize % iSamplesPerFrame) == 0 );
|
||||
iGotFrames = m_pSource->RetriedRead( pBuf, min(g_iReadBlockSizeFrames, iBufSize / iSamplesPerFrame), &iNextSourceFrame, &fRate );
|
||||
}
|
||||
@@ -306,7 +306,7 @@ int RageSoundReader_ThreadedBuffer::FillBlock()
|
||||
return iGotFrames;
|
||||
}
|
||||
|
||||
int RageSoundReader_ThreadedBuffer::Read( int16_t *pBuffer, int iFrames )
|
||||
int RageSoundReader_ThreadedBuffer::Read( float *pBuffer, int iFrames )
|
||||
{
|
||||
if( !m_bEOF )
|
||||
EnableBuffering();
|
||||
|
||||
@@ -18,7 +18,7 @@ public:
|
||||
RageSoundReader_ThreadedBuffer *Copy() const { return new RageSoundReader_ThreadedBuffer(*this); }
|
||||
|
||||
virtual int SetPosition( int iFrame );
|
||||
virtual int Read( int16_t *pBuffer, int iLength );
|
||||
virtual int Read( float *pBuffer, int iLength );
|
||||
virtual int GetNextSourceFrame() const;
|
||||
|
||||
virtual int GetLength() const;
|
||||
@@ -46,7 +46,7 @@ private:
|
||||
int m_iSampleRate;
|
||||
int m_iChannels;
|
||||
|
||||
CircBuf<int16_t> m_DataBuffer;
|
||||
CircBuf<float> m_DataBuffer;
|
||||
|
||||
struct Mapping
|
||||
{
|
||||
|
||||
@@ -160,15 +160,15 @@ int RageSoundReader_Vorbisfile::SetPosition( int iFrame )
|
||||
return 1;
|
||||
}
|
||||
|
||||
int RageSoundReader_Vorbisfile::Read( int16_t *buf, int iFrames )
|
||||
int RageSoundReader_Vorbisfile::Read( float *buf, int iFrames )
|
||||
{
|
||||
int frames_read = 0;
|
||||
|
||||
while( iFrames && !eof )
|
||||
{
|
||||
const int bytes_per_frame = sizeof(int16_t)*channels;
|
||||
const int bytes_per_frame = sizeof(float)*channels;
|
||||
|
||||
int ret = 0;
|
||||
int iFramesRead = 0;
|
||||
|
||||
{
|
||||
int curofs = (int) ov_pcm_tell(vf);
|
||||
@@ -193,18 +193,20 @@ int RageSoundReader_Vorbisfile::Read( int16_t *buf, int iFrames )
|
||||
CHECKPOINT_M( ssprintf("p %i,%i: %i frames of silence needed", curofs, read_offset, silence) );
|
||||
|
||||
memset( buf, 0, silence );
|
||||
ret = silence;
|
||||
iFramesRead = iSilentFrames;
|
||||
}
|
||||
}
|
||||
|
||||
if( ret == 0 )
|
||||
if( iFramesRead == 0 )
|
||||
{
|
||||
int bstream;
|
||||
#if defined(INTEGER_VORBIS)
|
||||
ret = ov_read( vf, (char *) buf, iFrames * bytes_per_frame, &bstream );
|
||||
int ret = ov_read( vf, (char *) buf, iFrames * channels * sizeof(int16_t), &bstream );
|
||||
#else // float vorbis decoder
|
||||
ret = ov_read( vf, (char *) buf, iFrames * bytes_per_frame, (BYTE_ORDER == BIG_ENDIAN)?1:0, 2, 1, &bstream );
|
||||
float **pcm;
|
||||
int ret = ov_read_float( vf, &pcm, iFrames, &bstream );
|
||||
#endif
|
||||
|
||||
{
|
||||
vorbis_info *vi = ov_info( vf, -1 );
|
||||
ASSERT( vi != NULL );
|
||||
@@ -228,12 +230,43 @@ int RageSoundReader_Vorbisfile::Read( int16_t *buf, int iFrames )
|
||||
eof = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
#if defined(INTEGER_VORBIS)
|
||||
if( ret > 0 )
|
||||
{
|
||||
int iSamplesRead = ret / sizeof(int16_t);
|
||||
iFramesRead = iSamplesRead / channels;
|
||||
|
||||
/* Convert in reverse, so we can do it in-place. */
|
||||
const int16_t *pIn = (int16_t *) buf;
|
||||
float *pOut = (float *) buf;
|
||||
for( int i = iSamplesRead-1; i >= 0; --i )
|
||||
pOut[i] = pIn[i] / 32768.0f;
|
||||
}
|
||||
#else
|
||||
if( ret > 0 )
|
||||
{
|
||||
iFramesRead = ret;
|
||||
|
||||
int iNumChannels = channels;
|
||||
for( int iChannel = 0; iChannel < iNumChannels; ++iChannel )
|
||||
{
|
||||
const float *pChannelIn = pcm[iChannel];
|
||||
float *pChannelOut = &buf[iChannel];
|
||||
for( int i = 0; i < iFramesRead; ++i )
|
||||
{
|
||||
*pChannelOut = *pChannelIn;
|
||||
++pChannelIn;
|
||||
pChannelOut += iNumChannels;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
int iFramesRead = ret / bytes_per_frame;
|
||||
read_offset += ret / bytes_per_frame;
|
||||
read_offset += iFramesRead;
|
||||
|
||||
buf += ret / sizeof(int16_t);
|
||||
buf += iFramesRead * channels;
|
||||
frames_read += iFramesRead;
|
||||
iFrames -= iFramesRead;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ public:
|
||||
|
||||
int GetLength() const;
|
||||
int SetPosition( int iFrame );
|
||||
int Read( int16_t *pBuf, int iFrames );
|
||||
int Read( float *pBuf, int iFrames );
|
||||
int GetSampleRate() const;
|
||||
unsigned GetNumChannels() const { return channels; }
|
||||
int GetNextSourceFrame() const;
|
||||
|
||||
@@ -19,21 +19,31 @@ namespace
|
||||
{
|
||||
/* pBuf contains iSamples 8-bit samples; convert to 16-bit. pBuf must
|
||||
* have enough storage to hold the resulting data. */
|
||||
void Convert8bitTo16bit( void *pBuf, int iSamples )
|
||||
void Convert8bitToFloat( void *pBuf, int iSamples )
|
||||
{
|
||||
/* Convert in reverse, so we can do it in-place. */
|
||||
const uint8_t *pIn = (uint8_t *) pBuf;
|
||||
int16_t *pOut = (int16_t *) pBuf;
|
||||
float *pOut = (float *) pBuf;
|
||||
for( int i = iSamples-1; i >= 0; --i )
|
||||
pOut[i] = SCALE( pIn[i], 0, 255, -32768, 32767 );
|
||||
{
|
||||
int iSample = pIn[i];
|
||||
iSample -= 128; /* 0..255 -> -128..127 */
|
||||
pOut[i] = iSample / 128.0f;
|
||||
}
|
||||
}
|
||||
|
||||
/* Flip 16-bit samples if necessary. On little-endian systems, this will
|
||||
* optimize out. */
|
||||
void Convert16BitFromLittleEndian( int16_t *pBuf, int iSamples )
|
||||
void ConvertLittleEndian16BitToFloat( void *pBuf, int iSamples )
|
||||
{
|
||||
for( int i = 0; i < iSamples; ++i )
|
||||
pBuf[i] = Swap16LE( pBuf[i] );
|
||||
/* Convert in reverse, so we can do it in-place. */
|
||||
const int16_t *pIn = (int16_t *) pBuf;
|
||||
float *pOut = (float *) pBuf;
|
||||
for( int i = iSamples-1; i >= 0; --i )
|
||||
{
|
||||
int16_t iSample = Swap16LE( pIn[i] );
|
||||
pOut[i] = iSample / 32768.0f;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -42,7 +52,7 @@ struct WavReader
|
||||
WavReader( RageFile &f, const RageSoundReader_WAV::WavData &data ):
|
||||
m_File(f), m_WavData(data) { }
|
||||
virtual ~WavReader() { }
|
||||
virtual int Read( int16_t *pBuf, int iFrames ) = 0;
|
||||
virtual int Read( float *pBuf, int iFrames ) = 0;
|
||||
virtual int GetLength() const = 0;
|
||||
virtual bool Init() = 0;
|
||||
virtual int SetPosition( int iFrame ) = 0;
|
||||
@@ -72,11 +82,10 @@ struct WavReaderPCM: public WavReader
|
||||
return true;
|
||||
}
|
||||
|
||||
int Read( int16_t *buf, int iFrames )
|
||||
int Read( float *buf, int iFrames )
|
||||
{
|
||||
int len = iFrames * m_WavData.m_iChannels * sizeof(int16_t);
|
||||
if( m_WavData.m_iBitsPerSample == 8 )
|
||||
len /= 2;
|
||||
int len = iFrames * m_WavData.m_iChannels;
|
||||
len *= m_WavData.m_iBitsPerSample/8;
|
||||
|
||||
const int iBytesLeftInDataChunk = m_WavData.m_iDataChunkSize - (m_File.Tell() - m_WavData.m_iDataChunkPos);
|
||||
if( !iBytesLeftInDataChunk )
|
||||
@@ -84,16 +93,16 @@ struct WavReaderPCM: public WavReader
|
||||
|
||||
len = min( len, iBytesLeftInDataChunk );
|
||||
int iGot = m_File.Read( buf, len );
|
||||
int iGotSamples = 0;
|
||||
|
||||
int iBytesPerSample = m_WavData.m_iBitsPerSample/8;
|
||||
int iGotSamples = iGot / iBytesPerSample;
|
||||
switch( m_WavData.m_iBitsPerSample )
|
||||
{
|
||||
case 8:
|
||||
Convert8bitTo16bit( buf, iGot );
|
||||
iGotSamples = iGot;
|
||||
Convert8bitToFloat( buf, iGotSamples );
|
||||
break;
|
||||
case 16:
|
||||
Convert16BitFromLittleEndian( buf, iGot/2 );
|
||||
iGotSamples = iGot / 2;
|
||||
ConvertLittleEndian16BitToFloat( buf, iGotSamples );
|
||||
break;
|
||||
}
|
||||
return iGotSamples / m_WavData.m_iChannels;
|
||||
@@ -133,7 +142,7 @@ struct WavReaderADPCM: public WavReader
|
||||
public:
|
||||
vector<int16_t> m_iaCoef1, m_iaCoef2;
|
||||
int16_t m_iFramesPerBlock;
|
||||
int8_t *m_pBuffer;
|
||||
float *m_pBuffer;
|
||||
int m_iBufferAvail, m_iBufferUsed;
|
||||
|
||||
WavReaderADPCM( RageFile &f, const RageSoundReader_WAV::WavData &data ):
|
||||
@@ -170,7 +179,7 @@ public:
|
||||
if( m_sError.size() != 0 )
|
||||
return false;
|
||||
|
||||
m_pBuffer = new int8_t[m_iFramesPerBlock*m_WavData.m_iChannels*sizeof(int16_t)];
|
||||
m_pBuffer = new float[m_iFramesPerBlock*m_WavData.m_iChannels];
|
||||
m_iBufferAvail = m_iBufferUsed = 0;
|
||||
|
||||
m_File.Seek( m_WavData.m_iDataChunkPos );
|
||||
@@ -207,7 +216,7 @@ public:
|
||||
if( m_File.Tell() >= m_WavData.m_iDataChunkSize+m_WavData.m_iDataChunkPos || m_File.AtEOF() )
|
||||
return true; /* past the data chunk */
|
||||
|
||||
int16_t *pBuffer = (int16_t *) m_pBuffer;
|
||||
float *pBuffer = m_pBuffer;
|
||||
int iCoef1[2], iCoef2[2];
|
||||
for( int i = 0; i < m_WavData.m_iChannels; ++i )
|
||||
{
|
||||
@@ -239,9 +248,9 @@ public:
|
||||
}
|
||||
|
||||
for( int i = 0; i < m_WavData.m_iChannels; ++i )
|
||||
pBuffer[m_iBufferAvail++] = iSamp2[i];
|
||||
pBuffer[m_iBufferAvail++] = iSamp2[i] / 32768.0f;
|
||||
for( int i = 0; i < m_WavData.m_iChannels; ++i )
|
||||
pBuffer[m_iBufferAvail++] = iSamp1[i];
|
||||
pBuffer[m_iBufferAvail++] = iSamp1[i] / 32768.0f;
|
||||
|
||||
int8_t iBuf = 0, iBufSize = 0;
|
||||
|
||||
@@ -272,7 +281,7 @@ public:
|
||||
int32_t iNewSample = iPredSample + (iDelta[c] * iErrorDelta);
|
||||
iNewSample = clamp( iNewSample, -32768, 32767 );
|
||||
|
||||
pBuffer[m_iBufferAvail++] = (int16_t) iNewSample;
|
||||
pBuffer[m_iBufferAvail++] = iNewSample / 32768.0f;
|
||||
|
||||
static const int aAdaptionTable[] = {
|
||||
768, 614, 512, 409, 307, 230, 230, 230,
|
||||
@@ -290,10 +299,10 @@ public:
|
||||
return true;
|
||||
}
|
||||
|
||||
int Read( int16_t *buf, int iFrames )
|
||||
int Read( float *buf, int iFrames )
|
||||
{
|
||||
int iSamplesPerFrame = m_WavData.m_iChannels;
|
||||
int iBytesPerFrame = iSamplesPerFrame * sizeof(int16_t);
|
||||
int iBytesPerFrame = iSamplesPerFrame * sizeof(float);
|
||||
int iGotFrames = 0;
|
||||
while( iGotFrames < (int) iFrames )
|
||||
{
|
||||
@@ -541,7 +550,7 @@ int RageSoundReader_WAV::GetNextSourceFrame() const
|
||||
return m_pImpl->GetNextSourceFrame();
|
||||
}
|
||||
|
||||
int RageSoundReader_WAV::Read( int16_t *pBuf, int iFrames )
|
||||
int RageSoundReader_WAV::Read( float *pBuf, int iFrames )
|
||||
{
|
||||
ASSERT( m_pImpl != NULL );
|
||||
return m_pImpl->Read( pBuf, iFrames );
|
||||
|
||||
@@ -14,7 +14,7 @@ public:
|
||||
void Close();
|
||||
int GetLength() const;
|
||||
int SetPosition( int iFrame );
|
||||
int Read( int16_t *pBuf, int iFrames );
|
||||
int Read( float *pBuf, int iFrames );
|
||||
int GetSampleRate() const { return m_WavData.m_iSampleRate; }
|
||||
unsigned GetNumChannels() const { return m_WavData.m_iChannels; }
|
||||
int GetNextSourceFrame() const;
|
||||
|
||||
@@ -5,17 +5,17 @@
|
||||
/* Some of these functions assume a channel count: */
|
||||
static const int channels = 2;
|
||||
|
||||
void RageSoundUtil::Attenuate( int16_t *pBuf, int iSamples, float fVolume )
|
||||
void RageSoundUtil::Attenuate( float *pBuf, int iSamples, float fVolume )
|
||||
{
|
||||
while( iSamples-- )
|
||||
{
|
||||
*pBuf = int16_t( (*pBuf) * fVolume );
|
||||
*pBuf *= fVolume;
|
||||
++pBuf;
|
||||
}
|
||||
}
|
||||
|
||||
/* Pan buffer left or right; fPos is -1...+1. Buffer is assumed to be stereo. */
|
||||
void RageSoundUtil::Pan( int16_t *buffer, int frames, float fPos )
|
||||
void RageSoundUtil::Pan( float *buffer, int frames, float fPos )
|
||||
{
|
||||
if( fPos == 0 )
|
||||
return; /* no change */
|
||||
@@ -40,15 +40,15 @@ void RageSoundUtil::Pan( int16_t *buffer, int frames, float fPos )
|
||||
ASSERT_M( channels == 2, ssprintf("%i", channels) );
|
||||
for( int samp = 0; samp < frames; ++samp )
|
||||
{
|
||||
int16_t l = int16_t(buffer[0]*fLeftFactors[0] + buffer[1]*fLeftFactors[1]);
|
||||
int16_t r = int16_t(buffer[0]*fRightFactors[0] + buffer[1]*fRightFactors[1]);
|
||||
float l = buffer[0]*fLeftFactors[0] + buffer[1]*fLeftFactors[1];
|
||||
float r = buffer[0]*fRightFactors[0] + buffer[1]*fRightFactors[1];
|
||||
buffer[0] = l;
|
||||
buffer[1] = r;
|
||||
buffer += 2;
|
||||
}
|
||||
}
|
||||
|
||||
void RageSoundUtil::Fade( int16_t *buffer, int frames, float fStartVolume, float fEndVolume )
|
||||
void RageSoundUtil::Fade( float *buffer, int frames, float fStartVolume, float fEndVolume )
|
||||
{
|
||||
/* If the whole buffer is full volume, skip. */
|
||||
if( fStartVolume > .9999f && fEndVolume > .9999f )
|
||||
@@ -61,17 +61,17 @@ void RageSoundUtil::Fade( int16_t *buffer, int frames, float fStartVolume, float
|
||||
fVolPercent = clamp( fVolPercent, 0.f, 1.f );
|
||||
for(int i = 0; i < channels; ++i)
|
||||
{
|
||||
*buffer = short(*buffer * fVolPercent);
|
||||
*buffer *= fVolPercent;
|
||||
buffer++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Dupe mono to stereo in-place; do it in reverse, to handle overlap. */
|
||||
void RageSoundUtil::ConvertMonoToStereoInPlace( int16_t *data, int iFrames )
|
||||
void RageSoundUtil::ConvertMonoToStereoInPlace( float *data, int iFrames )
|
||||
{
|
||||
int16_t *input = data;
|
||||
int16_t *output = input;
|
||||
float *input = data;
|
||||
float *output = input;
|
||||
input += iFrames;
|
||||
output += iFrames * 2;
|
||||
while( iFrames-- )
|
||||
|
||||
@@ -5,10 +5,10 @@
|
||||
|
||||
namespace RageSoundUtil
|
||||
{
|
||||
void Attenuate( int16_t *pBuf, int iSamples, float fVolume );
|
||||
void Pan( int16_t *pBuffer, int iFrames, float fPos );
|
||||
void Fade( int16_t *pBuffer, int iFrames, float fStartVolume, float fEndVolume );
|
||||
void ConvertMonoToStereoInPlace( int16_t *pBuffer, int iFrames );
|
||||
void Attenuate( float *pBuf, int iSamples, float fVolume );
|
||||
void Pan( float *pBuffer, int iFrames, float fPos );
|
||||
void Fade( float *pBuffer, int iFrames, float fStartVolume, float fEndVolume );
|
||||
void ConvertMonoToStereoInPlace( float *pBuffer, int iFrames );
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user