Moving ITAHDFTSpectra and some useful methods for sampleframe and -buffer.

parent 6da506d7
......@@ -69,6 +69,7 @@ set( ITABaseHeader
"include/ITAFade.h"
"include/ITAFastMath.h"
"include/ITAFileSystemUtils.h"
"include/ITAHDFTSpectra.h"
"include/ITAHDFTSpectrum.h"
"include/ITAFunctors.h"
"include/ITALog.h"
......@@ -99,6 +100,7 @@ set( ITABaseSources
"src/ITAException.cpp"
"src/ITAFade.cpp"
"src/ITAFileSystemUtils.cpp"
"src/ITAHDFTSpectra.cpp"
"src/ITAHDFTSpectrum.cpp"
"src/ITALog.cpp"
"src/ITANumericUtils.cpp"
......
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2017
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_HDFT_SPECTRA
#define INCLUDE_WATCHER_ITA_HDFT_SPECTRA
// ITA includes
#include <ITABaseDefinitions.h>
#include <ITAException.h>
// STL includes
#include <vector>
class ITAHDFTSpectrum;
//! Multi-channel half-sided discrete fourier spectra
/**
*
* This class describes DFT spectrum data with variable number channels
* and provides functionality for manipulation and math operations.
*
* This class extends the \ITAHDFTSpectrum for multi-channel applications.
*
*/
class ITA_BASE_API ITAHDFTSpectra
{
public:
//! Constructor that initializes the
ITAHDFTSpectra( const double dSampleRate, const int iNumChannels, const int iDFTSize, const bool bZeroInit=true );
//! Constructor that uses a non-empty HDFTSpectrum vector
ITAHDFTSpectra( const std::vector< ITAHDFTSpectrum* >& vpSpectrumVec );
//! Standard destructor
~ITAHDFTSpectra();
//! Return number of channels
/**
* \return Number of spectra / dimension of filter
*/
int GetNumChannels() const;
//! Return DFT size
/**
* \return Number of coeffs + 1 for DC value
*/
int GetDFTSize() const;
//! Return sampling rate
double GetSampleRate() const;
//! Adds the given spectra channel-wise
void add( const ITAHDFTSpectra* );
//! Subtracts the given spectra channel-wise
void sub( const ITAHDFTSpectra* );
//! Multiplies the given spectra channel-wise
void mul( const ITAHDFTSpectra* );
//! Multiplies the conjugate of the given spectra without data copy channel-wise
void mul_conj( const ITAHDFTSpectra* );
//! Multiplies a scalar
void mul_scalar( double );
//! Divides the given spectra channel-wise
void div( const ITAHDFTSpectra* );
//! Set unity (all coefficiants real one)
void SetUnity();
//! Set unity (all coefficiants real one)
void SetZero();
//! Copy from another Spectra
void CopyFrom(const ITAHDFTSpectra* otherSpectra);
//! Subscript operator gives direct access to spectrum channel
const ITAHDFTSpectrum* operator[]( const int ) const;
ITAHDFTSpectrum* operator[]( const int );
private:
//! Standard constructor
ITAHDFTSpectra();
std::vector< ITAHDFTSpectrum* > m_vpSpectra; //! DFT spectra
};
#endif // INCLUDE_WATCHER_ITA_HDFT_SPECTRA
......@@ -301,6 +301,9 @@ public:
//! Negieren (Multiplikation mit -1 bzw. Phasendrehungum 180)
void Negate();
//! Normalize data
void Normalize();
//! Read/Write Indizierungsoperator
float& operator[]( int iSample );
......
......@@ -114,7 +114,11 @@ public:
* \param iLength Lnge [Anzahl Samples]
* \param bZeroinit Samples mit Nullen initialisieren?
*/
void init( int iChannels, int iLength, bool bZeroinit);
void Init( int iChannels, int iLength, bool bZeroinit );
inline void init( int iChannels, int iLength, bool bZeroinit )
{
return Init( iChannels, iLength, bZeroinit );
}
void Load( const std::string& sFilePath );
void Load( const std::string& sFilePath, double& dSampleRate );
......@@ -294,7 +298,11 @@ public:
*
* \return Overall peak value that has been used for normalization (can be negative)
*/
float normalize();
float Normalize();
inline float normalize()
{
return Normalize();
};
//! Read/Write Indizierungsoperator fr Zugriff auf Kanaldaten
ITASampleBuffer& operator[](int iChannel);
......
#include <ITAHDFTSpectra.h>
#include <ITAAudiofileWriter.h>
#include <ITAFilesystemUtils.h>
#include <ITAHDFTSpectrum.h>
#include <ITASampleFrame.h>
#include <ITAStringUtils.h>
ITAHDFTSpectra::ITAHDFTSpectra( const double dSampleRate, const int iNumChannels, const int iDFTSize, const bool bZeroInit/*=true*/ )
{
if( iNumChannels < 1 )
ITA_EXCEPT1( INVALID_PARAMETER, "At least one DFT channel must be used" );
if( iDFTSize < 1 )
ITA_EXCEPT1( INVALID_PARAMETER, "Invalid DFT size" );
for( int i=0; i<iNumChannels; i++ )
m_vpSpectra.push_back( new ITAHDFTSpectrum( dSampleRate, iDFTSize, bZeroInit ) );
}
ITAHDFTSpectra::ITAHDFTSpectra( const std::vector< ITAHDFTSpectrum* >& vpSpectrumVec )
{
if( vpSpectrumVec.size() == 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "At least one DFT channel must be used" );
for( size_t i=0; i<vpSpectrumVec.size(); i++ )
{
const ITAHDFTSpectrum* pSpectrum( vpSpectrumVec[i] );
if( pSpectrum->getDFTSize() <= 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "Invalid DFT size in spectrum number " + IntToString( int(i) ) );
if( pSpectrum->getSamplerate() <= 0 )
ITA_EXCEPT1( INVALID_PARAMETER, "Invalid sampling rate in spectrum number " + IntToString( int(i) ) );
m_vpSpectra.push_back( new ITAHDFTSpectrum( pSpectrum ) ); // copy
}
}
ITAHDFTSpectra::~ITAHDFTSpectra()
{
for( size_t i=0; i<m_vpSpectra.size(); i++ )
delete m_vpSpectra[i];
}
void ITAHDFTSpectra::CopyFrom(const ITAHDFTSpectra *otherSpectra)
{
int iNumChannels=otherSpectra->GetNumChannels();
m_vpSpectra.clear();
for( int i=0; i<iNumChannels; i++ )
{
//ITAHDFTSpectrum* tempSpectrum = new ITAHDFTSpectrum(double(otherSpectra->GetSampleRate()),int(otherSpectra->GetDFTSize()));
ITAHDFTSpectrum* tempSpectrum = new ITAHDFTSpectrum((*otherSpectra)[i]);
//tempSpectrum->copyFrom((*otherSpectra)[i]);
m_vpSpectra.push_back(tempSpectrum);
}
}
void ITAHDFTSpectra::SetUnity()
{
for( size_t i=0; i<m_vpSpectra.size(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
pSpectrum->SetUnity();
}
}
void ITAHDFTSpectra::SetZero()
{
for( size_t i=0; i<m_vpSpectra.size(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
pSpectrum->mul( 0.0f );
}
}
int ITAHDFTSpectra::GetNumChannels() const
{
return int( m_vpSpectra.size() );
}
int ITAHDFTSpectra::GetDFTSize() const
{
return m_vpSpectra[0]->getDFTSize();
}
double ITAHDFTSpectra::GetSampleRate() const
{
return m_vpSpectra[0]->getSamplerate();
}
void ITAHDFTSpectra::add( const ITAHDFTSpectra* pSource )
{
if( GetNumChannels() != pSource->GetNumChannels() )
ITA_EXCEPT1( INVALID_PARAMETER, "Channel number mismatch" );
for( int i=0; i<GetNumChannels(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
const ITAHDFTSpectrum* pSourceSpectrum( (*pSource)[i] );
pSpectrum->add( pSourceSpectrum );
}
return;
}
void ITAHDFTSpectra::sub( const ITAHDFTSpectra* pSource )
{
if( GetNumChannels() != pSource->GetNumChannels() )
ITA_EXCEPT1( INVALID_PARAMETER, "Channel number mismatch" );
for( int i=0; i<GetNumChannels(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
const ITAHDFTSpectrum* pSourceSpectrum( (*pSource)[i] );
pSpectrum->sub( pSourceSpectrum );
}
return;
}
void ITAHDFTSpectra::mul( const ITAHDFTSpectra* pSource )
{
if( GetNumChannels() != pSource->GetNumChannels() )
ITA_EXCEPT1( INVALID_PARAMETER, "Channel number mismatch" );
for( int i=0; i<GetNumChannels(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
const ITAHDFTSpectrum* pSourceSpectrum( (*pSource)[i] );
pSpectrum->mul( pSourceSpectrum );
}
return;
}
void ITAHDFTSpectra::mul_conj( const ITAHDFTSpectra* pSource )
{
if( GetNumChannels() != pSource->GetNumChannels() )
ITA_EXCEPT1( INVALID_PARAMETER, "Channel number mismatch" );
for( int i=0; i<GetNumChannels(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
const ITAHDFTSpectrum* pSourceSpectrum( (*pSource)[i] );
pSpectrum->mul( pSourceSpectrum );
}
return;
}
void ITAHDFTSpectra::mul_scalar( double )
{
ITA_EXCEPT0( NOT_IMPLEMENTED );
}
void ITAHDFTSpectra::div( const ITAHDFTSpectra* pSource )
{
if( GetNumChannels() != pSource->GetNumChannels() )
ITA_EXCEPT1( INVALID_PARAMETER, "Channel number mismatch" );
for( int i=0; i<GetNumChannels(); i++ )
{
ITAHDFTSpectrum* pSpectrum( m_vpSpectra[i] );
const ITAHDFTSpectrum* pSourceSpectrum( (*pSource)[i] );
pSpectrum->div( pSourceSpectrum );
}
return;
}
const ITAHDFTSpectrum* ITAHDFTSpectra::operator[]( const int iIdx ) const
{
return m_vpSpectra[iIdx];
}
ITAHDFTSpectrum* ITAHDFTSpectra::operator[]( const int iIdx )
{
return m_vpSpectra[iIdx];
}
......@@ -562,7 +562,13 @@ float ITASampleBuffer::FindPeak( int* piPeakIndex )
void ITASampleBuffer::Negate()
{
mul_scalar( -1 );
mul_scalar( -1.0f );
}
void ITASampleBuffer::Normalize()
{
mul_scalar( FindPeak() );
}
float& ITASampleBuffer::operator[]( int iSample )
......
......@@ -8,23 +8,26 @@
#include <ITAException.h>
ITASampleFrame::ITASampleFrame()
: m_iChannels(0), m_iLength(0) {}
: m_iChannels( 0 ), m_iLength( 0 ) {}
ITASampleFrame::ITASampleFrame(int iChannels, int iLength, bool bZeroinit)
: m_iChannels(0), m_iLength(0)
ITASampleFrame::ITASampleFrame( int iChannels, int iLength, bool bZeroinit )
: m_iChannels( 0 )
, m_iLength( 0 )
{
init( iChannels, iLength, bZeroinit);
Init( iChannels, iLength, bZeroinit );
}
ITASampleFrame::ITASampleFrame(const ITASampleFrame* pSource)
: m_iChannels(0), m_iLength(0)
ITASampleFrame::ITASampleFrame( const ITASampleFrame* pSource )
: m_iChannels( 0 )
, m_iLength( 0 )
{
*this = *pSource;
}
ITASampleFrame::ITASampleFrame(const ITASampleFrame& sbSource)
: m_iChannels(0), m_iLength(0)
ITASampleFrame::ITASampleFrame( const ITASampleFrame& sbSource )
: m_iChannels( 0 )
, m_iLength( 0 )
{
*this = sbSource;
}
......@@ -38,32 +41,36 @@ ITASampleFrame::~ITASampleFrame()
{
}
bool ITASampleFrame::empty() const {
return ((m_iChannels == 0) || (m_iLength == 0));
bool ITASampleFrame::empty() const
{
return ( ( m_iChannels == 0 ) || ( m_iLength == 0 ) );
}
int ITASampleFrame::channels() const {
int ITASampleFrame::channels() const
{
return m_iChannels;
}
int ITASampleFrame::length() const {
int ITASampleFrame::length() const
{
return m_iLength;
}
void ITASampleFrame::init( int iChannels, int iLength, bool bZeroinit)
void ITASampleFrame::Init( int iChannels, int iLength, bool bZeroinit )
{
assert( iChannels >= 0 );
assert( iLength >= 0 );
// TODO: Mit ein wenig cleverness knnte dies ohne Vollstndiges Abrumen gehen.
// Die Frage ist: Wer's braucht?
if ((m_iChannels > 0) || (m_iLength > 0)) free();
if( ( m_iChannels > 0 ) || ( m_iLength > 0 ) ) free();
m_vChannels.resize(iChannels);
for (int i=0; i<iChannels; i++) {
m_vChannels[i].m_pParent = NULL;
m_vChannels[i].Init( iLength, bZeroinit);
m_vChannels[i].m_pParent = this;
m_vChannels.resize( iChannels );
for( int i = 0; i < iChannels; i++ )
{
m_vChannels[ i ].m_pParent = NULL;
m_vChannels[ i ].Init( iLength, bZeroinit );
m_vChannels[ i ].m_pParent = this;
}
m_iChannels = iChannels;
......@@ -121,10 +128,10 @@ void ITASampleFrame::Store( const std::string& sFilePath, double dSamplingRate )
oProps.dSampleRate = dSamplingRate;
oProps.eDomain = ITADomain::ITA_TIME_DOMAIN;
oProps.eQuantization = ITAQuantization::ITA_FLOAT;
oProps.iChannels = (unsigned int) m_iChannels;
oProps.iLength = (unsigned int) m_iLength;
oProps.iChannels = ( unsigned int ) m_iChannels;
oProps.iLength = ( unsigned int ) m_iLength;
pWriter = ITAAudiofileWriter::create( sFilePath, oProps );
std::vector< const float* > vpfDest( oProps.iChannels );
for( int i = 0; i < oProps.iChannels; i++ )
vpfDest[ i ] = m_vChannels[ i ].data();
......@@ -132,7 +139,7 @@ void ITASampleFrame::Store( const std::string& sFilePath, double dSamplingRate )
pWriter->write( oProps.iLength, vpfDest );
}
catch (...)
catch( ... )
{
delete pWriter;
throw;
......@@ -154,212 +161,264 @@ void ITASampleFrame::free()
void ITASampleFrame::fill( float fValue )
{
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->Fill(fValue);
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->Fill( fValue );
}
void ITASampleFrame::fill(int iOffset, int iCount, float fValue) {
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->Fill(iOffset, iCount, fValue);
void ITASampleFrame::fill( int iOffset, int iCount, float fValue )
{
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->Fill( iOffset, iCount, fValue );
}
void ITASampleFrame::zero() {
fill(0);
fill( 0 );
}
void ITASampleFrame::zero(int iOffset, int iCount )
void ITASampleFrame::zero( int iOffset, int iCount )
{
fill(iOffset, iCount, 0.0f);
fill( iOffset, iCount, 0.0f );
}
void ITASampleFrame::identity() {
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->Identity();
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->Identity();
}
void ITASampleFrame::fade(int iOffset, int iCount, int iFadeDirection, int iFadeFunction) {
for (int i=0; i<m_iChannels; i++)
m_vChannels[i].Fade( iOffset, iCount, iFadeDirection, iFadeFunction );
void ITASampleFrame::fade( int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
{
for( int i = 0; i < m_iChannels; i++ )
m_vChannels[ i ].Fade( iOffset, iCount, iFadeDirection, iFadeFunction );
}
void ITASampleFrame::crossfade(const ITASampleFrame* psfSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction) {
if (!psfSrc) ITA_EXCEPT1(INVALID_PARAMETER, "Nullpointer passed");
if (psfSrc->channels() != m_iChannels) ITA_EXCEPT1(INVALID_PARAMETER, "Number of channels do not match");
void ITASampleFrame::crossfade( const ITASampleFrame* psfSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
{
if( !psfSrc ) ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
if( psfSrc->channels() != m_iChannels ) ITA_EXCEPT1( INVALID_PARAMETER, "Number of channels do not match" );
for (int i=0; i<m_iChannels; i++)
m_vChannels[i].Crossfade( (*psfSrc)[i], iOffset, iCount, iFadeDirection, iFadeFunction );
for( int i = 0; i < m_iChannels; i++ )
m_vChannels[ i ].Crossfade( ( *psfSrc )[ i ], iOffset, iCount, iFadeDirection, iFadeFunction );
}
void ITASampleFrame::crossfade(const ITASampleFrame& sfSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction) {
void ITASampleFrame::crossfade( const ITASampleFrame& sfSrc, int iOffset, int iCount, int iFadeDirection, int iFadeFunction )
{
crossfade( &sfSrc, iOffset, iCount, iFadeDirection, iFadeFunction );
}
void ITASampleFrame::envelope(float fGain0, float fGain1) {
if (empty()) return;
void ITASampleFrame::envelope( float fGain0, float fGain1 ) {
if( empty() ) return;
for (int i=0; i<m_iChannels; i++)
m_vChannels[i].Envelope( fGain0, fGain1 );
for( int i = 0; i < m_iChannels; i++ )
m_vChannels[ i ].Envelope( fGain0, fGain1 );
}
void ITASampleFrame::write(const ITASampleFrame* psfSrc, int iCount, int iSrcOffset, int iDestOffset) {
if (!psfSrc) ITA_EXCEPT1(INVALID_PARAMETER, "Nullpointer passed");
if (psfSrc->channels() != m_iChannels) ITA_EXCEPT1(INVALID_PARAMETER, "Number of channels do not match");
void ITASampleFrame::write( const ITASampleFrame* psfSrc, int iCount, int iSrcOffset, int iDestOffset )
{
if( !psfSrc ) ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
if( psfSrc->channels() != m_iChannels ) ITA_EXCEPT1( INVALID_PARAMETER, "Number of channels do not match" );
for (int i=0; i<m_iChannels; i++)
m_vChannels[i].write( (*psfSrc)[i], iCount, iSrcOffset, iDestOffset );
for( int i = 0; i < m_iChannels; i++ )
m_vChannels[ i ].write( ( *psfSrc )[ i ], iCount, iSrcOffset, iDestOffset );
}
void ITASampleFrame::write(const ITASampleFrame& sfSrc, int iCount, int iSrcOffset, int iDestOffset) {
write(&sfSrc, iCount, iSrcOffset, iDestOffset);
void ITASampleFrame::write( const ITASampleFrame& sfSrc, int iCount, int iSrcOffset, int iDestOffset )
{
write( &sfSrc, iCount, iSrcOffset, iDestOffset );
}
void ITASampleFrame::cyclic_write(const ITASampleFrame* psfSrc, int iCount, int iSrcOffset, int iDestOffset) {
if (!psfSrc) ITA_EXCEPT1(INVALID_PARAMETER, "Nullpointer passed");
if (psfSrc->channels() != m_iChannels) ITA_EXCEPT1(INVALID_PARAMETER, "Number of channels do not match");
void ITASampleFrame::cyclic_write( const ITASampleFrame* psfSrc, int iCount, int iSrcOffset, int iDestOffset )
{
if( !psfSrc ) ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
if( psfSrc->channels() != m_iChannels ) ITA_EXCEPT1( INVALID_PARAMETER, "Number of channels do not match" );
for (int i=0; i<m_iChannels; i++)
m_vChannels[i].cyclic_write( &((*psfSrc)[i]), iCount, iSrcOffset, iDestOffset );
for( int i = 0; i < m_iChannels; i++ )
m_vChannels[ i ].cyclic_write( &( ( *psfSrc )[ i ] ), iCount, iSrcOffset, iDestOffset );
}
void ITASampleFrame::cyclic_write(const ITASampleFrame& sfSrc, int iCount, int iSrcOffset, int iDestOffset) {
cyclic_write(&sfSrc, iCount, iSrcOffset, iDestOffset);
void ITASampleFrame::cyclic_write( const ITASampleFrame& sfSrc, int iCount, int iSrcOffset, int iDestOffset )
{
cyclic_write( &sfSrc, iCount, iSrcOffset, iDestOffset );
}
void ITASampleFrame::CyclicShift( int iCount)
void ITASampleFrame::CyclicShift( int iCount )
{
for (int i = 0; i < m_iChannels; i++)
m_vChannels[i].CyclicShift(iCount);
for( int i = 0; i < m_iChannels; i++ )
m_vChannels[ i ].CyclicShift( iCount );
}
void ITASampleFrame::add_scalar(float fValue) {
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->add_scalar(fValue);
void ITASampleFrame::add_scalar( float fValue )
{
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->add_scalar( fValue );
}
void ITASampleFrame::sub_scalar(float fValue) {
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->sub_scalar(fValue);
void ITASampleFrame::sub_scalar( float fValue )
{
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->sub_scalar( fValue );
}
void ITASampleFrame::mul_scalar(float fValue) {
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->mul_scalar(fValue);
void ITASampleFrame::mul_scalar( float fValue )
{
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->mul_scalar( fValue );
}
void ITASampleFrame::div_scalar(float fValue) {
for (ch_it it=m_vChannels.begin(); it!=m_vChannels.end(); ++it)
it->div_scalar(fValue);
void ITASampleFrame::div_scalar( float fValue )
{
for( ch_it it = m_vChannels.begin(); it != m_vChannels.end(); ++it )
it->div_scalar( fValue );
}
void ITASampleFrame::add_buf( const ITASampleBuffer* psbSource )
{
if( !psbSource ) ITA_EXCEPT1( INVALID_PARAMETER, "Nullpointer passed" );
if( psbSource->GetLength() != m_iLength ) ITA_EXCEPT1( INVALID_PARAMETER, "Lengths do not match" );