summaryrefslogtreecommitdiffhomepage
path: root/audioio.cpp
diff options
context:
space:
mode:
authorRoland Stigge <stigge@antcom.de>2019-02-17 22:10:33 +0100
committerRoland Stigge <stigge@antcom.de>2019-02-17 22:10:33 +0100
commiteac187fcbafcc518185d1074395c5fbe6a7e5aec (patch)
treeb3585f50f9db0a04fd3e5c781eb9f952e39e4a53 /audioio.cpp
parent308a53c389cdc2631860f434989cd57efbf91145 (diff)
Added portaudio support
Diffstat (limited to 'audioio.cpp')
-rw-r--r--audioio.cpp128
1 files changed, 128 insertions, 0 deletions
diff --git a/audioio.cpp b/audioio.cpp
new file mode 100644
index 0000000..31fa1cd
--- /dev/null
+++ b/audioio.cpp
@@ -0,0 +1,128 @@
+#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
+ {
+ std::cout << "Callback" << std::endl;
+
+ float* buf = (float*)inputBuffer;
+ for (int i = 0; i < framesPerBuffer; i++) {
+ 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? PaUtilRingBuffer?
+}
+
+int RIT::AudioIO::size() const
+{
+ return mImpl->mSize;
+}
+
+int RIT::AudioIO::sampleFrequency() const
+{
+ return int(mImpl->mSampleRate);
+}
+