Commit 196df527 authored by llea's avatar llea

PortAudio library integration instead of alsa and oss

parent 7d410955
SFLphone (0.3.1) / 2005-05-27 SFLphone (0.3.1) / 2005-06-01
* Add PortAudio library to make easy sound portability
* Reorganisation of SFLphone architecture * Reorganisation of SFLphone architecture
* Handle error messages on screen * Handle error messages on screen
* Handle refused call * Handle refused call
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
# Author: Laurielle Lea (laurielle.lea@savoirfairelinux.com) # Author: Laurielle Lea (laurielle.lea@savoirfairelinux.com)
# #
all: all:
cd stund; make
cd src/audio/portaudio; make
cd src/audio/gsm ; make cd src/audio/gsm ; make
cd src; make cd src; make
...@@ -14,6 +16,8 @@ uninstall: ...@@ -14,6 +16,8 @@ uninstall:
cd src; make uninstall cd src; make uninstall
clean: clean:
cd src; make clean cd stund; make clean
cd src/audio/portaudio; make clean
cd src/audio/gsm ; make clean cd src/audio/gsm ; make clean
cd src; make clean
...@@ -33,10 +33,7 @@ CLASSIC_DIRS=/usr:/usr/local:/opt ...@@ -33,10 +33,7 @@ CLASSIC_DIRS=/usr:/usr/local:/opt
usage () { usage () {
echo "Usage: $0 [options]" echo "Usage: $0 [options]"
echo "Options: echo "Options:
-prefix DIR Set install prefix -prefix DIR Set install prefix"
-oss Enable OSS support
-alsa Enable ALSA support
-macosx Enable MacOSX audio support [Not supported yet]"
} }
# Check if $1 is contained in $PATH-style $2. Optionally $3 is "-p" to print # Check if $1 is contained in $PATH-style $2. Optionally $3 is "-p" to print
...@@ -83,11 +80,11 @@ do ...@@ -83,11 +80,11 @@ do
shift 2 shift 2
;; ;;
-oss) -oss)
DEFVARS="-DOSS ${DEFVARS}" DEFVARS="-DAUDIO_OSS ${DEFVARS}"
shift shift
;; ;;
-alsa) -alsa)
DEFVARS="-DALSA ${DEFVARS}" DEFVARS="-DAUDIO_ALSA ${DEFVARS}"
shift shift
;; ;;
-help|--help|-h) -help|--help|-h)
......
...@@ -17,13 +17,31 @@ SKINS = skins ...@@ -17,13 +17,31 @@ SKINS = skins
RINGS = rings RINGS = rings
METAL_SKINS = metal METAL_SKINS = metal
INCPATH = -I. -I$(QTDIR)/include -I$(CCPPDIR)/include/cc++2 -I$(CCRTPDIR)/include -I$(OSIPDIR)/include -I$(EXOPSIP)/include -I/usr/include -Iaudio/gsm # Platform-specific variables
HOSTMACH = $(shell uname -m | sed -e 's/ //g')
ifeq (${HOSTSYSTEM},PowerMacintosh)
MACHOPTS=-mpowerpc
HOSTDEFS=-DGUI_TEXT1 -DAUDIO_MACOSX
else
HOSTSYS = $(shell uname -s)
endif
ifeq (${HOSTSYS},Linux)
HOSTMACH = $(shell uname -m | sed -e 's/i.86/i386/')
HOSTLIBS=-lX11 -lXext -lasound -lqt-mt
# HOSTDEFS=-DGUI_TEXT1 -DAUDIO_OSS # eventually
HOSTDEFS=-DGUI_QT -DAUDIO_ALSA
ifeq (${HOSTMACH},i386)
MACHOPTS=-march=i386
endif
endif
CXXFLAGS = -pipe -Wall -W -g -pipe -march=i386 -mcpu=i686 -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT -fpermissive -Wno-deprecated $(INCPATH) INCPATH = -I. -I$(QTDIR)/include -I$(CCPPDIR)/include/cc++2 -I$(CCRTPDIR)/include -I$(OSIPDIR)/include -I$(EXOPSIP)/include -I/usr/include -Iaudio/gsm -Iaudio/portaudio/pa_common
CXXFLAGS = -pipe -Wall -W -g $(MACHOPTS) -pipe -DQT_NO_DEBUG -DQT_SHARED -DQT_THREAD_SUPPORT -fpermissive -Wno-deprecated $(INCPATH)
LIBS=-L$(QTDIR)/lib -L/usr/X11R6/lib -lqt-mt -lXext -lX11 -lm -L/opt/lib -losip2 -leXosip -lccrtp1 -lasound `$(CCPPDIR)/bin/ccgnu2-config --flags --stdlibs` LIBS=-L$(QTDIR)/lib -L/usr/X11R6/lib -lm -L/opt/lib -losip2 -leXosip -lccrtp1 $(HOSTLIBS) `$(CCPPDIR)/bin/ccgnu2-config --flags --stdlibs`
EXTRALIBS=audio/gsm/libgsm.a EXTRALIBS=audio/gsm/libgsm.a audio/portaudio/lib/libportaudio.a
CONFIGURE_CONF=$(shell ls ../configure.conf) CONFIGURE_CONF=$(shell ls ../configure.conf)
...@@ -35,6 +53,7 @@ OBJS = \ ...@@ -35,6 +53,7 @@ OBJS = \
audio/audiodrivers.o \ audio/audiodrivers.o \
audio/audiodriversalsa.o \ audio/audiodriversalsa.o \
audio/audiodriversoss.o \ audio/audiodriversoss.o \
audio/audiodriversportaudio.o \
audio/audiortp.o \ audio/audiortp.o \
audio/dtmf.o \ audio/dtmf.o \
audio/dtmfgenerator.o \ audio/dtmfgenerator.o \
...@@ -82,8 +101,8 @@ OBJS = \ ...@@ -82,8 +101,8 @@ OBJS = \
udp.o udp.o
start: check prereq all #start: check prereq all
#start:check all start:check all
check: check:
ifeq ($(CONFIGURE_CONF),../configure.conf) ifeq ($(CONFIGURE_CONF),../configure.conf)
...@@ -93,7 +112,7 @@ else ...@@ -93,7 +112,7 @@ else
endif endif
.cpp.o: .cpp.o:
$(CXX) $(DEFVARS) $(CXXFLAGS) -c -o $@ $< $(CXX) $(DEFVARS) -DAUDIO_PORTAUDIO $(CXXFLAGS) -c -o $@ $<
prereq: gui/qt/url_input.ui gui/qt/configurationpanel.ui prereq: gui/qt/url_input.ui gui/qt/configurationpanel.ui
@echo "Making User Interface files..." @echo "Making User Interface files..."
......
...@@ -18,11 +18,21 @@ ...@@ -18,11 +18,21 @@
*/ */
#include <endian.h> #if defined(__APPLE__)
# include <machine/endian.h>
#else
# include <endian.h>
#endif
#include <string.h> #include <string.h>
#include <iostream> #include <iostream>
#include <string> #include <string>
#include "portaudio/pa_common/portaudio.h"
#include "portaudio/pa_common/pa_converters.h"
#include "portaudio/pa_common/pa_dither.h"
#include "../global.h"
#include "audiocodec.h" #include "audiocodec.h"
#include "../configuration.h" #include "../configuration.h"
...@@ -49,6 +59,29 @@ AudioCodec::getCodecName (void) ...@@ -49,6 +59,29 @@ AudioCodec::getCodecName (void)
return _codecName; return _codecName;
} }
void
AudioCodec::float32ToInt16 (float32* src, int16* dst, int size) {
PaUtilConverter* myconverter;
struct PaUtilTriangularDitherGenerator tdg;
PaUtil_InitializeTriangularDitherState (&tdg);
myconverter = PaUtil_SelectConverter (paFloat32, paInt16, paNoFlag);
if (myconverter != NULL) {
myconverter(dst, 1, src, 1, size, &tdg);
} else {
_debug("Format conversion is not supported\n");
}
}
void
AudioCodec::int16ToFloat32 (int16* src, float32* dst, int size) {
PaUtilConverter* myconverter;
myconverter = PaUtil_SelectConverter (paInt16, paFloat32, paNoFlag);
if (myconverter != NULL) {
myconverter(dst, 1, src, 1, size, NULL);
} else {
_debug("Format conversion is not supported\n");
}
}
...@@ -21,7 +21,8 @@ ...@@ -21,7 +21,8 @@
#define __CODEC_AUDIO_H__ #define __CODEC_AUDIO_H__
#include <string> #include <string>
#include "../global.h"
using namespace std; using namespace std;
...@@ -37,6 +38,8 @@ public: ...@@ -37,6 +38,8 @@ public:
void setCodecName (const string& codec); void setCodecName (const string& codec);
string getCodecName (void); string getCodecName (void);
void float32ToInt16 (float32* src, int16* dst, int size);
void int16ToFloat32 (int16* src, float32* dst, int size);
private: private:
string _codecName; string _codecName;
......
...@@ -44,7 +44,6 @@ public: ...@@ -44,7 +44,6 @@ public:
virtual int resetDevice (void) = 0; virtual int resetDevice (void) = 0;
virtual int writeBuffer (void) = 0; virtual int writeBuffer (void) = 0;
virtual int readBuffer (void *, int) = 0; virtual int readBuffer (void *, int) = 0;
virtual int readBuffer (int) = 0;
virtual unsigned int readableBytes (void) = 0; virtual unsigned int readableBytes (void) = 0;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
//#if defined(AUDIO_ALSA)
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
...@@ -237,4 +239,5 @@ AudioDriversALSA::resetDevice (void) { ...@@ -237,4 +239,5 @@ AudioDriversALSA::resetDevice (void) {
return 0; return 0;
} }
//#endif // defined(AUDIO_ALSA)
// EOF // EOF
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
//#ifdef AUDIO_ALSA
#ifndef _AUDIO_DRIVERS_ALSA_H_ #ifndef _AUDIO_DRIVERS_ALSA_H_
#define _AUDIO_DRIVERS_ALSA_H_ #define _AUDIO_DRIVERS_ALSA_H_
...@@ -48,7 +50,6 @@ public: ...@@ -48,7 +50,6 @@ public:
int resetDevice (void); int resetDevice (void);
int writeBuffer (void); int writeBuffer (void);
int readBuffer (void *, int); int readBuffer (void *, int);
int readBuffer (int) { return 0; }
unsigned int readableBytes (void) { return 0; } unsigned int readableBytes (void) { return 0; }
private: private:
...@@ -59,3 +60,5 @@ private: ...@@ -59,3 +60,5 @@ private:
}; };
#endif // _AUDIO_DRIVERS_ALSA_H_ #endif // _AUDIO_DRIVERS_ALSA_H_
//#endif // defined(AUDIO_ALSA)
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if defined(AUDIO_OSS)
#include <errno.h> #include <errno.h>
#include <string.h> #include <string.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
...@@ -205,61 +207,6 @@ AudioDriversOSS::readBuffer (void *ptr, int bytes) { ...@@ -205,61 +207,6 @@ AudioDriversOSS::readBuffer (void *ptr, int bytes) {
return rc; return rc;
} }
int
AudioDriversOSS::readBuffer (int bytes) {
if( devstate != DeviceOpened ) {
return -1;
}
audio_buf.resize(bytes);
ssize_t count = bytes;
short *buf;
buf = (short*)audio_buf.getData();
ssize_t rc;
rc = read (audio_fd, buf, count);
if (rc < 0) {
_debug ("rc < 0 read(): %s\n", strerror(errno));
}
else if (rc != count) {
_debug ("WARNING: asked microphone for %d got %d\n", count, rc);
}
return rc;
}
int
AudioDriversOSS::writeBuffer (void *ptr, int len) {
if (devstate != DeviceOpened ) {
error->errorName(DEVICE_NOT_OPEN, NULL);
return -1;
}
audio_buf_info info;
if (ioctl(audio_fd, SNDCTL_DSP_GETOSPACE, &info) == 0 ) {
if (info.fragstotal - info.fragments > 15) {
// drop the fragment if the buffer starts to fill up
return 1;
}
}
// Loop into write() while buffer not complete.
for (;;) {
int a;
if ((a = write(audio_fd, ptr, len)) < 0) {
_debug ("write(): %s\n", strerror(errno));
break;
}
if (a > 0) {
return a;
break;
}
}
return 1;
}
int int
AudioDriversOSS::writeBuffer (void) { AudioDriversOSS::writeBuffer (void) {
...@@ -323,4 +270,5 @@ AudioDriversOSS::readableBytes(void) { ...@@ -323,4 +270,5 @@ AudioDriversOSS::readableBytes(void) {
return info.bytes; return info.bytes;
} }
#endif // defined(AUDIO_OSS)
...@@ -20,6 +20,8 @@ ...@@ -20,6 +20,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#if defined(AUDIO_OSS)
#ifndef _AUDIO_DRIVERS_OSS_H #ifndef _AUDIO_DRIVERS_OSS_H
#define _AUDIO_DRIVERS_OSS_H #define _AUDIO_DRIVERS_OSS_H
...@@ -38,10 +40,8 @@ public: ...@@ -38,10 +40,8 @@ public:
int initDevice (DeviceMode); int initDevice (DeviceMode);
int resetDevice (void); int resetDevice (void);
bool openDevice (int); bool openDevice (int);
int writeBuffer (void *, int);
int writeBuffer (void); int writeBuffer (void);
int readBuffer (void *, int); int readBuffer (void *, int);
int readBuffer (int);
unsigned int readableBytes (void); unsigned int readableBytes (void);
int audio_fd; int audio_fd;
...@@ -51,3 +51,5 @@ private: ...@@ -51,3 +51,5 @@ private:
}; };
#endif // _AUDIO_DRIVERS_OSS_H #endif // _AUDIO_DRIVERS_OSS_H
#endif // defined(AUDIO_OSS)
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include "audiortp.h" #include "audiortp.h"
#include "../configuration.h" #include "../configuration.h"
#include "../manager.h" #include "../manager.h"
#include "../global.h"
#include "../user_cfg.h" #include "../user_cfg.h"
#include "../sipcall.h" #include "../sipcall.h"
#include "../stund/stun.h" #include "../stund/stun.h"
...@@ -65,17 +66,9 @@ AudioRtp::createNewSession (SipCall *ca) { ...@@ -65,17 +66,9 @@ AudioRtp::createNewSession (SipCall *ca) {
} else { } else {
_symetric = true; _symetric = true;
} }
#ifdef ALSA _RTXThread = new AudioRtpRTX (ca, _manager->getAudioDriver(),
if (_manager->useAlsa()) { _manager, _symetric);
_RTXThread = new AudioRtpRTX (ca, _manager->audiodriver,
_manager->audiodriverReadAlsa, _manager, _symetric);
}
#endif
if (!_manager->useAlsa()) {
_RTXThread = new AudioRtpRTX (ca, _manager->audiodriver, NULL,_manager,
_symetric);
}
if (_RTXThread->start() != 0) { if (_RTXThread->start() != 0) {
return -1; return -1;
...@@ -96,25 +89,20 @@ AudioRtp::closeRtpSession (SipCall *ca) { ...@@ -96,25 +89,20 @@ AudioRtp::closeRtpSession (SipCall *ca) {
_RTXThread = NULL; _RTXThread = NULL;
} }
// Flush audio read buffer // Flush audio read buffer
_manager->audiodriver->resetDevice(); _manager->getAudioDriver()->stopStream();
} }
} }
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
// AudioRtpRTX Class // // AudioRtpRTX Class //
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////
AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioDrivers *driver, AudioRtpRTX::AudioRtpRTX (SipCall *sipcall, AudioDriversPortAudio* driver,
AudioDrivers *read_driver, Manager *mngr, bool sym) { Manager *mngr, bool sym) {
time = new Time(); time = new Time();
_manager = mngr; _manager = mngr;
_ca = sipcall; _ca = sipcall;
_sym =sym; _sym =sym;
_audioDevice = driver; _audioDevice = driver;
#ifdef ALSA
if (_manager->useAlsa()) {
_audioDeviceRead = read_driver;
}
#endif
// TODO: Change bind address according to user settings. // TODO: Change bind address according to user settings.
InetHostAddress local_ip("0.0.0.0"); InetHostAddress local_ip("0.0.0.0");
...@@ -152,20 +140,22 @@ AudioRtpRTX::~AudioRtpRTX () { ...@@ -152,20 +140,22 @@ AudioRtpRTX::~AudioRtpRTX () {
void void
AudioRtpRTX::run (void) { AudioRtpRTX::run (void) {
unsigned char *data_to_send; unsigned char *data_to_send;
short *data_mute; int16 *data_from_mic_int16;
short *data_from_mic; float32 *data_mute;
short *data_from_mic_tmp; float32 *data_from_mic;
int i, float32 *data_from_mic_tmp;
compSize, int compSize,
timestamp; timestamp;
int expandedSize; int expandedSize;
short *data_for_speakers = NULL;
int countTime = 0; int countTime = 0;
data_for_speakers = new short[2048]; int16 *data_for_speakers = NULL;
data_from_mic = new short[1024]; float32 *data_for_speakers_float = NULL;
data_from_mic_tmp = new short[1024];
data_from_mic = new float32[1024];
data_from_mic_tmp = new float32[1024];
data_mute = new float32[1024];
data_to_send = new unsigned char[1024]; data_to_send = new unsigned char[1024];
data_mute = new short[1024]; data_for_speakers = new int16[2048];
InetHostAddress remote_ip(_ca->getRemoteSdpAudioIp()); InetHostAddress remote_ip(_ca->getRemoteSdpAudioIp());
...@@ -238,47 +228,35 @@ AudioRtpRTX::run (void) { ...@@ -238,47 +228,35 @@ AudioRtpRTX::run (void) {
// Send session // Send session
//////////////////////////// ////////////////////////////
int size = 320; int size = 320;
if (!_manager->getCall(_ca->getId())->isOnMute()) { if (!_manager->getCall(_ca->getId())->isOnMute()) {
#ifdef ALSA _manager->getAudioDriver()->mydata.dataIn = data_from_mic;
if (_manager->useAlsa()) { } else {
i = _audioDeviceRead->readBuffer (data_from_mic, size);
}
#endif
if (!_manager->useAlsa()) {
i = _audioDevice->readBuffer (data_from_mic, size);
}
}
else {
// When IP-phone user click on mute button, we read buffer of a // When IP-phone user click on mute button, we read buffer of a
// temp buffer to avoid delay in sound. // temp buffer to avoid delay in sound.
#ifdef ALSA _manager->getAudioDriver()->mydata.dataIn = data_mute;
if (_manager->useAlsa())
i = _audioDeviceRead->readBuffer (data_mute, size);
#endif
if (!_manager->useAlsa())
i = _audioDevice->readBuffer (data_mute, size);
}
// TODO : return an error because no sound
if (i < 0) {
break;
} }
for (int j = 0; j < i; j++) {
for (int j = 0; j < size; j++) {
data_from_mic_tmp[j] = data_from_mic[j] * data_from_mic_tmp[j] = data_from_mic[j] *
_manager->getMicroVolume()/100; _manager->getMicroVolume()/100;
} }
// Convert float32 buffer to int16 to encode
data_from_mic_int16 = new int16[size];
_ca->getAudioCodec()->float32ToInt16 (data_from_mic_tmp,
data_from_mic_int16, size);
// Encode acquired audio sample // Encode acquired audio sample
compSize = _ca->getAudioCodec()->codecEncode (data_to_send, compSize = _ca->getAudioCodec()->codecEncode (data_to_send,
data_from_mic_tmp, data_from_mic_int16,
i); size);
// Send encoded audio sample // Send encoded audio sample
if (!_sym) { if (!_sym) {
_sessionSend->putData(timestamp, data_to_send, compSize); _sessionSend->putData(timestamp, data_to_send, compSize);
} else { } else {
_session->putData(timestamp, data_to_send, compSize); _session->putData(timestamp, data_to_send, compSize);
} }
timestamp += 160; timestamp += MY_TIMESTAMP;
//////////////////////////// ////////////////////////////
// Recv session // Recv session
//////////////////////////// ////////////////////////////
...@@ -302,10 +280,13 @@ AudioRtpRTX::run (void) { ...@@ -302,10 +280,13 @@ AudioRtpRTX::run (void) {
(unsigned char*) adu->getData(), (unsigned char*) adu->getData(),
adu->getSize()); adu->getSize());
// To convert int16 to float32 after decoding
data_for_speakers_float = new float32[expandedSize];
ac->int16ToFloat32 (data_for_speakers, data_for_speakers_float,
expandedSize);
// Set decoded data to sound device // Set decoded data to sound device
_audioDevice->audio_buf.resize(expandedSize); _manager->getAudioDriver()->mydata.dataOut = data_for_speakers_float;
_audioDevice->audio_buf.setData (data_for_speakers,
_manager->getSpkrVolume());
// Notify (with a bip) an incoming call when there is already a call // Notify (with a bip) an incoming call when there is already a call
countTime += time->getSecond(); countTime += time->getSecond();
...@@ -316,18 +297,23 @@ AudioRtpRTX::run (void) { ...@@ -316,18 +297,23 @@ AudioRtpRTX::run (void) {
} }
} }
// Write data or notification
i = _audioDevice->writeBuffer ();
delete cd; delete cd;
delete adu; delete adu;
// Let's wait for the next transmit cycle // Let's wait for the next transmit cycle
Thread::sleep(TimerPort::getTimer()); Thread::sleep(TimerPort::getTimer());
TimerPort::incTimer(frameSize); // 'frameSize' ms TimerPort::incTimer(frameSize); // 'frameSize' ms
if (!_manager->getAudioDriver()->isStreamActive()) {
_manager->getAudioDriver()->mydata.dataToAddRem = 0;
_manager->getAudioDriver()->startStream();
}
} }
delete[] data_for_speakers; delete[] data_for_speakers;
delete[] data_for_speakers_float;
delete[] data_from_mic; delete[] data_from_mic;
delete[] data_from_mic_int16;
delete[] data_from_mic_tmp; delete[] data_from_mic_tmp;
delete[] data_mute; delete[] data_mute;
delete[] data_to_send; delete[] data_to_send;
......
...@@ -28,9 +28,9 @@ ...@@ -28,9 +28,9 @@
using namespace ost; using namespace ost;
#define LEN_BUFFER 160 #define MY_TIMESTAMP 160
class AudioDrivers; class AudioDriversPortAudio;
class Manager; class Manager;
class SipCall; class SipCall;
...@@ -39,23 +39,20 @@ class SipCall; ...@@ -39,23 +39,20 @@ class SipCall;
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
class AudioRtpRTX : public Thread, public TimerPort { class AudioRtpRTX : public Thread, public TimerPort {
public: public:
AudioRtpRTX (SipCall *, AudioDrivers *, AudioDrivers *, Manager *, bool); AudioRtpRTX (SipCall *, AudioDriversPortAudio*, Manager *, bool);
~AudioRtpRTX(); ~AudioRtpRTX();
Time *time; // For incoming call notification Time *time; // For incoming call notification
virtual void run (); virtual void run ();
private: private:
SipCall* _ca; SipCall* _ca;
AudioDrivers* _audioDevice; AudioDriversPortAudio* _audioDevice;
#ifdef ALSA RTPSession* _sessionSend;
AudioDrivers* _audioDeviceRead; RTPSession* _sessionRecv;
#endif SymmetricRTPSession* _session;