portaudio.hh
#ifndef __SDR_PORTAUDIO_HH__
#define __SDR_PORTAUDIO_HH__
#include <portaudio.h>
#include "buffer.hh"
#include "node.hh"
#include "config.hh"
#include "logger.hh"
namespace sdr {
class PortAudio {
public:
static void init();
static void terminate();
static int numDevices();
static int defaultInputDevice();
static int defaultOutputDevice();
static bool hasInputStream(int idx);
static bool hasOutputStream(int idx);
static std::string deviceName(int idx);
};
class PortSink: public SinkBase
{
public:
PortSink();
virtual ~PortSink();
virtual void config(const Config &src_cfg);
virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite);
protected:
PaStream *_stream;
size_t _frame_size;
};
template <class Scalar>
class PortSource: public Source
{
public:
PortSource(double sampleRate, size_t bufferSize, int dev=-1):
Source(), _streamIsOpen(false), _stream(0), _sampleRate(sampleRate), _is_real(true)
{
// Allocate buffer
_buffer = Buffer<Scalar>(bufferSize);
_initializeStream(dev);
}
virtual ~PortSource() {
// close stream
if (0 != _stream) { Pa_CloseStream(_stream); }
// unref buffer
_buffer.unref();
}
void next() {
Pa_ReadStream(_stream, _buffer.ptr(), _buffer.size());
this->send(_buffer);
}
int deviceIndex() const { return _deviceIndex; }
void setDeviceIndex(int idx=-1) {
_initializeStream(idx);
}
bool hasSampleRate(double sampleRate) {
PaStreamParameters params;
params.device = _deviceIndex;
params.channelCount = _is_real ? 1 : 2;
params.sampleFormat = _fmt;
params.hostApiSpecificStreamInfo = 0;
return paFormatIsSupported == Pa_IsFormatSupported(&params, 0, sampleRate);
}
void setSampleRate(double sampleRate) {
_sampleRate = sampleRate;
_initializeStream(_deviceIndex);
}
protected:
void _initializeStream(int idx=-1) {
// Stop and close stream if running
if (_streamIsOpen) {
Pa_StopStream(_stream); Pa_CloseStream(_stream); _streamIsOpen = false;
}
// Determine input stream format by scalar type
switch (Config::typeId<Scalar>()) {
case Config::Type_f32:
_fmt = paFloat32;
_is_real = true;
break;
case Config::Type_u16:
case Config::Type_s16:
_fmt = paInt16;
_is_real = true;
break;
case Config::Type_cf32:
_fmt = paFloat32;
_is_real = false;
break;
case Config::Type_cu16:
case Config::Type_cs16:
_fmt = paInt16;
_is_real = false;
break;
default:
ConfigError err;
err << "Can not configure PortAudio sink: Unsupported format " << Config::typeId<Scalar>()
<< " must be one of " << Config::Type_u16 << ", " << Config::Type_s16
<< ", " << Config::Type_f32 << ", " << Config::Type_cu16 << ", " << Config::Type_cs16
<< " or " << Config::Type_cf32 << ".";
throw err;
}
// Assemble config:
int numCh = _is_real ? 1 : 2;
_deviceIndex = idx < 0 ? Pa_GetDefaultInputDevice() : idx;
PaStreamParameters params;
params.device = _deviceIndex;
params.channelCount = numCh;
params.sampleFormat = _fmt;
params.suggestedLatency = Pa_GetDeviceInfo(_deviceIndex)->defaultHighInputLatency;
params.hostApiSpecificStreamInfo = 0;
// open stream
PaError err = Pa_OpenStream(&_stream, &params, 0, _sampleRate, _buffer.size(), 0, 0, 0);
// Check for errors
if (0 > err) {
ConfigError err;
err << "Can not open PortAudio input stream!"; throw err;
}
// Mark stream as open
_streamIsOpen = true;
// Start stream
Pa_StartStream(_stream);
LogMessage msg(LOG_DEBUG);
msg << "Configure PortAudio source: " << std::endl
<< " sample rate " << _sampleRate << std::endl
<< " buffer size " << _buffer.size() << std::endl
<< " format " << Config::typeId<Scalar>() << std::endl
<< " num chanels " << numCh;
Logger::get().log(msg);
// Set config
this->setConfig(Config(Config::typeId<Scalar>(), _sampleRate, _buffer.size(), 1));
}
protected:
bool _streamIsOpen;
PaStream *_stream;
PaSampleFormat _fmt;
double _sampleRate;
int _deviceIndex;
bool _is_real;
Buffer<Scalar> _buffer;
};
}
#endif // __SDR_PORTAUDIO_HH__
sdr::PortSource::_initializeStream
void _initializeStream(int idx=-1)
Device setup.
Definition: portaudio.hh:119
sdr::PortAudio::hasInputStream
static bool hasInputStream(int idx)
Returns true of the given device provides an input chanel.
Definition: portaudio.cc:35
sdr::Config
A collection of configuration information that is send by a source to all connected sinks to properga...
Definition: node.hh:35
sdr::Config::Type_cf32
Complex (aka I/Q) type of 32bit floats aka. std::complex<float>.
Definition: node.hh:51
sdr::PortSink
PortAudio playback node.
Definition: portaudio.hh:38
sdr::RawBuffer
Base class of all buffers, represents an untyped array of bytes.
Definition: buffer.hh:32
sdr::PortSource::_streamIsOpen
bool _streamIsOpen
If true, the PortAudio stream, _stream is open.
Definition: portaudio.hh:192
sdr::PortAudio::defaultOutputDevice
static int defaultOutputDevice()
Returns the index of the default output device.
Definition: portaudio.cc:30
sdr::PortSource::_is_real
bool _is_real
If true, the input stream is real (1 chanel), otherwise complex (2 chanels).
Definition: portaudio.hh:202
sdr::Config::Type_s16
Real signed 16b ints.
Definition: node.hh:44
sdr::Source::send
virtual void send(const RawBuffer &buffer, bool allow_overwrite=false)
Sends the given buffer to all connected sinks.
Definition: node.cc:67
sdr::PortAudio::init
static void init()
Initializes the PortAudio system, must be called first.
Definition: portaudio.cc:10
sdr::Config::Type_cu16
Complex (aka I/Q) type of unsigned 16b ints.
Definition: node.hh:49
sdr
Definition: autocast.hh:8
sdr::PortAudio::numDevices
static int numDevices()
Returns the number of devices available.
Definition: portaudio.cc:20
sdr::Source
Generic source class.
Definition: node.hh:213
sdr::PortSource::_stream
PaStream * _stream
The PortAudio input stream.
Definition: portaudio.hh:194
sdr::PortAudio::deviceName
static std::string deviceName(int idx)
Returns the device name.
Definition: portaudio.cc:47
sdr::PortSource::next
void next()
Reads (blocking) the next buffer from the PortAudio stream.
Definition: portaudio.hh:84
sdr::PortSource::_buffer
Buffer< Scalar > _buffer
The output buffer.
Definition: portaudio.hh:204
sdr::PortSink::handleBuffer
virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite)
Playback.
Definition: portaudio.cc:152
sdr::Buffer::size
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
sdr::Source::sampleRate
virtual double sampleRate() const
Returns the configured sample rate or 0 otherwise.
Definition: node.cc:122
sdr::Config::Type_u16
Real unsigned 16b ints.
Definition: node.hh:43
sdr::PortSource::_sampleRate
double _sampleRate
The current sample rate.
Definition: portaudio.hh:198
sdr::Source::setConfig
virtual void setConfig(const Config &config)
Stores the configuration and propergates it if the configuration has been changed.
Definition: node.cc:98
sdr::PortAudio::hasOutputStream
static bool hasOutputStream(int idx)
Returns true of the given device provides an output chanel.
Definition: portaudio.cc:41
sdr::PortSink::config
virtual void config(const Config &src_cfg)
Configures the PortAudio output.
Definition: portaudio.cc:70
sdr::PortSink::_frame_size
size_t _frame_size
The frame-size.
Definition: portaudio.hh:55
sdr::PortSource::setDeviceIndex
void setDeviceIndex(int idx=-1)
Selects the input device, throws a ConfigError exception if the device can not be setup as an input d...
Definition: portaudio.hh:96
sdr::PortSource::_deviceIndex
int _deviceIndex
The current input device index.
Definition: portaudio.hh:200
sdr::PortSink::_stream
PaStream * _stream
The PortAudio stream.
Definition: portaudio.hh:53
sdr::PortAudio::terminate
static void terminate()
Shutdown.
Definition: portaudio.cc:15
sdr::PortSource::setSampleRate
void setSampleRate(double sampleRate)
Resets the sample rate of the input device.
Definition: portaudio.hh:112
sdr::Logger::log
void log(const LogMessage &message)
Logs a message.
Definition: logger.cc:100
sdr::PortSource
PortAudio input stream as a Source.
Definition: portaudio.hh:62
sdr::PortAudio
"Namespace" to collect all static, PortAudio related functions.
Definition: portaudio.hh:14
sdr::PortSource::hasSampleRate
bool hasSampleRate(double sampleRate)
Checks if the given sample rate is supported by the device.
Definition: portaudio.hh:101
sdr::PortSource::_fmt
PaSampleFormat _fmt
The current format of the PortAudio stream.
Definition: portaudio.hh:196
sdr::Logger::get
static Logger & get()
Returns the singleton instance of the logger.
Definition: logger.cc:89
sdr::Config::Type_f32
Real 32b floats aka. "float".
Definition: node.hh:45
sdr::ConfigError
The configuration error class.
Definition: exception.hh:24
sdr::LogMessage
A log message.
Definition: logger.hh:22
sdr::PortAudio::defaultInputDevice
static int defaultInputDevice()
Returns the index of the default input device.
Definition: portaudio.cc:25
sdr::SinkBase
Basic interface of all Sinks.
Definition: node.hh:174
sdr::PortSource::~PortSource
virtual ~PortSource()
Destructor.
Definition: portaudio.hh:75
sdr::RawBuffer::ptr
char * ptr() const
Returns the pointer to the data (w/o view).
Definition: buffer.hh:67
sdr::Config::Type_cs16
Complex (aka I/Q) type of signed 16b ints.
Definition: node.hh:50
sdr::RawBuffer::unref
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
sdr::PortSource::PortSource
PortSource(double sampleRate, size_t bufferSize, int dev=-1)
Constructor.
Definition: portaudio.hh:66
sdr::PortSink::PortSink
PortSink()
Constructor.
Definition: portaudio.cc:57
sdr::PortSink::~PortSink
virtual ~PortSink()
Destructor.
Definition: portaudio.cc:63
sdr::Buffer< Scalar >
sdr::PortSource::deviceIndex
int deviceIndex() const
Returns the currently selected input device.
Definition: portaudio.hh:92