libsdr  0.1.0
A simple SDR library
portaudio.hh
1 #ifndef __SDR_PORTAUDIO_HH__
2 #define __SDR_PORTAUDIO_HH__
3 
4 #include <portaudio.h>
5 
6 #include "buffer.hh"
7 #include "node.hh"
8 #include "config.hh"
9 #include "logger.hh"
10 
11 namespace sdr {
12 
14 class PortAudio {
15 public:
17  static void init();
19  static void terminate();
20 
22  static int numDevices();
24  static int defaultInputDevice();
26  static int defaultOutputDevice();
28  static bool hasInputStream(int idx);
30  static bool hasOutputStream(int idx);
32  static std::string deviceName(int idx);
33 };
34 
35 
38 class PortSink: public SinkBase
39 {
40 public:
42  PortSink();
44  virtual ~PortSink();
45 
47  virtual void config(const Config &src_cfg);
49  virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite);
50 
51 protected:
53  PaStream *_stream;
55  size_t _frame_size;
56 };
57 
58 
61 template <class Scalar>
62 class PortSource: public Source
63 {
64 public:
66  PortSource(double sampleRate, size_t bufferSize, int dev=-1):
67  Source(), _streamIsOpen(false), _stream(0), _sampleRate(sampleRate), _is_real(true)
68  {
69  // Allocate buffer
70  _buffer = Buffer<Scalar>(bufferSize);
71  _initializeStream(dev);
72  }
73 
75  virtual ~PortSource() {
76  // close stream
77  if (0 != _stream) { Pa_CloseStream(_stream); }
78  // unref buffer
79  _buffer.unref();
80  }
81 
84  void next() {
87  Pa_ReadStream(_stream, _buffer.ptr(), _buffer.size());
88  this->send(_buffer);
89  }
90 
92  int deviceIndex() const { return _deviceIndex; }
93 
96  void setDeviceIndex(int idx=-1) {
97  _initializeStream(idx);
98  }
99 
101  bool hasSampleRate(double sampleRate) {
102  PaStreamParameters params;
103  params.device = _deviceIndex;
104  params.channelCount = _is_real ? 1 : 2;
105  params.sampleFormat = _fmt;
106  params.hostApiSpecificStreamInfo = 0;
107  return paFormatIsSupported == Pa_IsFormatSupported(&params, 0, sampleRate);
108  }
109 
112  void setSampleRate(double sampleRate) {
115  }
116 
117 protected:
119  void _initializeStream(int idx=-1) {
120  // Stop and close stream if running
121  if (_streamIsOpen) {
122  Pa_StopStream(_stream); Pa_CloseStream(_stream); _streamIsOpen = false;
123  }
124 
125  // Determine input stream format by scalar type
126  switch (Config::typeId<Scalar>()) {
127  case Config::Type_f32:
128  _fmt = paFloat32;
129  _is_real = true;
130  break;
131  case Config::Type_u16:
132  case Config::Type_s16:
133  _fmt = paInt16;
134  _is_real = true;
135  break;
136  case Config::Type_cf32:
137  _fmt = paFloat32;
138  _is_real = false;
139  break;
140  case Config::Type_cu16:
141  case Config::Type_cs16:
142  _fmt = paInt16;
143  _is_real = false;
144  break;
145  default:
146  ConfigError err;
147  err << "Can not configure PortAudio sink: Unsupported format " << Config::typeId<Scalar>()
148  << " must be one of " << Config::Type_u16 << ", " << Config::Type_s16
149  << ", " << Config::Type_f32 << ", " << Config::Type_cu16 << ", " << Config::Type_cs16
150  << " or " << Config::Type_cf32 << ".";
151  throw err;
152  }
153 
154  // Assemble config:
155  int numCh = _is_real ? 1 : 2;
156  _deviceIndex = idx < 0 ? Pa_GetDefaultInputDevice() : idx;
157  PaStreamParameters params;
158  params.device = _deviceIndex;
159  params.channelCount = numCh;
160  params.sampleFormat = _fmt;
161  params.suggestedLatency = Pa_GetDeviceInfo(_deviceIndex)->defaultHighInputLatency;
162  params.hostApiSpecificStreamInfo = 0;
163 
164  // open stream
165  PaError err = Pa_OpenStream(&_stream, &params, 0, _sampleRate, _buffer.size(), 0, 0, 0);
166 
167  // Check for errors
168  if (0 > err) {
169  ConfigError err;
170  err << "Can not open PortAudio input stream!"; throw err;
171  }
172  // Mark stream as open
173  _streamIsOpen = true;
174  // Start stream
175  Pa_StartStream(_stream);
176 
177  LogMessage msg(LOG_DEBUG);
178  msg << "Configure PortAudio source: " << std::endl
179  << " sample rate " << _sampleRate << std::endl
180  << " buffer size " << _buffer.size() << std::endl
181  << " format " << Config::typeId<Scalar>() << std::endl
182  << " num chanels " << numCh;
183  Logger::get().log(msg);
184 
185  // Set config
186  this->setConfig(Config(Config::typeId<Scalar>(), _sampleRate, _buffer.size(), 1));
187  }
188 
189 
190 protected:
194  PaStream *_stream;
196  PaSampleFormat _fmt;
198  double _sampleRate;
202  bool _is_real;
205 };
206 
207 }
208 
209 #endif // __SDR_PORTAUDIO_HH__
void _initializeStream(int idx=-1)
Device setup.
Definition: portaudio.hh:119
static bool hasInputStream(int idx)
Returns true of the given device provides an input chanel.
Definition: portaudio.cc:35
A collection of configuration information that is send by a source to all connected sinks to properga...
Definition: node.hh:35
Complex (aka I/Q) type of 32bit floats aka. std::complex.
Definition: node.hh:51
PortAudio playback node.
Definition: portaudio.hh:38
Base class of all buffers, represents an untyped array of bytes.
Definition: buffer.hh:32
bool _streamIsOpen
If true, the PortAudio stream, _stream is open.
Definition: portaudio.hh:192
static int defaultOutputDevice()
Returns the index of the default output device.
Definition: portaudio.cc:30
bool _is_real
If true, the input stream is real (1 chanel), otherwise complex (2 chanels).
Definition: portaudio.hh:202
Real signed 16b ints.
Definition: node.hh:44
virtual void send(const RawBuffer &buffer, bool allow_overwrite=false)
Sends the given buffer to all connected sinks.
Definition: node.cc:67
static void init()
Initializes the PortAudio system, must be called first.
Definition: portaudio.cc:10
Complex (aka I/Q) type of unsigned 16b ints.
Definition: node.hh:49
Definition: autocast.hh:8
static int numDevices()
Returns the number of devices available.
Definition: portaudio.cc:20
Generic source class.
Definition: node.hh:213
PaStream * _stream
The PortAudio input stream.
Definition: portaudio.hh:194
static std::string deviceName(int idx)
Returns the device name.
Definition: portaudio.cc:47
void next()
Reads (blocking) the next buffer from the PortAudio stream.
Definition: portaudio.hh:84
Buffer< Scalar > _buffer
The output buffer.
Definition: portaudio.hh:204
virtual void handleBuffer(const RawBuffer &buffer, bool allow_overwrite)
Playback.
Definition: portaudio.cc:152
size_t size() const
Returns the number of elements of type T in this buffer.
Definition: buffer.hh:166
virtual double sampleRate() const
Returns the configured sample rate or 0 otherwise.
Definition: node.cc:122
Real unsigned 16b ints.
Definition: node.hh:43
double _sampleRate
The current sample rate.
Definition: portaudio.hh:198
virtual void setConfig(const Config &config)
Stores the configuration and propergates it if the configuration has been changed.
Definition: node.cc:98
static bool hasOutputStream(int idx)
Returns true of the given device provides an output chanel.
Definition: portaudio.cc:41
virtual void config(const Config &src_cfg)
Configures the PortAudio output.
Definition: portaudio.cc:70
size_t _frame_size
The frame-size.
Definition: portaudio.hh:55
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
int _deviceIndex
The current input device index.
Definition: portaudio.hh:200
PaStream * _stream
The PortAudio stream.
Definition: portaudio.hh:53
static void terminate()
Shutdown.
Definition: portaudio.cc:15
void setSampleRate(double sampleRate)
Resets the sample rate of the input device.
Definition: portaudio.hh:112
void log(const LogMessage &message)
Logs a message.
Definition: logger.cc:100
PortAudio input stream as a Source.
Definition: portaudio.hh:62
"Namespace" to collect all static, PortAudio related functions.
Definition: portaudio.hh:14
bool hasSampleRate(double sampleRate)
Checks if the given sample rate is supported by the device.
Definition: portaudio.hh:101
PaSampleFormat _fmt
The current format of the PortAudio stream.
Definition: portaudio.hh:196
static Logger & get()
Returns the singleton instance of the logger.
Definition: logger.cc:89
Real 32b floats aka. "float".
Definition: node.hh:45
The configuration error class.
Definition: exception.hh:24
A log message.
Definition: logger.hh:22
static int defaultInputDevice()
Returns the index of the default input device.
Definition: portaudio.cc:25
Basic interface of all Sinks.
Definition: node.hh:174
virtual ~PortSource()
Destructor.
Definition: portaudio.hh:75
char * ptr() const
Returns the pointer to the data (w/o view).
Definition: buffer.hh:67
Complex (aka I/Q) type of signed 16b ints.
Definition: node.hh:50
void unref()
Dereferences the buffer.
Definition: buffer.cc:63
PortSource(double sampleRate, size_t bufferSize, int dev=-1)
Constructor.
Definition: portaudio.hh:66
PortSink()
Constructor.
Definition: portaudio.cc:57
virtual ~PortSink()
Destructor.
Definition: portaudio.cc:63
int deviceIndex() const
Returns the currently selected input device.
Definition: portaudio.hh:92