From eac187fcbafcc518185d1074395c5fbe6a7e5aec Mon Sep 17 00:00:00 2001 From: Roland Stigge Date: Sun, 17 Feb 2019 22:10:33 +0100 Subject: Added portaudio support --- audioio.cpp | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 audioio.cpp (limited to 'audioio.cpp') 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 +#include + +#include +#include +#include +#include +#include +#include +#include + +namespace { + +class Callback: public portaudio::CallbackInterface { + public: + Callback(int size): mBuffer(size){} + + std::vector> 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()) +{ +} + +RIT::AudioIO::~AudioIO() +{ +} + +std::vector> 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); +} + -- cgit v1.2.3