#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 { 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()) { } RIT::AudioIO::~AudioIO() { } std::vector> 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); }