Testing and updating ita data sink (write to buffer / audio file)

parent 3992ffe3
......@@ -38,12 +38,13 @@ class ITADatasource;
* welche die Audiodaten in eine Datei schreibt. Der Datentransfer muss
* selbst initiiert werden.
*/
class ITA_DATA_SOURCES_API ITABufferDatasink {
class ITA_DATA_SOURCES_API ITABufferDataSink
{
public:
//! Konstruktor (Eigene Pufferverwaltung)
/**
* Dieser Konstruktor erzeugt eine Puffer-Datensenke. Die Puffer zum Speichern
* der Audiodaten werden bei diesem Konstruktor selbst erzeugt und von der
* der Audiodaten werden bei diesem Konstruktor selbst erzeugt und von der
* Datenquelle verwaltet. Mit dem Aufruf des Destruktors werden die Puffer
* freigeben. Die Pufferzeiger knnen mit der Methode GetBuffers() abgerufen werden.
*
......@@ -52,8 +53,7 @@ public:
*
* \note Bei Fehlern werden ITAExceptions aufgelst.
*/
ITABufferDatasink(ITADatasource* pdsSource,
unsigned int uiBuffersize);
ITABufferDataSink( ITADatasource* pdsSource, int uiBuffersize );
//! Konstruktor (Fremdverwaltete Puffer)
/**
......@@ -66,24 +66,22 @@ public:
*
* \note Bei Fehlern werden ITAExceptions aufgelst.
*/
ITABufferDatasink(ITADatasource* pdsSource,
std::vector<float*> vpfBuffer,
unsigned int uiBuffersize);
ITABufferDataSink( ITADatasource* pdsSource, std::vector< float* > vpfBuffer, int uiBuffersize );
//! Destruktor
virtual ~ITABufferDatasink();
virtual ~ITABufferDataSink();
//! Puffergre [Anzahl Samples] zurckgeben
unsigned int GetBuffersize() const;
int GetBuffersize() const;
//! Pufferzeiger zurckgeben
std::vector<float*> GetBuffers() const;
std::vector< float* > GetBuffers() const;
//! Schreibposition in den Puffern zurckgeben
unsigned int GetWriteCursor() const;
//! Schreibposition in den Puffern setzen
void SetWriteCursor(unsigned int uiWriteCursor);
void SetWriteCursor( unsigned int uiWriteCursor );
//! Audiodaten transferrieren
/**
......@@ -91,9 +89,9 @@ public:
* und schreibt diese in die Audiodatei. Hierbei wird die Anzahl Samples
* auf das nchstgrere Vielfache der Blocklnge aufgerundet.
*/
void Transfer(unsigned int uiSamples);
void Transfer( unsigned int uiSamples );
private:
private:
ITADatasource* m_pdsSource; // Datenquelle
std::vector<float*> m_vpfBuffer; // Puffervektor
std::vector<const float*> m_vpfBufferX; // Export-Puffervektor (const)
......
......@@ -11,92 +11,96 @@
#include <memory.h>
#endif
ITABufferDatasink::ITABufferDatasink( ITADatasource* pdsSource, unsigned int uiBuffersize )
: m_pdsSource( pdsSource )
, m_vpfBuffer( pdsSource->GetNumberOfChannels(), NULL )
, m_vpfBufferX( pdsSource->GetNumberOfChannels(), NULL )
, m_uiBuffersize( uiBuffersize )
, m_bManagedBuffer( true )
ITABufferDataSink::ITABufferDataSink( ITADatasource* pdsSource, int iBuffersize )
: m_pdsSource( pdsSource )
, m_vpfBuffer( pdsSource->GetNumberOfChannels(), NULL )
, m_vpfBufferX( pdsSource->GetNumberOfChannels(), NULL )
, m_uiBuffersize( iBuffersize )
, m_bManagedBuffer( true )
{
// Puffer erzeugen
for (unsigned int i=0; i<pdsSource->GetNumberOfChannels(); i++) {
m_vpfBuffer[i] = fm_falloc(uiBuffersize, true);
m_vpfBufferX[i] = (const float*) m_vpfBuffer[i];
for( unsigned int i = 0; i < pdsSource->GetNumberOfChannels(); i++ )
{
m_vpfBuffer[ i ] = fm_falloc( iBuffersize, true );
m_vpfBufferX[ i ] = ( const float* ) m_vpfBuffer[ i ];
}
m_uiWriteCursor = 0;
}
ITABufferDatasink::ITABufferDatasink( ITADatasource* pdsSource, std::vector<float*> vpfBuffer, unsigned int uiBuffersize )
: m_pdsSource( pdsSource )
, m_vpfBuffer( vpfBuffer )
, m_vpfBufferX( pdsSource->GetNumberOfChannels(), NULL )
, m_uiBuffersize( uiBuffersize )
, m_bManagedBuffer( false )
ITABufferDataSink::ITABufferDataSink( ITADatasource* pdsSource, std::vector<float*> vpfBuffer, int iBuffersize )
: m_pdsSource( pdsSource )
, m_vpfBuffer( vpfBuffer )
, m_vpfBufferX( pdsSource->GetNumberOfChannels(), NULL )
, m_uiBuffersize( iBuffersize )
, m_bManagedBuffer( false )
{
// Parameter prfen
if (pdsSource->GetNumberOfChannels() != (unsigned int) vpfBuffer.size())
ITA_EXCEPT1(INVALID_PARAMETER, "Number of buffers does not meet the datasource's number of channels");
if( pdsSource->GetNumberOfChannels() != ( unsigned int ) vpfBuffer.size() )
ITA_EXCEPT1( INVALID_PARAMETER, "Number of buffers does not meet the datasource's number of channels" );
// Puffer erzeugen
for (unsigned int i=0; i<pdsSource->GetNumberOfChannels(); i++)
m_vpfBufferX[i] = (const float*) m_vpfBuffer[i];
for( unsigned int i = 0; i < pdsSource->GetNumberOfChannels(); i++ )
m_vpfBufferX[ i ] = ( const float* ) m_vpfBuffer[ i ];
m_uiWriteCursor = 0;
}
ITABufferDatasink::~ITABufferDatasink() {
if (m_bManagedBuffer)
std::for_each(m_vpfBuffer.begin(), m_vpfBuffer.end(), fm_free);
ITABufferDataSink::~ITABufferDataSink() {
if( m_bManagedBuffer )
std::for_each( m_vpfBuffer.begin(), m_vpfBuffer.end(), fm_free );
}
unsigned int ITABufferDatasink::GetBuffersize() const {
int ITABufferDataSink::GetBuffersize() const
{
return m_uiBuffersize;
}
std::vector<float*> ITABufferDatasink::GetBuffers() const {
std::vector<float*> ITABufferDataSink::GetBuffers() const {
return m_vpfBuffer;
}
unsigned int ITABufferDatasink::GetWriteCursor() const {
unsigned int ITABufferDataSink::GetWriteCursor() const {
return m_uiWriteCursor;
}
void ITABufferDatasink::SetWriteCursor(unsigned int uiWriteCursor) {
m_uiWriteCursor = (std::min)(uiWriteCursor, m_uiBuffersize);
void ITABufferDataSink::SetWriteCursor( unsigned int uiWriteCursor ) {
m_uiWriteCursor = ( std::min )( uiWriteCursor, m_uiBuffersize );
}
void ITABufferDatasink::Transfer(unsigned int uiSamples) {
void ITABufferDataSink::Transfer( unsigned int uiSamples )
{
/*
* Hinweis: Auch wenn der Puffer schon vollgeschrieben wurde,
* so werden trotzdem die Daten von der Datenquelle
* so werden trotzdem die Daten von der Datenquelle
* geholt und dann ins Nirvana geworfen...
*/
if (m_pdsSource) {
// Anzahl der zu transferrierenden Blcke bestimmen
unsigned int b = m_pdsSource->GetBlocklength();
unsigned int n = uprdivu(uiSamples, b);
for (unsigned int i=0; i<n; i++) {
// Anzahl der zu speichernden Samples bestimmen
unsigned int m = (std::min)(m_uiBuffersize - m_uiWriteCursor, b);
for (unsigned int j=0; j<m_pdsSource->GetNumberOfChannels(); j++) {
const float* pfSrc = m_pdsSource->GetBlockPointer(j, &m_siState);
if (m > 0) {
if (pfSrc)
memcpy(m_vpfBuffer[j] + m_uiWriteCursor, pfSrc, m*sizeof(float));
else
memset(m_vpfBuffer[j] + m_uiWriteCursor, 0, m*sizeof(float));
}
if( !m_pdsSource )
return;
unsigned int n = uprdivu( uiSamples, m_pdsSource->GetBlocklength() ); // Number of block increments until data is completely transferred
// Iterate over blocks
for( unsigned int i = 0; i < n; i++ )
{
for( int j = 0; j < int( m_pdsSource->GetNumberOfChannels() ); j++ )
{
const float* pfSrc = m_pdsSource->GetBlockPointer( j, &m_siState );
unsigned int m = ( std::min )( m_uiBuffersize - m_uiWriteCursor, m_pdsSource->GetBlocklength() ); // One sample block or less
if( m > 0 )
{
if( pfSrc )
memcpy( m_vpfBuffer[ j ] + m_uiWriteCursor, pfSrc, m*sizeof( float ) );
else
memset( m_vpfBuffer[ j ] + m_uiWriteCursor, 0, m*sizeof( float ) );
}
m_pdsSource->IncrementBlockPointer();
m_uiWriteCursor += m;
m_siState.nSamples += m_pdsSource->GetBlocklength();
m_siState.dTimecode = ( double ) ( m_siState.nSamples ) / m_pdsSource->GetSampleRate();
m_siState.nSamples += b;
m_siState.dTimecode = (double) (m_siState.nSamples) / m_pdsSource->GetSampleRate();
m_pdsSource->IncrementBlockPointer();
}
}
}
}
// $Id: ITAPortaudioInterfaceRecorder.cpp 2333 2012-03-05 14:21:39Z stienen $
#include <ITAPortaudioInterface.h>
#include <ITADataSource.h>
//#include <ITADatasourceUtils.h>
#include <ITABufferDataSink.h>
#include <ITASampleFrame.h>
#include <iostream>
#include <string>
#include <ITADatasourceUtils.h>
#include <ITAPortaudioInterface.h>
#include <vector>
static double g_dSampleRate = 44.1e3;
static int g_iBlockSize = 512;
static std::string g_sOutputFileName = "ITAPA_Record.wav";
float g_fRecordingTime = 5; // Seconds
static double dSampleRate = 44.1e3;
static int iBlockSize = 512;
static std::string sOutputFileName = "ITAPA_Record.wav";
float fRecordingTime = 5; // Seconds
void record()
{
void record() {
ITAPortaudioInterface ITAPA(dSampleRate, iBlockSize);
ITAPortaudioInterface ITAPA( g_dSampleRate, g_iBlockSize );
int iInputDevice = ITAPA.GetDefaultInputDevice();
//iInputDevice = 4;
ITAPortaudioInterface::ITA_PA_ERRORCODE err;
err = ITAPA.Initialize(iInputDevice);
ITAPA.SetPlaybackEnabled(false);
ITAPA.SetRecordEnabled(true);
err = ITAPA.Initialize( iInputDevice );
ITAPA.SetPlaybackEnabled( false );
ITAPA.SetRecordEnabled( true );
ITADatasource* pdsRecordDatasource = ITAPA.GetRecordDatasource();
ITAPA.Open();
unsigned int nRecordSamples = ( unsigned int ) ( 5 * g_dSampleRate );
ITASampleFrame sfRecordData( pdsRecordDatasource->GetNumberOfChannels(), nRecordSamples, true );
std::vector< float* > vpfRecordData( sfRecordData.channels() );
for( int i = 0; i < sfRecordData.channels(); i++ )
vpfRecordData[ i ] = sfRecordData[ i ].data();
ITAPA.Start();
WriteFromDatasourceToFile(pdsRecordDatasource, sOutputFileName, (unsigned int)(5*dSampleRate), 1.0, true, true);
ITABufferDataSink oBufferRec( pdsRecordDatasource, vpfRecordData, g_iBlockSize );
oBufferRec.Transfer( nRecordSamples );
//WriteFromDatasourceToFile( pdsRecordDatasource, sOutputFileName, (unsigned int)(5*g_dSampleRate), 1.0, true, true );
ITAPA.Stop();
ITAPA.Close();
ITAPA.Finalize();
sfRecordData.Store( g_sOutputFileName, g_dSampleRate );
return;
}
int main(int argc,char *argv[]) {
int main( int , char** )
{
std::cout << "Starting recording ..." << std::endl;
record();
......
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