Fixing samplerate conversion test and added some more useful methods for CITAAudioSample

parent 9d390cf2
...@@ -37,6 +37,12 @@ public: ...@@ -37,6 +37,12 @@ public:
* Requires initialization or load to be used, otherwise methods will throw ITAException. * Requires initialization or load to be used, otherwise methods will throw ITAException.
*/ */
CITAAudioSample( const float fSampleRate = 44100.0f ); CITAAudioSample( const float fSampleRate = 44100.0f );
//! Create audio sample from file
/**
* Requires initialization or load to be used, otherwise methods will throw ITAException.
*/
CITAAudioSample( const std::string& sFilePath );
//! Create (empty) audio sample with given parameters //! Create (empty) audio sample with given parameters
/** /**
...@@ -87,6 +93,9 @@ public: ...@@ -87,6 +93,9 @@ public:
//! Load audio sample from file and convert sample rate, if necessary //! Load audio sample from file and convert sample rate, if necessary
void LoadWithSampleTypeConversion( const std::string& sFilePath ); void LoadWithSampleTypeConversion( const std::string& sFilePath );
//! Load audio sample from file and convert sample rate, if necessary
void LoadWithSampleTypeConversion( const CITAAudioSample& asSource );
private: private:
//! Disable this Init method from sample buffer //! Disable this Init method from sample buffer
......
#include <ITAAudioSample.h> #include <ITAAudioSample.h>
#include <ITAException.h> #include <ITAException.h>
#include <cassert>
#include <samplerate.h> #include <samplerate.h>
CITAAudioSample::CITAAudioSample( const float fSampleRate ) CITAAudioSample::CITAAudioSample( const float fSampleRate )
...@@ -26,6 +27,12 @@ CITAAudioSample::CITAAudioSample( const CITAAudioSample& sfSource ) ...@@ -26,6 +27,12 @@ CITAAudioSample::CITAAudioSample( const CITAAudioSample& sfSource )
ITASampleFrame::write( sfSource, sfSource.GetLength() ); ITASampleFrame::write( sfSource, sfSource.GetLength() );
} }
CITAAudioSample::CITAAudioSample( const std::string& sFilePath )
:CITAAudioSample()
{
Load( sFilePath );
}
void CITAAudioSample::Init( const int iNumChannels, const int iLength, const float fSampleRate, const bool bZeroInit /*= true */ ) void CITAAudioSample::Init( const int iNumChannels, const int iLength, const float fSampleRate, const bool bZeroInit /*= true */ )
{ {
m_fSampleRate = fSampleRate; m_fSampleRate = fSampleRate;
...@@ -45,12 +52,25 @@ void CITAAudioSample::LoadWithSampleTypeConversion( const std::string& sFilePath ...@@ -45,12 +52,25 @@ void CITAAudioSample::LoadWithSampleTypeConversion( const std::string& sFilePath
Load( sfRaw, GetSampleRate() ); Load( sfRaw, GetSampleRate() );
} }
void CITAAudioSample::LoadWithSampleTypeConversion( const CITAAudioSample& asSource )
{
ITASampleFrame* psfSource = ( ITASampleFrame* ) &asSource;
Load( *psfSource, asSource.GetSampleRate() );
}
void CITAAudioSample::Load( const CITAAudioSample& oSource ) void CITAAudioSample::Load( const CITAAudioSample& oSource )
{ {
Load( oSource, oSource.GetSampleRate() ); Load( oSource, oSource.GetSampleRate() );
} }
void CITAAudioSample::Load( const std::string& sFilePath )
{
double dSampleRate;
ITASampleFrame::Load( sFilePath, dSampleRate );
m_fSampleRate = float( dSampleRate );
}
float CITAAudioSample::GetSampleRate() const float CITAAudioSample::GetSampleRate() const
{ {
return m_fSampleRate; return m_fSampleRate;
...@@ -70,26 +90,33 @@ void CITAAudioSample::Load( const ITASampleFrame& sfSource, const float fSourceS ...@@ -70,26 +90,33 @@ void CITAAudioSample::Load( const ITASampleFrame& sfSource, const float fSourceS
} }
const float fSRCRation = GetSampleRate() / fSourceSampleRate; const float fSRCRation = GetSampleRate() / fSourceSampleRate;
const int iTargetLength = (int) ceil( sfSource.GetLength() * fSRCRation ); // @tbd test! const float fTargetLengthSamples = sfSource.GetLength() * fSRCRation;
Init( sfSource.GetNumChannels(), iTargetLength, m_fSampleRate ); int iTargetLengthSamples = ( int ) floor( fTargetLengthSamples );
const float fTargetLengthSubsampleFraction = fTargetLengthSamples - float( iTargetLengthSamples );
// Account for exact match, then the "last" sample is not resampled anymore and can be skipped
if( fTargetLengthSubsampleFraction == 0.0f )
iTargetLengthSamples--;
Init( sfSource.GetNumChannels(), iTargetLengthSamples, m_fSampleRate );
const int iConverter = SRC_SINC_MEDIUM_QUALITY; const int iConverter = SRC_SINC_MEDIUM_QUALITY;
for( int i = 0; i < sfSource.GetNumChannels(); i++ ) for( int i = 0; i < sfSource.GetNumChannels(); i++ )
{ {
int iSRCError; int iSRCError;
SRC_STATE* pSRCStace = src_new( iConverter, sfSource.GetNumChannels(), &iSRCError ); SRC_STATE* pSRCStace = src_new( iConverter, 1, &iSRCError ); // single channel conversion, samplerate expets interleaved. this is not compatible with ITASampleBuffer/Frame
if( pSRCStace == nullptr ) if( pSRCStace == nullptr )
ITA_EXCEPT_INVALID_PARAMETER( "Could not create sample rate converter, samplerate error was: " + std::string( src_strerror( iSRCError ) ) ); ITA_EXCEPT_INVALID_PARAMETER( "Could not create sample rate converter, samplerate error was: " + std::string( src_strerror( iSRCError ) ) );
SRC_DATA oSRCData; SRC_DATA oSRCData;
oSRCData.data_in = sfSource[ i ].GetData(); oSRCData.data_in = sfSource[ i ].GetData();
oSRCData.data_out = ( *this )[ i ].GetData(); oSRCData.data_out = ( *this )[ i ].GetData();
oSRCData.input_frames = 1; oSRCData.input_frames = sfSource.GetLength(); // In samplerate, one frame is "one sample" of multi channel audio
oSRCData.output_frames = 1; oSRCData.output_frames = iTargetLengthSamples;
oSRCData.src_ratio = fSRCRation; oSRCData.src_ratio = fSRCRation;
if( ( iSRCError = src_process( pSRCStace, &oSRCData ) ) != 0 ) if( ( iSRCError = src_process( pSRCStace, &oSRCData ) ) != 0 )
ITA_EXCEPT_INVALID_PARAMETER( "Could not convert sample rate: " + std::string( src_strerror( iSRCError ) ) ); ITA_EXCEPT_INVALID_PARAMETER( "Could not convert sample rate: " + std::string( src_strerror( iSRCError ) ) );
assert( oSRCData.output_frames_gen == iTargetLengthSamples );
src_delete( pSRCStace ); src_delete( pSRCStace );
} }
} }
\ No newline at end of file
...@@ -7,6 +7,20 @@ using namespace std; ...@@ -7,6 +7,20 @@ using namespace std;
int main( int, char** ) int main( int, char** )
{ {
try
{
CITAAudioSample asTTS48kHz( "tts.wav" );
CITAAudioSample asTTS44kHz;
asTTS44kHz.LoadWithSampleTypeConversion( asTTS48kHz );
asTTS44kHz.Store( "tts_44khz.wav" );
cout << "Converted files." << endl;
}
catch( ITAException& err )
{
cerr << "File test error: " << err << endl;
}
try try
{ {
CITAAudioSample as44kfs; CITAAudioSample as44kfs;
...@@ -18,13 +32,15 @@ int main( int, char** ) ...@@ -18,13 +32,15 @@ int main( int, char** )
as44kfs[ 0 ][ 0 ] = 1.0f; as44kfs[ 0 ][ 0 ] = 1.0f;
as44kfs[ 0 ][ as44kfs.GetLength() - 1 ] = -1.0f; as44kfs[ 0 ][ as44kfs.GetLength() - 1 ] = -1.0f;
as48kfs.Load( as44kfs ); as48kfs.LoadWithSampleTypeConversion( as44kfs );
as96kfs.Load( as48kfs ); as96kfs.LoadWithSampleTypeConversion( as48kfs );
as128kfs.Load( as96kfs ); as128kfs.LoadWithSampleTypeConversion( as96kfs );
cout << "Converted." << endl;
} }
catch( ITAException& err ) catch( ITAException& err )
{ {
cerr << "Error: " << err << endl; cerr << "Generic test error: " << err << endl;
} }
return 0; return 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment