Add portaudio support

merge-requests/7/head
Phil Taylor 2021-11-01 20:27:33 +00:00
rodzic 43efadbeaa
commit 0c7bc17382
4 zmienionych plików z 166 dodań i 7 usunięć

Wyświetl plik

@ -8,6 +8,10 @@
#include "logcategories.h"
#include "ulaw.h"
#if defined(Q_OS_WIN) && defined(PORTAUDIO)
#include <objbase.h>
#endif
audioHandler::audioHandler(QObject* parent)
{
@ -29,6 +33,7 @@ audioHandler::~audioHandler()
}
delete audio;
#elif defined(PORTAUDIO)
Pa_StopStream(audio);
#else
stop();
#endif
@ -184,6 +189,79 @@ bool audioHandler::init(audioSetup setupIn)
#elif defined(PORTAUDIO)
PaError err;
#ifdef Q_OS_WIN
CoInitialize(0);
#endif
memset(&aParams, 0,sizeof(PaStreamParameters));
if (setup.port > 0) {
aParams.device = setup.port;
}
else if (setup.isinput) {
aParams.device = Pa_GetDefaultInputDevice();
}
else {
aParams.device = Pa_GetDefaultOutputDevice();
}
info = Pa_GetDeviceInfo(aParams.device);
aParams.channelCount = 2;
aParams.hostApiSpecificStreamInfo = NULL;
aParams.sampleFormat = paInt16;
aParams.suggestedLatency = info->defaultLowInputLatency;
aParams.hostApiSpecificStreamInfo = NULL;
// Always use the "preferred" sample rate
// We can always resample if needed
this->nativeSampleRate = info->defaultSampleRate;
// Per channel chunk size.
this->chunkSize = (this->nativeSampleRate / 50);
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << info->name << "(" << aParams.device << ") successfully probed";
if (setup.isinput) {
devChannels = info->maxInputChannels;
}
else {
devChannels = info->maxOutputChannels;
}
qInfo(logAudio()) << " Channels:" << devChannels;
if (devChannels > 2) {
devChannels = 2;
}
aParams.channelCount = devChannels;
qInfo(logAudio()) << " chunkSize: " << chunkSize;
if (setup.isinput) {
err=Pa_OpenStream(&audio, &aParams, 0, this->nativeSampleRate, this->chunkSize, paNoFlag, &audioHandler::staticWrite, (void*)this);
//err = Pa_OpenDefaultStream(&audio, 2, 0, paFloat32, this->nativeSampleRate, this->chunkSize, &audioHandler::staticWrite, (void*)this);
}
else {
err=Pa_OpenStream(&audio, 0, &aParams, this->nativeSampleRate, this->chunkSize, paNoFlag, &audioHandler::staticRead, (void*)this);
//err = Pa_OpenDefaultStream(&audio, 0, 2, paFloat32, this->nativeSampleRate, this->chunkSize, &audioHandler::staticRead, (void*)this);
}
if (err == paNoError) {
err = Pa_StartStream(audio);
}
if (err == paNoError) {
isInitialized = true;
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "device successfully opened";
}
else {
qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "failed to open device" << Pa_GetErrorText(err);
}
//qInfo(logAudio()) << (setup.isinput ? "Input" : "Output") << "detected latency:" << audio->getStreamLatency();
#else
format.setSampleSize(16);
@ -323,7 +401,8 @@ void audioHandler::setVolume(unsigned char volume)
/// <param name="maxlen"></param>
/// <returns></returns>
#if defined(RTAUDIO)
int audioHandler::readData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status)
int audioHandler::readData(void* outputBuffer, void* inputBuffer,
unsigned int nFrames, double streamTime, RtAudioStreamStatus status)
{
Q_UNUSED(inputBuffer);
Q_UNUSED(streamTime);
@ -332,6 +411,15 @@ int audioHandler::readData(void* outputBuffer, void* inputBuffer, unsigned int n
int nBytes = nFrames * devChannels * 2; // This is ALWAYS 2 bytes per sample and 2 channels
quint8* buffer = (quint8*)outputBuffer;
#elif defined(PORTAUDIO)
int audioHandler::readData(const void* inputBuffer, void* outputBuffer,
unsigned long nFrames, const PaStreamCallbackTimeInfo * streamTime, PaStreamCallbackFlags status)
{
Q_UNUSED(inputBuffer);
Q_UNUSED(streamTime);
Q_UNUSED(status);
int nBytes = nFrames * devChannels * 2; // This is ALWAYS 2 bytes per sample and 2 channels
quint8* buffer = (quint8*)outputBuffer;
#else
qint64 audioHandler::readData(char* buffer, qint64 nBytes)
{
@ -411,13 +499,15 @@ qint64 audioHandler::readData(char* buffer, qint64 nBytes)
#if defined(RTAUDIO)
return 0;
#elif defined(PORTAUDIO)
return 0;
#else
return nBytes;
#endif
}
#if defined(RTAUDIO)
int audioHandler::writeData(void* outputBuffer, void* inputBuffer, unsigned int nFrames, double streamTime, RtAudioStreamStatus status)
int audioHandler::writeData(void* outputBuffer, void* inputBuffer,
unsigned int nFrames, double streamTime, RtAudioStreamStatus status)
{
Q_UNUSED(outputBuffer);
Q_UNUSED(streamTime);
@ -425,6 +515,15 @@ int audioHandler::writeData(void* outputBuffer, void* inputBuffer, unsigned int
int nBytes = nFrames * devChannels * 2; // This is ALWAYS 2 bytes per sample and 2 channels
const char* data = (const char*)inputBuffer;
#elif defined(PORTAUDIO)
int audioHandler::writeData(const void* inputBuffer, void* outputBuffer,
unsigned long nFrames, const PaStreamCallbackTimeInfo * streamTime,
PaStreamCallbackFlags status)
{
Q_UNUSED(outputBuffer);
Q_UNUSED(streamTime);
Q_UNUSED(status);
int nBytes = nFrames * devChannels * 2; // This is ALWAYS 2 bytes per sample and 2 channels
const char* data = (const char*)inputBuffer;
#else
qint64 audioHandler::writeData(const char* data, qint64 nBytes)
{
@ -462,6 +561,7 @@ qint64 audioHandler::writeData(const char* data, qint64 nBytes)
#if defined(RTAUDIO)
return 0;
#elif defined(PORTAUDIO)
return 0;
#else
return nBytes;
#endif
@ -586,7 +686,7 @@ void audioHandler::incomingAudio(audioPacket inPacket)
if (!ringBuf->try_write(inPacket))
{
qDebug(logAudio()) << "Buffer full! capacity:" << ringBuf->capacity() << "length" << ringBuf->size();
qDebug(logAudio()) << (setup.isinput ? "Input" : "Output") << "Buffer full! capacity:" << ringBuf->capacity() << "length" << ringBuf->size();
}
return;
}

Wyświetl plik

@ -9,10 +9,14 @@
#include <QtMath>
#if defined(RTAUDIO)
#ifdef Q_OS_WIN
#include "RtAudio.h"
#else
#include "rtaudio/RtAudio.h"
#endif
#elif defined (PORTAUDIO)
#include "portaudio.h"
#error "PORTAUDIO is not currently supported"
//#error "PORTAUDIO is not currently supported"
#else
#include <QAudioOutput>
#include <QAudioFormat>
@ -67,9 +71,8 @@ struct audioSetup {
quint8 codec;
bool ulaw;
bool isinput;
#if defined(RTAUDIO)
#if defined(RTAUDIO) || defined(PORTAUDIO)
int port;
#elif defined(PORTAUDIO)
#else
QAudioDeviceInfo port;
#endif
@ -137,6 +140,21 @@ private:
return static_cast<audioHandler*>(userData)->writeData(outputBuffer, inputBuffer, nFrames, streamTime, status);
}
#elif defined(PORTAUDIO)
int readData(const void* inputBuffer, void* outputBuffer,
unsigned long nFrames,
const PaStreamCallbackTimeInfo* streamTime,
PaStreamCallbackFlags status);
static int staticRead(const void* inputBuffer, void* outputBuffer, unsigned long nFrames, const PaStreamCallbackTimeInfo* streamTime, PaStreamCallbackFlags status, void* userData) {
return ((audioHandler*)userData)->readData(inputBuffer, outputBuffer, nFrames, streamTime, status);
}
int writeData(const void* inputBuffer, void* outputBuffer,
unsigned long nFrames,
const PaStreamCallbackTimeInfo* streamTime,
PaStreamCallbackFlags status);
static int staticWrite(const void* inputBuffer, void* outputBuffer, unsigned long nFrames, const PaStreamCallbackTimeInfo* streamTime, PaStreamCallbackFlags status, void* userData) {
return ((audioHandler*)userData)->writeData(inputBuffer, outputBuffer, nFrames, streamTime, status);
}
#else
qint64 readData(char* data, qint64 nBytes);
@ -154,6 +172,9 @@ private:
RtAudio::StreamOptions options;
RtAudio::DeviceInfo info;
#elif defined(PORTAUDIO)
PaStream* audio = Q_NULLPTR;
PaStreamParameters aParams;
const PaDeviceInfo *info;
#else
QAudioOutput* audioOutput=Q_NULLPTR;
QAudioInput* audioInput=Q_NULLPTR;

Wyświetl plik

@ -106,6 +106,11 @@ wfmain::~wfmain()
delete rpt;
delete ui;
delete settings;
#if defined(PORTAUDIO)
Pa_Terminate();
#endif
}
void wfmain::closeEvent(QCloseEvent *event)
@ -1023,6 +1028,35 @@ void wfmain::setAudioDevicesUI()
#elif defined(PORTAUDIO)
// Use PortAudio device enumeration
PaError err;
err = Pa_Initialize();
if (err != paNoError)
{
qInfo(logAudio()) << "ERROR: Cannot initialize Portaudio";
}
qInfo(logAudio()) << "PortAudio version: " << Pa_GetVersionInfo()->versionText;
int numDevices;
numDevices = Pa_GetDeviceCount();
qInfo(logAudio()) << "Pa_CountDevices returned" << numDevices;
const PaDeviceInfo* info;
for (int i = 0; i < numDevices; i++)
{
info = Pa_GetDeviceInfo(i);
if (info->maxInputChannels > 0) {
qInfo(logAudio()) << (i == Pa_GetDefaultInputDevice() ? "*" : " ") << "(" << i << ") Output Device : " << info->name;
ui->audioInputCombo->addItem(info->name, i);
}
if (info->maxOutputChannels > 0) {
qInfo(logAudio()) << (i == Pa_GetDefaultOutputDevice() ? "*" : " ") << "(" << i << ") Input Device : " << info->name;
ui->audioOutputCombo->addItem(info->name, i);
}
}
#else
// If no external library is configured, use QTMultimedia
@ -1466,6 +1500,7 @@ void wfmain::loadSettings()
#if defined(RTAUDIO)
rxSetup.port = ui->audioOutputCombo->itemData(audioOutputIndex).toInt();
#elif defined(PORTAUDIO)
rxSetup.port = ui->audioOutputCombo->itemData(audioOutputIndex).toInt();
#else
QVariant v = ui->audioOutputCombo->currentData();
rxSetup.port = v.value<QAudioDeviceInfo>();
@ -1482,6 +1517,7 @@ void wfmain::loadSettings()
#if defined(RTAUDIO)
txSetup.port = ui->audioInputCombo->itemData(audioInputIndex).toInt();
#elif defined(PORTAUDIO)
txSetup.port = ui->audioInputCombo->itemData(audioInputIndex).toInt();
#else
QVariant v = ui->audioInputCombo->currentData();
txSetup.port = v.value<QAudioDeviceInfo>();
@ -4223,6 +4259,7 @@ void wfmain::on_audioOutputCombo_currentIndexChanged(int value)
#if defined(RTAUDIO)
rxSetup.port = ui->audioOutputCombo->itemData(value).toInt();
#elif defined(PORTAUDIO)
rxSetup.port = ui->audioOutputCombo->itemData(value).toInt();
#else
QVariant v = ui->audioOutputCombo->itemData(value);
rxSetup.port = v.value<QAudioDeviceInfo>();
@ -4236,6 +4273,7 @@ void wfmain::on_audioInputCombo_currentIndexChanged(int value)
#if defined(RTAUDIO)
txSetup.port = ui->audioInputCombo->itemData(value).toInt();
#elif defined(PORTAUDIO)
txSetup.port = ui->audioInputCombo->itemData(value).toInt();
#else
QVariant v = ui->audioInputCombo->itemData(value);
txSetup.port = v.value<QAudioDeviceInfo>();

Wyświetl plik

@ -46,7 +46,7 @@ DEFINES += PREFIX=\\\"$$PREFIX\\\"
# Choose audio system, uses QTMultimedia if both are commented out.
# DEFINES += RTAUDIO
# DEFINES += PORTAUDIO
DEFINES += PORTAUDIO
contains(DEFINES, RTAUDIO) {
# RTAudio defines