30#ifndef APF_PORTAUDIO_POLICY_H
31#define APF_PORTAUDIO_POLICY_H
40#ifndef APF_MIMOPROCESSOR_INTERFACE_POLICY
41#define APF_MIMOPROCESSOR_INTERFACE_POLICY apf::portaudio_policy
53 using sample_type = float;
57 struct portaudio_error : std::runtime_error
59 portaudio_error(PaError error)
60 : std::runtime_error(
"PortAudio: "+std::string(Pa_GetErrorText(error)))
66 static std::string device_info()
68 auto err = Pa_Initialize();
69 if (err != paNoError)
throw portaudio_error(err);
72 for (
int i = 0; i < Pa_GetDeviceCount(); ++i)
74 result = result +
"Device ID " +
str::A2S(i) +
": "
75 + Pa_GetDeviceInfo(i)->name +
"\n";
84 unsigned long sample_format = 0x00000001 | 0x80000000;
86 auto inputParameters = PaStreamParameters();
87 auto outputParameters = PaStreamParameters();
89 inputParameters.channelCount = _next_input_id;
90 inputParameters.device = _device_id;
91 inputParameters.hostApiSpecificStreamInfo =
nullptr;
92 inputParameters.sampleFormat = sample_format;
93 inputParameters.suggestedLatency
96 outputParameters.channelCount = _next_output_id;
97 outputParameters.device = _device_id;
98 outputParameters.hostApiSpecificStreamInfo =
nullptr;
99 outputParameters.sampleFormat = sample_format;
100 outputParameters.suggestedLatency
103 auto err = Pa_OpenStream(&_stream, &inputParameters, &outputParameters
104 , _sample_rate, _block_size, 0, _pa_callback,
this);
106 if (err != paNoError)
throw portaudio_error(err);
108 err = Pa_StartStream(_stream);
109 if (err != paNoError)
throw portaudio_error(err);
115 auto err = Pa_StopStream(_stream);
116 if (err != paNoError)
throw portaudio_error(err);
120 unsigned long block_size()
const {
return _block_size; }
121 int sample_rate()
const {
return _sample_rate; }
123 int in_channels()
const {
return _next_input_id; }
124 int out_channels()
const {
return _next_output_id; }
128 int get_real_time_priority()
const {
return -1; }
133 : _sample_rate(p.get<int>(
"sample_rate"))
134 , _block_size(p.get<unsigned long>(
"block_size"))
135 , _device_id(p.get(
"device_id", 0))
139 auto err = Pa_Initialize();
140 if (err != paNoError)
throw portaudio_error(err);
146 Pa_CloseStream(_stream);
151 static int _pa_callback(
const void *input,
void *output
152 ,
unsigned long frameCount,
const PaStreamCallbackTimeInfo* timeInfo
153 , PaStreamCallbackFlags statusFlags,
void *userData)
159 , output, frameCount);
162 int pa_callback(
const void *input,
void *output,
unsigned long frameCount)
165 assert(frameCount == this->block_size());
167 _in =
static_cast<sample_type* const*
>(input);
168 _out =
static_cast<sample_type* const*
>(output);
176 virtual void process() = 0;
180 int get_next_input_id() {
return _next_input_id++; }
183 int get_next_output_id() {
return _next_output_id++; }
185 const int _sample_rate;
186 const unsigned long _block_size;
187 const int _device_id;
191 sample_type*
const* _in;
192 sample_type*
const* _out;
197class portaudio_policy::Input
200 using iterator = sample_type
const*;
202 struct buffer_type : has_begin_and_end<iterator> {
friend class Input; };
206 this->buffer._begin = _parent._in[_id];
207 this->buffer._end = this->buffer._begin + _parent.block_size();
215 , _id(_parent.get_next_input_id())
225class portaudio_policy::Output
228 using iterator = sample_type*;
230 struct buffer_type : has_begin_and_end<iterator> {
friend class Output; };
234 this->buffer._begin = _parent._out[_id];
235 this->buffer._end = this->buffer._begin + _parent.block_size();
243 , _id(_parent.get_next_output_id())
interface_policy using PortAudio.
portaudio_policy(const parameter_map &p=parameter_map())
Constructor.
~portaudio_policy()
Protected destructor.
Several more or less useful iterators and some macros.
std::string A2S(const T &input)
Converter "Anything to String".
Audio Processing Framework.
A "dictionary" for parameters.
A "dictionary" for parameters.