Something went wrong on our end
Select Git revision
OrbitCamera.cpp
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ITASampleBuffer.h 12.26 KiB
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2024
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
#ifndef INCLUDE_WATCHER_ITA_SAMPLE_BUFFER
#define INCLUDE_WATCHER_ITA_SAMPLE_BUFFER
// ITABase
#include <ITABaseDefinitions.h>
// STL
#include <string>
// Forwards
class ITASampleFrame;
//! Buffer for a field of audio samples of type 32-bit floating point
/**
*
*/
class ITA_BASE_API ITASampleBuffer
{
public:
ITASampleBuffer( );
//! Create sample buffer of certain size
/**
* \param iLength Length (size) of buffer in samples
*/
explicit ITASampleBuffer( int iLength, bool bZeroInit = true );
//! Copy constructor as pointer
/**
* \param pSource Pointer to source buffer
*/
ITASampleBuffer( const ITASampleBuffer* pSource );
//! Copy constructor as reference
/**
* \param pbSource Reference to source buffer
*/
ITASampleBuffer( const ITASampleBuffer& sbSource );
virtual ~ITASampleBuffer( );
bool IsEmpty( ) const;
//! Deprecated
inline int length( ) { return GetLength( ); };
//! Length (size) of buffer (number of samples)
int GetLength( ) const;
//! Deprecated
inline const float* data( ) const { return GetData( ); };
inline float* data( ) { return GetData( ); };
//! Data pointer read-only
const float* GetData( ) const;
//! Data pointer
float* GetData( );
//! Initialize
/**
* (Re-)Initialize a sample buffer
*
* \param iLength Number of new samples
* \param bZeroInit Init with zeros
*/
void Init( int iLength, bool bZeroInit = true );
//! Free allocated samples
void Free( );
//! Sets all buffer samples to given value
void Fill( float fValue );
//! Sets defined samples to given value
/**
* \param iOffset Startindex
* \param iCount Anzahl Samples
* \param fFloat Wert
*/
void Fill( int iOffset, int iCount, float fValue );
//! Sets all samples to zero
void Zero( );
//! Sets given samples to zero
void Zero( int iOffset, int iCount );
//! Sets a Cronecker-Delta function (diskrete Dirac impulse)
void Identity( );
//! Fade ind or fade out
/**
* Fades in sample region [iOffset, iOffset+iCount] using given fading function
*/
void Fade( int iOffset, int iCount, int iFadingSign, int iFadingFunction = ITABase::FadingFunction::COSINE_SQUARE );
//! Crossfade
/**
* Fhrt eine Kreuzblende von angebenen Puffer in diesen Puffer durch.
*
* Fr den Modus CROSSFADE_FROM gilt:
*
* Zunchst werden iOffset Samples vom angebenen Puffer kopiert.
* Danach werden iCount Samples zwischen den beiden Puffern kreuzgeblendet.
* Dahinter folgen nur noch Samples dieses Puffers.
*/
void Crossfade( const ITASampleBuffer* psbSrc, int iOffset, int iCount, int iCrossfadeDirection, int iFadingFunction = ITABase::FadingFunction::COSINE_SQUARE );
void Crossfade( const ITASampleBuffer& sbSrc, int iOffset, int iCount, int iCrossfadeDirection, int iFadingFunction = ITABase::FadingFunction::COSINE_SQUARE );
//! Envelope
/**
/* Wendet eine lineare Einhllende (envelope) auf den Puffer an.
*
* \param fGain0 Startwert [0..1]
* \param fGain1 Endwert [0..1]
*/
void Envelope( float fGain0, float fGain1 );
//! Samples in ein Array kopieren
/**
* Kopiert iCount Samples aus dem Block beginnend bei Leseposition iOffset
* in den angegebenen Zielpuffer, dort beginnend ab Schreibposition 0.
*
* \param pfDest Zielarray
* \param iCount Anzahl zu kopierender Samples
* \param iSrcOffset Leseposition in diesem Puffer (SampleBuffer)
*
* TODO: Memory alignment fr SSE?
* \note Kein Lesen ber das Pufferende hinaus!
*/
void read( float* pfDest, int iCount, int iSrcOffset = 0 ) const;
//! Samples aus einem Array in den Puffer kopieren
/**
* Kopiert iCount Samples aus angegebenen Array beginnend bei Leseposition 0
* in den Puffer (SampleBuffer), dort beginnend ab Schreibposition iDestOffset.
*
* \param pfSrc Quellarray
* \param iCount Anzahl zu kopierender Samples
* \param iDestOffset Schreibposition in diesem Puffer (SampleBuffer)
*
* \note Kein Schreiben ber das Pufferende hinaus!
*/
void write( const float* pfSrc, int iCount, int iDestOffset = 0 );
//! Write samples from a source to the buffer (overwrites!)
/**
* Writes iCount samples from the given buffer starting at read position 0
* into the sample buffer beginning at given destination offset.
*
* @param pfSrc Source buffer / float array / vector
* @param iCount Number of samples to be added from source buffer into sample buffer
* @param iDestOffset Write position in sample buffer
*
* \@ote Make sure source buffer has iCount valid samples. Buffer will be overwritten by new samples.
*/
inline void WriteSamples( const float* pfSrc, int iCount, int iDestOffset = 0 ) { write( pfSrc, iCount, iDestOffset ); };
//! Add samples from a source to the buffer
/**
* Adds iCount samples from the given buffer starting at read position 0
* into the sample buffer beginning at given destination offset.
*
* @param pfSrc Source buffer / float array / vector
* @param iCount Number of samples to be added from source buffer into sample buffer
* @param iDestOffset Write position in sample buffer
*
* \@ote Make sure source buffer has iCount valid samples
*/
void AddSamples( const float* pfSrc, int iCount, int iDestOffset = 0 );
//! Samples aus einem anderen Puffer in den Puffer kopieren
/**
* Kopiert iCount Samples aus angegebenen Puffer beginnend bei Leseposition iSrcOffset
* in disen Puffer, dort beginnend ab Schreibposition iDestOffset.
*
* \param psbSrc Quellpuffer
* \param iCount Anzahl zu kopierender Samples
* \param iSrcOffset Leseposition im Quellpuffer
* \param iDestOffset Schreibposition in diesem Puffer
*
* \note Kein Schreiben ber das Pufferende hinaus!
*/
void write( const ITASampleBuffer* psbSrc, int iCount, int iSrcOffset = 0, int iDestOffset = 0 );
void write( const ITASampleBuffer& sbSrc, int iCount, int iSrcOffset = 0, int iDestOffset = 0 );
//! Zyklisches Lesen
/**
* Diese Methode erlaubt das zylische Lesen von Samples aus dem Puffer.
* Wenn die Leseanforderung das Ende der Puffers berschreitet wird das
* Lesen einfach am Anfang des Puffers fortgesetzt. Ntzlich ist diese
* Funktionalitt vorallem fr das Implementieren von Ringpuffern.
* Semantik ansonsten wie read().
*
* \param pfDest Zielarray
* \param iCount Anzahl zu kopierender Samples
* \param iSrcOffset Leseposition in diesem Puffer (SampleBuffer)
*
* TODO: Memory alignment fr SSE?
*/
void cyclic_read( float* pfDest, int iCount, int iSrcOffset = 0 ) const;
//! Zyklisches Schreiben
/**
* Diese Methode erlaubt das zylische Lesen von Samples aus dem Puffer.
* Wenn die Leseanforderung das Ende der Puffers berschreitet wird das
* Lesen einfach am Anfang des Puffers fortgesetzt. Ntzlich ist diese
* Funktionalitt vorallem fr das Implementieren von Ringpuffern.
* Semantik ansonsten wie read().
*
* \param pfSrc Quellarray
* \param iCount Anzahl zu kopierender Samples
* \param iDestOffset Schreibposition in diesem Puffer (SampleBuffer)
*
* TODO: Memory alignment fr SSE?
*/
void cyclic_write( const float* pfSrc, int iCount, int iDestOffset = 0 );
//! Zyklisches Schreiben
/**
* Diese Methode erlaubt das zylische Lesen von Samples aus dem Puffer.
* Wenn die Leseanforderung das Ende der Puffers berschreitet wird das
* Lesen einfach am Anfang des Puffers fortgesetzt. Ntzlich ist diese
* Funktionalitt vorallem fr das Implementieren von Ringpuffern.
* Semantik ansonsten wie read().
*
* \param psbSrc Quellpuffer
* \param iCount Anzahl zu kopierender Samples
* \param iSrcOffset Leseposition im Quellpuffer
* \param iDestOffset Schreibposition in diesem Puffer
*
* TODO: Memory alignment fr SSE?
*/
void cyclic_write( const ITASampleBuffer* psbSrc, int iCount, int iSrcOffset = 0, int iDestOffset = 0 );
void cyclic_write( const ITASampleBuffer& sbSrc, int iCount, int iSrcOffset = 0, int iDestOffset = 0 );
//! Cyclic shifting of samples
/**
* @param [in] iCount Shifts the samples in buffer by given count
*/
void CyclicShift( int iCount );
//! In-place Addition: Jedem Sample einen konstanten Wert addieren
void add_scalar( float fValue );
//! In-place Subtraktion: Jedem Sample einen konstanten Wert subtrahieren
void sub_scalar( float fValue );
//! In-place Multiplikation: Jedes Sample mit einem konstanten Wert multiplizieren
void mul_scalar( float fValue );
//! In-place Division: Jedes Sample durch einen konstanten Wert dividieren
void div_scalar( float fValue );
// TODO: Bereiche Addieren usw.
//! Paarweise alle Samples des gegebenen Puffers zu den Samples diesem addieren
/*
* - Mssen gleiche Lngen haben!
*/
void add_buf( const ITASampleBuffer* pSource, int iCount );
void add_buf( const ITASampleBuffer* pSource );
void sub_buf( const ITASampleBuffer* pSource );
void mul_buf( const ITASampleBuffer* pSource );
void div_buf( const ITASampleBuffer* pSource );
void add_buf_pos( const ITASampleBuffer* pSource, int iPos );
void add_buf_pos( float* fSource, int iSize, int iPos );
// Implementierung mittels Referenzen
void add_buf( const ITASampleBuffer& sbSource, int iCount );
void add_buf( const ITASampleBuffer& sbSource );
void sub_buf( const ITASampleBuffer& sbSource );
void mul_buf( const ITASampleBuffer& sbSource );
void div_buf( const ITASampleBuffer& sbSource );
// Spezial-Operatoren
// Werte eines anderen Puffers mit einer Konstante multiplizieren und dann hierauf addieren
// Semantik:
// for i from 0 to iCount-1 do
// this[dest_offset + i] += (scalar * source[src_offset + i])
//
// iSrcOffset = Leseposition im Quellpuffer
// iDestOffset = Schreibposition in diesem Puffer
// iCount = Anzahl Samples
void MulAdd( const ITASampleBuffer* pSource, float fScalar, int iSrcOffset, int iDestOffset, int iCount );
void MulAdd( const ITASampleBuffer& sbSource, float fScalar, int iSrcOffset, int iDestOffset, int iCount );
//! Spitzenwert suchen
/**
* Sucht den betragsgrten Wert im Puffer und gibt dessen Betragswert zurck.
* Auf Wunsch wird auch der Index der ersten Samples zurckgegeben, das diesen
* Spitzenwert erreichte (erste Fundstelle).
*/
float FindPeak( int* piPeakIndex = NULL );
//! Negieren (Multiplikation mit -1 bzw. Phasendrehungum 180)
void Negate( );
//! Normalize data
void Normalize( );
//! Calculate root-mean-square
/**
* @param[in] bPower If true, the RMS value is divided by the length of the buffer
*
* @return Root-Mean-Square value
*/
float RootMeanSquare( bool bPower = true ) const;
//! Read/Write Indizierungsoperator
float& operator[]( int iSample );
//! Read-only Indizierungsoperator
const float& operator[]( int iSample ) const;
//! Zuweisungsoperator
/**
* Dieser Operator weist dem Puffer alle Samples eines anderen Quellpuffers zu.
* Hierzu wird zunchst die Lnge des Puffer der des Quellpuffers angepasst.
* Anschlieend werden alle Samples kopiert.
*/
ITASampleBuffer& operator=( const ITASampleBuffer& rhs );
//! Arithemtische Operatoren (Aliase fr arithmetische Methoden - siehe oben)
ITASampleBuffer& operator+=( float rhs );
ITASampleBuffer& operator-=( float rhs );
ITASampleBuffer& operator*=( float rhs );
ITASampleBuffer& operator/=( float rhs );
ITASampleBuffer& operator+=( const ITASampleBuffer& rhs );
ITASampleBuffer& operator-=( const ITASampleBuffer& rhs );
ITASampleBuffer& operator*=( const ITASampleBuffer& rhs );
ITASampleBuffer& operator/=( const ITASampleBuffer& rhs );
//! Informationen ber den Puffer als Zeichenkette zurckgeben
std::string toString( ) const;
//! Werte als Zeichenkette zurckgeben
std::string ValuesToString( ) const;
void Load( const std::string& sFilePath );
void Load( const std::string& sFilePath, float& fSampleRate );
void Store( const std::string& sFilePath, const float fSampleRate = 44100.0f ) const;
private:
int m_iLength;
float* m_pfData;
ITASampleFrame* m_pParent;
friend class ITASampleFrame;
};
#endif // INCLUDE_WATCHER_ITA_SAMPLE_BUFFER