Aufgrund einer Störung des s3 Storage, könnten in nächster Zeit folgende GitLab Funktionen nicht zur Verfügung stehen: LFS, Container Registry, Job Artifacs, Uploads (Wiki, Bilder, Projekt-Exporte). Wir bitten um Verständnis. Es wird mit Hochdruck an der Behebung des Problems gearbeitet. Weitere Informationen zur Störung des Object Storage finden Sie hier: https://maintenance.itc.rwth-aachen.de/ticket/status/messages/59-object-storage-pilot

Commit 0d6ac2dc authored by Dipl.-Ing. Jonas Stienen's avatar Dipl.-Ing. Jonas Stienen
Browse files

Updating and merging

Merge branch 'develop' of https://git.rwth-aachen.de/ita/ITADataSources into develop

# Conflicts:
#	tests/ITAPortaudioTests/ITAPortaudioInterfaceRecorder.cpp
parents f8bc3cb5 f100667e
CMakeCache.txt
*.suo
CMakeFiles
cmake_minimum_required( VERSION 2.8 )
cmake_minimum_required(VERSION 3.1.0 FATAL_ERROR)
project( ITADataSources )
......@@ -10,6 +10,7 @@ include( VistaCommon )
vista_use_package( ITABase REQUIRED FIND_DEPENDENCIES )
vista_use_package( ASIO QUIET )
vista_use_package( Portaudio QUIET )
vista_use_package( JACK QUIET )
if( NOT DEFINED ITA_VISTA_BUILD_STATIC )
set( ITA_VISTA_BUILD_STATIC OFF CACHE BOOL "Build against static ViSTA libraries" )
......@@ -27,6 +28,10 @@ if( NOT DEFINED ITA_DATA_SOURCE_WITH_INTEGRATED_PORTAUDIO )
set( ITA_DATA_SOURCE_WITH_INTEGRATED_PORTAUDIO ${VPORTAUDIO_FOUND} CACHE BOOL "Build with Portaudio support" )
endif( NOT DEFINED ITA_DATA_SOURCE_WITH_INTEGRATED_PORTAUDIO )
if( NOT DEFINED ITA_DATA_SOURCE_WITH_INTEGRATED_JACK )
set( ITA_DATA_SOURCE_WITH_INTEGRATED_JACK ${VJACK_FOUND} CACHE BOOL "Build with JACK2 support" )
endif( NOT DEFINED ITA_DATA_SOURCE_WITH_INTEGRATED_JACK )
# includes
include_directories( "include" )
......@@ -72,6 +77,8 @@ set( ITADataSourcesSources
"src/ITAStreamYJunction.cpp"
)
list( APPEND ITADataSourcesSources "src/ITADataSourceUtils.cpp" )
# Filter windows-only components
if( WIN32 )
list( APPEND ITADataSourcesHeader "include/ITAStreamPump.h" "include/ITADataSourceUtils.h" )
......@@ -83,11 +90,17 @@ if( VASIO_FOUND AND ITA_DATA_SOURCE_WITH_INTEGRATED_ASIO )
list( APPEND ITADataSourcesSources "src/ITAAsioInterface.cpp" )
add_definitions( -DIEEE754_64FLOAT=1 )
endif( VASIO_FOUND AND ITA_DATA_SOURCE_WITH_INTEGRATED_ASIO )
if( VPORTAUDIO_FOUND AND ITA_DATA_SOURCE_WITH_INTEGRATED_PORTAUDIO )
list( APPEND ITADataSourcesHeader "include/ITAPortaudioInterface.h" )
list( APPEND ITADataSourcesSources "src/ITAPortaudioInterface.cpp" )
endif( VPORTAUDIO_FOUND AND ITA_DATA_SOURCE_WITH_INTEGRATED_PORTAUDIO )
if( VJACK_FOUND AND ITA_DATA_SOURCE_WITH_INTEGRATED_JACK )
list( APPEND ITADataSourcesHeader "include/ITAJACKInterface.h" )
list( APPEND ITADataSourcesSources "src/ITAJACKInterface.cpp" )
endif( VJACK_FOUND AND ITA_DATA_SOURCE_WITH_INTEGRATED_JACK )
# compiler settings
if( ITA_VISTA_BUILD_STATIC )
......@@ -115,6 +128,11 @@ endif( NOT WIN32)
add_library( ITADataSources ${ITADataSourcesHeader} ${ITADataSourcesSources} )
target_link_libraries( ITADataSources ${VISTA_USE_PACKAGE_LIBRARIES} )
#target_compile_features(ITADataSources PRIVATE cxx_range_for)
add_definitions( -std=c++11 )
set( BUILD_SHARED_LIBS ${BUILD_SHARED_LIBS_TEMP} )
......
/*
* ----------------------------------------------------------------
*
* ITA core libs
* (c) Copyright Institute of Technical Acoustics (ITA)
* RWTH Aachen University, Germany, 2015-2016
*
* ----------------------------------------------------------------
* ____ __________ _______
* // / //__ ___/ // _ |
* // / // / // /_| |
* // / // / // ___ |
* //__/ //__/ //__/ |__|
*
* ----------------------------------------------------------------
*
*/
// $Id: ITAJACKInterface.h $
#pragma once
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#include <queue>
#include <functional>
#include <jack/jack.h>
// Forward declaration of ITADatasource
class ITADatasource;
// Forward declarations of callbacks
int ITAJackXRUN(void *arg);
void ITAJackMsg(const char *msg);
void ITAJackShutdown (void *arg);
void ITAJackPortConnected(jack_port_id_t a, jack_port_id_t b, int connect, void* arg);
void ITAJackPortRegistered(jack_port_id_t port_id, int reg, void *arg);
/*! ITAJACKInterface
*
*
*
* see also \ITADatasources
*
*/
class ITAJACKInterface {
public:
//! ITAPortaudio error code table
enum ITA_JACK_ERRORCODE {
//! Portaudio/ITAPortaudio no error
ITA_JACK_NO_ERROR=0,
ITA_JACK_ERROR=1,
ITA_JACK_IS_OPEN,
ITA_JACK_IS_STARTED,
ITA_JACK_OPEN_FAILED,
ITA_JACK_NOT_INITIALIZED,
ITA_JACK_UNMATCHED_CHANNELS,
ITA_JACK_NO_PLAYBACK_DATASOURCE,
ITA_JACK_NO_RECORD_DATASOURCE,
ITA_JACK_IS_NOT_OPEN,
ITA_JACK_INTERNAL_ERROR,
ITA_JACK_STREAM_IS_STOPPED,
ITA_JACK_UNMATCHED_BUFFER_SIZE,
ITA_JACK_UNMATCHED_SAMPLE_RATE
};
//! If no blockSize given the interface will use blockSize of JACK server
ITAJACKInterface(int blockSize = -1);
~ITAJACKInterface();
//! Initialize JACK
ITA_JACK_ERRORCODE Initialize(const std::string& clientName);
//! Finalize JACK
/**
* This also deletes the record datasource.
*/
ITA_JACK_ERRORCODE Finalize();
//! Opens a JACK client
ITA_JACK_ERRORCODE Open();
//! Closes the JACK client
ITA_JACK_ERRORCODE Close();
//! Start JACK client
ITA_JACK_ERRORCODE Start();
//! Stop JACK client
ITA_JACK_ERRORCODE Stop();
inline int GetNumInputChannels() const {
return m_bInitialized ? m_iNumInputChannels : 0;
}
inline int GetNumOutputChannels() const {
return m_bInitialized ? m_iNumOutputChannels : 0;
}
inline int GetSampleRate() const {
return m_dSampleRate;
}
inline int GetBlockSize() const { return m_iBufferSize; }
inline int SetBlockSize(int blockSize);
//! Set the playback data source
/**
* \note Enables playback, see IsPlaybackEnabled() and SetPlaybackEnabled()
*/
ITA_JACK_ERRORCODE SetPlaybackDatasource(ITADatasource* pidsDatasource);
//! Get the recording data source
/**
* This also creates the record datasource if not already present.
* \note Enables recording, see IsRecordingEnabled() and SetRecordingEnabled()
*
* \see Finalize()
*/
ITADatasource* GetRecordDatasource();
//! Returns a human readable error code string
static std::string GetErrorCodeString(ITA_JACK_ERRORCODE err);
inline static jack_client_t *GetJackClient() { return s_jackClient; }
void printInfo();
struct ITAJackUserData {
ITADatasource* pdsPlaybackDatasource; //!< ITADatasource playback datasource
ITADatasource* pdsRecordDatasource; //!< ITADatasource record datasource
std::vector<jack_port_t *> input_ports, output_ports;
uint64_t num_xruns;
uint64_t num_samples;
ITAJackUserData() : num_xruns(0), num_samples(0), pdsPlaybackDatasource(nullptr), pdsRecordDatasource(nullptr)
{
}
};
private:
static jack_client_t *s_jackClient;
jack_client_t *m_jackClient;
int m_iBufferSize;
double m_dSampleRate;
ITAJackUserData m_oUserData; //!< ITAPortaudioDatasource user data
bool m_bInitialized; //!< Portaudio initialization status
bool m_bOpen; //!< Portaudio open status
bool m_bStreaming; //!< Portaudio streaming status
int m_iNumInputChannels; //!< Number of input channels
int m_iNumOutputChannels; //!< Number of output channels
ITA_JACK_ERRORCODE m_iError; //!< Last error
bool connectJackPorts(bool connect);
};
......@@ -259,7 +259,7 @@ private:
std::vector< const float* > vpfInputData; //!< Pointers to the next stream blocks
InputDesc( const int iChannels, const int iBlockLength )
: vpfInputData( iChannels, NULL )
: vpfInputData( iChannels, nullptr )
{
this->iChannels = iChannels;
fCurrentGain = 1.0F, fNewGain = 1.0F;
......
......@@ -11,8 +11,13 @@
#include <cmath>
#include <string>
#include <vector>
#include <cstring>
#include <algorithm>
#ifdef WIN32
#include <windows.h>
#else
#include <unistd.h>
#endif
void WriteFromDatasourceToBuffer(ITADatasource* pSource,
......@@ -30,26 +35,34 @@ void WriteFromDatasourceToBuffer(ITADatasource* pSource,
unsigned int uiBlocklength = pSource->GetBlocklength();
ITAStreamInfo siState;
HANDLE hTimer=0;
long periodMs = (long)ceil(uiBlocklength / dSamplerate * 1000);
#ifdef _WIN32
HANDLE hTimer=0;
if (bOnline) {
// Timer erzeugen
if (FAILED(hTimer = CreateWaitableTimer(NULL, false, NULL)))
if (FAILED(hTimer = CreateWaitableTimer(NULL, false, NULL)))
ITA_EXCEPT1(UNKNOWN, "Timer konnte nicht erzeugt werden");
LARGE_INTEGER liDueTime;
liDueTime.QuadPart=0;
long ms = (long) ceil(uiBlocklength/dSamplerate*1000);
SetWaitableTimer(hTimer, &liDueTime, ms, NULL, NULL, true);
liDueTime.QuadPart = 0;
SetWaitableTimer(hTimer, &liDueTime, periodMs, NULL, NULL, true);
}
#endif
try {
unsigned int n=0;
float fProgress = 0.0f;
while (n < uiNumberOfSamples)
{
#ifdef _WIN32
// Warten
if (bOnline) WaitForSingleObject(hTimer, INFINITE);
#else
if (bOnline) usleep(periodMs * 1000);
#endif
// Daten von der Quelle holen
for (unsigned int i=0; i<uiChannels; i++) {
......@@ -87,15 +100,19 @@ void WriteFromDatasourceToBuffer(ITADatasource* pSource,
}
}
} catch (...) {
#ifdef _WIN32
if (bOnline) CloseHandle(hTimer);
#endif
throw;
}
if (bDisplayProgress)
printf("WriteFromDatasourceToBuffer: 100,00%% geschrieben");
#ifdef _WIN32
if (bOnline)
CloseHandle(hTimer);
#endif
}
void WriteFromDatasourceToFile(ITADatasource* pSource,
......@@ -125,6 +142,9 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
ITAAudiofileWriter* writer = ITAAudiofileWriter::create(sFilename, props);
ITAStreamInfo siState;
long periodMs = (long)ceil(uiBlocklength / dSamplerate * 1000);
#ifdef _WIN32
HANDLE hTimer=0;
if (bOnline) {
......@@ -136,16 +156,21 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
LARGE_INTEGER liDueTime;
liDueTime.QuadPart=0;
long ms = (long) ceil(uiBlocklength/dSamplerate*1000);
SetWaitableTimer(hTimer, &liDueTime, ms, NULL, NULL, true);
SetWaitableTimer(hTimer, &liDueTime, periodMs, NULL, NULL, true);
}
#endif
try {
unsigned int n=0;
float fProgress = 0.0;
while (n < uiNumberOfSamples) {
#ifdef _WIN32
// Warten
if (bOnline) WaitForSingleObject(hTimer, INFINITE);
#else
if (bOnline) usleep(periodMs * 1000);
#endif
// Daten von der Quelle holen
for (unsigned int i=0; i<uiChannels; i++) {
......@@ -168,7 +193,7 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
siState.dTimecode = (double) (siState.nSamples) / dSamplerate;
// Daten schreiben
writer->write(__min(uiBlocklength, (uiNumberOfSamples - n)), vpfData);
writer->write((std::min)(uiBlocklength, (uiNumberOfSamples - n)), vpfData);
n += uiBlocklength;
......@@ -183,7 +208,9 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
}
}
} catch (...) {
#ifdef _WIN32
if (bOnline) CloseHandle(hTimer);
#endif
delete writer;
throw;
}
......@@ -191,8 +218,10 @@ void WriteFromDatasourceToFile(ITADatasource* pSource,
if (bDisplayProgress)
printf("WriteFromDatasourceToFile: 100,00%% geschrieben\r");
#ifdef _WIN32
if (bOnline)
CloseHandle(hTimer);
#endif
delete writer;
}
......
#include "ITAJACKInterface.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vector>
#include <math.h>
#include <signal.h>
#include <future>
#include <ITADataSource.h>
#include <ITADataSourceRealization.h>
#include <ITAStreamInfo.h>
#include <iostream>
static int ITAJackProcess (jack_nframes_t nframes, void *arg);
void connectNewPortToInput(jack_port_t * port, ITAJACKInterface::ITAJackUserData* userData);
jack_client_t *ITAJACKInterface::s_jackClient = NULL;
static void signal_handler(int sig)
{
jack_client_t *client = ITAJACKInterface::GetJackClient();
if(client != NULL) {
fprintf(stderr, "JACKInterface: Closing client ...\n");
jack_client_close(client);
}
fprintf(stderr, "JACKInterface: signal received, exiting ...\n");
exit(0);
}
class ITAJackSource : public ITADatasourceRealization {
public:
ITAJackSource(int iChannels, double dSamplerate, int iBufferSize)
: ITADatasourceRealization((unsigned int) iChannels, dSamplerate, (unsigned int) iBufferSize, 16) {}
};
ITAJACKInterface::ITAJACKInterface(int blockSize)
:m_iBufferSize(blockSize)
{
m_jackClient = NULL;
m_iNumInputChannels = -1;
m_iNumOutputChannels = -1;
m_bInitialized = false;
m_bOpen = false;
m_bStreaming = false;
m_iError = ITA_JACK_NO_ERROR;
}
ITAJACKInterface::~ITAJACKInterface() { }
ITAJACKInterface::ITA_JACK_ERRORCODE ITAJACKInterface::Initialize(const std::string& clientName) {
if (m_bInitialized)
return ITA_JACK_NO_ERROR; // allow multiple Init() calls
if (m_bOpen)
return ITA_JACK_IS_OPEN;
if (m_bStreaming)
return ITA_JACK_IS_STARTED;
int i;
jack_options_t options = JackNullOption; // JackNoStartServer; //
jack_status_t status;
jack_set_error_function(ITAJackMsg);
jack_set_info_function(ITAJackMsg);
m_jackClient = jack_client_open (clientName.c_str(), options, &status);
if (m_jackClient == NULL) {
fprintf (stderr, "jack_client_open() failed, "
"status = 0x%2.0x\n", status);
if (status & JackServerFailed) {
fprintf (stderr, "Unable to connect to JACK server\n");
}
return ITA_JACK_OPEN_FAILED;
}
s_jackClient = m_jackClient;
if (status & JackServerStarted) {
fprintf (stderr, "JACK server started\n");
}
if (status & JackNameNotUnique) {
auto clientName = std::string(jack_get_client_name(m_jackClient));
fprintf (stderr, "unique name `%s' assigned\n", clientName.c_str());
}
jack_set_process_callback (m_jackClient, ITAJackProcess, &m_oUserData);
jack_set_xrun_callback(m_jackClient, ITAJackXRUN, &m_oUserData);
jack_set_port_registration_callback(m_jackClient, ITAJackPortRegistered, &m_oUserData);
jack_on_shutdown (m_jackClient, ITAJackShutdown, 0);
jack_set_port_connect_callback(m_jackClient, ITAJackPortConnected, &m_oUserData);
if (m_iBufferSize > 0)
jack_set_buffer_size(m_jackClient, m_iBufferSize);
else
m_iBufferSize = jack_get_buffer_size(m_jackClient);
m_dSampleRate = jack_get_sample_rate(m_jackClient);
// get physical ports
const char** out_ports = jack_get_ports(m_jackClient, NULL, NULL, JackPortIsPhysical|JackPortIsOutput);
const char** in_ports = jack_get_ports(m_jackClient, NULL, NULL, JackPortIsPhysical|JackPortIsInput);
m_iNumOutputChannels = 0;
m_iNumInputChannels = 0;
while (out_ports[m_iNumOutputChannels]) m_iNumOutputChannels++;
while (in_ports[m_iNumInputChannels]) m_iNumInputChannels++;
jack_free(out_ports);
jack_free(in_ports);
/* install a signal handler to properly quits jack client */
#ifdef WIN32
signal(SIGINT, signal_handler);
signal(SIGABRT, signal_handler);
signal(SIGTERM, signal_handler);
#else
signal(SIGQUIT, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGHUP, signal_handler);
signal(SIGINT, signal_handler);
#endif
m_bInitialized = true;
return ITA_JACK_NO_ERROR;
}
ITAJACKInterface::ITA_JACK_ERRORCODE ITAJACKInterface::Finalize() {
if (!m_bInitialized)
return ITA_JACK_NOT_INITIALIZED;
if (m_bStreaming)
return ITA_JACK_IS_STARTED;
m_iError = ITA_JACK_NO_ERROR;
for(int i = 0; i < m_iNumInputChannels; i++)
jack_port_unregister(m_jackClient, m_oUserData.input_ports[i]);
for(int i = 0; i < m_iNumOutputChannels; i++)
jack_port_unregister(m_jackClient, m_oUserData.output_ports[i]);
jack_client_close(m_jackClient);
if (m_iError == ITA_JACK_NO_ERROR)
m_bInitialized = false;
if (m_oUserData.pdsRecordDatasource != NULL) {
delete m_oUserData.pdsRecordDatasource;
m_oUserData.pdsRecordDatasource = NULL;
}
return m_iError;
}
// Actually does nothing
ITAJACKInterface::ITA_JACK_ERRORCODE ITAJACKInterface::Open() {
if (!m_bInitialized) return ITA_JACK_NOT_INITIALIZED;
if (m_bOpen) return ITA_JACK_IS_OPEN;
m_bOpen = true;
return m_iError;
}
// Actually does nothing
ITAJACKInterface::ITA_JACK_ERRORCODE ITAJACKInterface::Close() {
if (!m_bInitialized)
return ITA_JACK_NOT_INITIALIZED;
if (!m_bOpen)
return ITA_JACK_IS_NOT_OPEN;
m_bOpen = false;
return ITA_JACK_NO_ERROR;
}
bool ITAJACKInterface::connectJackPorts(bool connect)
{
char portname[64]; // enough to hold all numbers up to 64-bits
auto func = connect ? &jack_connect : &jack_disconnect;
int i;
for (i=0; i < (std::min)((size_t)m_iNumInputChannels, m_oUserData.input_ports.size()); i++) {
sprintf(portname, "system:capture_%d", i+1);
if (func(m_jackClient, portname, jack_port_name(m_oUserData.input_ports[i]))) {
fprintf(stderr,"Could not %s input ports %s and %s!\n", connect ? "connect" : "disconnect", portname, jack_port_name(m_oUserData.input_ports[i]));
}
}
for (i=0; i < (std::min)((size_t)m_iNumOutputChannels, m_oUserData.output_ports.size()); i++) {
sprintf(portname, "system:playback_%d", i+1);
if (connect ? jack_connect(m_jackClient, jack_port_name(m_oUserData.output_ports[i]), portname)
: jack_disconnect(m_jackClient, jack_port_name(m_oUserData.output_ports[i]), portname)) {
fprintf(stderr,"Could not %s output ports %s and %s!\n", connect ? "connect" : "disconnect", jack_port_name(m_oUserData.output_ports[i]), portname);
}
}
return true;
}
ITAJACKInterface::ITA_JACK_ERRORCODE ITAJACKInterface::Start() {
if (m_bStreaming)
return ITA_JACK_IS_STARTED;
if (!m_bInitialized)
return ITA_JACK_NOT_INITIALIZED;