1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#include "audioio.h"
#include <exception>
#include <iostream>
#include <portaudiocpp/AutoSystem.hxx>
#include <portaudiocpp/CallbackInterface.hxx>
#include <portaudiocpp/Device.hxx>
#include <portaudiocpp/InterfaceCallbackStream.hxx>
#include <portaudiocpp/StreamParameters.hxx>
#include <portaudiocpp/System.hxx>
#include <portaudiocpp/SystemDeviceIterator.hxx>
namespace {
class Callback: public portaudio::CallbackInterface {
public:
Callback(int size): mBuffer(size){}
std::vector<std::complex<double>> mBuffer;
int paCallbackFun( const void *inputBuffer, void *outputBuffer,
unsigned long framesPerBuffer,
const PaStreamCallbackTimeInfo* timeInfo,
PaStreamCallbackFlags statusFlags ) override
{
float* buf = (float*)inputBuffer;
std::cout << "Callback " << std::endl;
for (int i = 0; i < framesPerBuffer; i++) {
//if (buf[i] > 0.1)
// std::cout << "DEBUG: " << buf[i] << std::endl;
mBuffer[i] = buf[i];
}
return 0;
}
};
int bufferSizeFromSampleRate(double sampleRate) {
int result = 1;
while (result < sampleRate)
result <<= 1;
result /= 32;
if (result < 1024)
throw std::runtime_error(std::string("Bad buffer size ") + std::to_string(result) + " for sample rate " + std::to_string(sampleRate));
return result;
}
void printDeviceList() {
portaudio::System& mSystem = portaudio::System::instance();
std::cout << "Number of Devices: " << mSystem.deviceCount() << std::endl;
std::for_each(mSystem.devicesBegin(), mSystem.devicesEnd(),
[](const portaudio::Device& device){ std::cout
<< "Device Name: " << device.name()
<< " Default Rate: " << device.defaultSampleRate()
<< std::endl;
}
);
}
} // namespace
struct RIT::AudioIO::Impl {
Impl()
: mAudioSystem()
, mSystem(portaudio::System::instance())
, mDevice(mSystem.defaultInputDevice())
, mSampleRate(mDevice.defaultSampleRate())
, mSize(bufferSizeFromSampleRate(mSampleRate))
, mInputParams(mDevice, 1, portaudio::FLOAT32, false, mDevice.defaultLowInputLatency(), nullptr)
, mOutputParams(portaudio::System::nullDevice(), 0, portaudio::FLOAT32, false, mDevice.defaultLowInputLatency(), nullptr)
, mParameters(mInputParams, mOutputParams, mSampleRate, mSize, paNoFlag)
, mCallback(mSize)
, mStream(mParameters, mCallback)
{
printDeviceList();
mStream.start();
if (!mStream.isOpen())
throw std::runtime_error("Error: Stream not open");
if (!mStream.isActive())
throw std::runtime_error("Error: Stream not active");
std::cout << "Activated Device: " << mDevice.name() << " at " << mSampleRate << " Hz, buffer: " << mSize << " samples, running..." << std::endl;
}
~Impl() {}
// Port audio specific
portaudio::AutoSystem mAudioSystem; // init / deinit portaudio
portaudio::System& mSystem;
portaudio::Device& mDevice;
double mSampleRate;
int mSize;
portaudio::DirectionSpecificStreamParameters mInputParams;
portaudio::DirectionSpecificStreamParameters mOutputParams;
portaudio::StreamParameters mParameters;
Callback mCallback;
portaudio::InterfaceCallbackStream mStream;
};
RIT::AudioIO::AudioIO(): mImpl(std::make_unique<AudioIO::Impl>())
{
}
RIT::AudioIO::~AudioIO()
{
}
std::vector<std::complex<double>> RIT::AudioIO::sample()
{
return mImpl->mCallback.mBuffer; // TODO: thread synchronization! Ringbuffer
}
int RIT::AudioIO::size() const
{
return mImpl->mSize;
}
int RIT::AudioIO::sampleFrequency() const
{
return int(mImpl->mSampleRate);
}
|