summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Daniel <cd@maintech.de>2013-08-01 23:46:45 +0200
committerChristian Daniel <cd@maintech.de>2013-08-01 23:46:45 +0200
commit0f28461e70706d8f3910a801c81d8a51690b2319 (patch)
tree7477ef0afd36a5502a369fdfb9470425070cc091
parentfca9f8870f8fa8144a97c02843aa6004ddd26421 (diff)
finalize switch to QAudioOutput, get rid of PortAudio
-rw-r--r--CMakeLists.txt7
-rw-r--r--cmake/Modules/FindPortaudio.cmake35
-rw-r--r--include-gpl/audio/audiooutput.h50
-rw-r--r--include-gpl/audio/portaudioholder.h13
-rw-r--r--include-gpl/mainwindow.h2
-rw-r--r--sdrbase/audio/audiodeviceinfo.cpp55
-rw-r--r--sdrbase/audio/audiooutput.cpp194
-rw-r--r--sdrbase/audio/portaudioholder.cpp26
8 files changed, 84 insertions, 298 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 272efac..56c833f 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -16,7 +16,6 @@ find_package(Qt5Multimedia 5.0 REQUIRED)
find_package(OpenGL REQUIRED)
find_package(PkgConfig)
-find_package(Portaudio REQUIRED)
find_package(FFTW3F)
##############################################################################
@@ -32,7 +31,6 @@ set(sdrbase_SOURCES
sdrbase/audio/audiodeviceinfo.cpp
sdrbase/audio/audiofifo.cpp
sdrbase/audio/audiooutput.cpp
- sdrbase/audio/portaudioholder.cpp
sdrbase/dsp/channelizer.cpp
sdrbase/dsp/channelmarker.cpp
@@ -90,7 +88,6 @@ set(sdrbase_HEADERS
include-gpl/audio/audiodeviceinfo.h
include-gpl/audio/audiofifo.h
include-gpl/audio/audiooutput.h
- include-gpl/audio/portaudioholder.h
include-gpl/dsp/channelizer.h
include/dsp/channelmarker.h
@@ -210,7 +207,6 @@ add_library(sdrbase SHARED
target_link_libraries(sdrbase
${QT_LIBRARIES}
${OPENGL_LIBRARIES}
- ${PORTAUDIO_LIBRARIES}
${LIBUSB_LIBRARIES}
)
@@ -227,11 +223,10 @@ include_directories(
${CMAKE_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/include-gpl
${OPENGL_INCLUDE_DIR}
- ${PORTAUDIO_INCLUDE_DIRS}
)
if(MSVC)
- set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox" )
+ set( CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Oi /GL /Ot /Ox" )
set( CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /LTCG" )
add_definitions (/D "_CRT_SECURE_NO_WARNINGS")
endif()
diff --git a/cmake/Modules/FindPortaudio.cmake b/cmake/Modules/FindPortaudio.cmake
deleted file mode 100644
index 3f23a9c..0000000
--- a/cmake/Modules/FindPortaudio.cmake
+++ /dev/null
@@ -1,35 +0,0 @@
-# - Try to find Portaudio
-# Once done this will define
-#
-# PORTAUDIO_FOUND - system has Portaudio
-# PORTAUDIO_INCLUDE_DIRS - the Portaudio include directory
-# PORTAUDIO_LIBRARIES - Link these to use Portaudio
-
-include(FindPkgConfig)
-pkg_check_modules(PC_PORTAUDIO portaudio-2.0)
-
-find_path(PORTAUDIO_INCLUDE_DIRS
- NAMES
- portaudio.h
- PATHS
- /usr/local/include
- /usr/include
- HINTS
- ${PC_PORTAUDIO_INCLUDE_DIR}
-)
-
-find_library(PORTAUDIO_LIBRARIES
- NAMES
- portaudio
- PATHS
- /usr/local/lib
- /usr/lib
- /usr/lib64
- HINTS
- ${PC_PORTAUDIO_LIBDIR}
-)
-
-mark_as_advanced(PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES)
-
-INCLUDE(FindPackageHandleStandardArgs)
-FIND_PACKAGE_HANDLE_STANDARD_ARGS(PORTAUDIO DEFAULT_MSG PORTAUDIO_INCLUDE_DIRS PORTAUDIO_LIBRARIES)
diff --git a/include-gpl/audio/audiooutput.h b/include-gpl/audio/audiooutput.h
index 487b29f..10816ac 100644
--- a/include-gpl/audio/audiooutput.h
+++ b/include-gpl/audio/audiooutput.h
@@ -18,70 +18,40 @@
#ifndef INCLUDE_AUDIOOUTPUT_H
#define INCLUDE_AUDIOOUTPUT_H
-#include <QIODevice>
-#include <QThread>
#include <QMutex>
-#include <QAudioOutput>
+#include <QIODevice>
#include <list>
#include <vector>
#include "util/export.h"
+class QAudioOutput;
class AudioFifo;
-class AudioOutput;
+class AudioOutputPipe;
-class SoundThread : public QThread
-{
- Q_OBJECT
-public:
- explicit SoundThread(AudioOutput* out, QObject *parent = 0);
- ~SoundThread();
- void run();
-
-signals:
-
-public slots:
- void play();
- void stop();
- void kill();
-private:
- void playInt();
-
- AudioOutput* m_generator;
- QAudioOutput* m_audioOutput;
-
-};
-
-class SDRANGELOVE_API AudioOutput : public QIODevice{
- Q_OBJECT
+class SDRANGELOVE_API AudioOutput : QIODevice {
public:
AudioOutput();
~AudioOutput();
- void start();
bool start(int device, int rate);
void stop();
void addFifo(AudioFifo* audioFifo);
void removeFifo(AudioFifo* audioFifo);
- qint64 readData(char *data, qint64 maxlen);
- qint64 writeData(const char *data, qint64 len);
- //int bufferedSamples();
-
private:
QMutex m_mutex;
- //AudioFifo* m_audioFifo;
+ QAudioOutput* m_audioOutput;
+
typedef std::list<AudioFifo*> AudioFifos;
AudioFifos m_audioFifos;
std::vector<qint32> m_mixBuffer;
- int m_sampleRate;
- //PaTime m_streamStartTime;
-
- SoundThread _sfxThread;
+ bool open(OpenMode mode);
+ qint64 readData(char* data, qint64 maxLen);
+ qint64 writeData(const char* data, qint64 len);
- int callback(void* outputBuffer,
- unsigned long framesPerBuffer);
+ friend class AudioOutputPipe;
};
#endif // INCLUDE_AUDIOOUTPUT_H
diff --git a/include-gpl/audio/portaudioholder.h b/include-gpl/audio/portaudioholder.h
deleted file mode 100644
index 9f6bd50..0000000
--- a/include-gpl/audio/portaudioholder.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef INCLUDE_PORTAUDIOHOLDER_H
-#define INCLUDE_PORTAUDIOHOLDER_H
-
-class PortAudioHolder {
-public:
- PortAudioHolder();
- ~PortAudioHolder();
-
-private:
- bool m_initialized;
-};
-
-#endif // INCLUDE_PORTAUDIOHOLDER_H
diff --git a/include-gpl/mainwindow.h b/include-gpl/mainwindow.h
index 8d944f4..c7396d5 100644
--- a/include-gpl/mainwindow.h
+++ b/include-gpl/mainwindow.h
@@ -20,7 +20,6 @@
#include <QMainWindow>
#include <QTimer>
-#include "audio/portaudioholder.h"
#include "settings/settings.h"
#include "util/export.h"
@@ -70,7 +69,6 @@ private:
Ui::MainWindow *ui;
- PortAudioHolder m_portAudioHolder;
AudioDeviceInfo* m_audioDeviceInfo;
MessageQueue* m_messageQueue;
diff --git a/sdrbase/audio/audiodeviceinfo.cpp b/sdrbase/audio/audiodeviceinfo.cpp
index 4d36691..e422878 100644
--- a/sdrbase/audio/audiodeviceinfo.cpp
+++ b/sdrbase/audio/audiodeviceinfo.cpp
@@ -19,65 +19,10 @@
AudioDeviceInfo::AudioDeviceInfo()
{
-// const PaDeviceInfo *deviceInfo;
-// const PaHostApiInfo *apiInfo;
-// PaError err;
-// int numDevices;
-// int i;
-//
-// if((numDevices = Pa_GetDeviceCount()) < 0) {
-// err = numDevices;
-// goto failed;
-// }
-//
-// m_devices.clear();
-//
-// for(i = 0; i < numDevices; i++) {
-// deviceInfo = Pa_GetDeviceInfo(i);
-// if(deviceInfo->maxOutputChannels >= 2) {
-// apiInfo = Pa_GetHostApiInfo(deviceInfo->hostApi);
-// m_devices.append(Device(
-// QString::fromLatin1(deviceInfo->name),
-// QString::fromLatin1(apiInfo->name),
-// i));
-// }
-// }
-// qDebug("Audio initialisation: %d devices found", m_devices.count());
-// return;
-//
-//failed:
-// if(err != paNoError)
-// qCritical("Audio initialisation failed: %s (%d)", Pa_GetErrorText(err), err);
}
int AudioDeviceInfo::match(const QString& api, const QString device) const
{
- if(m_devices.count() <= 0)
- return -1;
-
- // default - use first device
- if(api.isEmpty())
- return 0;
-
- if(device.isEmpty()) {
- // only match API
- for(int i = 0; i < m_devices.count(); ++i) {
- if(m_devices[i].api == api)
- return i;
- }
- } else {
- // match API and device name
- for(int i = 0; i < m_devices.count(); ++i) {
- if((m_devices[i].api == api) && (m_devices[i].name == device))
- return i;
- }
- // not found - only match API
- for(int i = 0; i < m_devices.count(); ++i) {
- if(m_devices[i].api == api)
- return i;
- }
- }
-
// nothing found - fall back to default
return 0;
}
diff --git a/sdrbase/audio/audiooutput.cpp b/sdrbase/audio/audiooutput.cpp
index ddd8f69..247111b 100644
--- a/sdrbase/audio/audiooutput.cpp
+++ b/sdrbase/audio/audiooutput.cpp
@@ -16,96 +16,22 @@
///////////////////////////////////////////////////////////////////////////////////
#include <string.h>
+#include <QAudioFormat>
+#include <QAudioDeviceInfo>
+#include <QAudioOutput>
#include "audio/audiooutput.h"
#include "audio/audiofifo.h"
-
-SoundThread::SoundThread(AudioOutput* out, QObject *parent) :
- m_generator(out)
- , m_audioOutput(0)
- , QThread(parent)
-{
- start();
-
- // Move event processing of SoundThread to this thread
- QObject::moveToThread(this);
-}
-
-SoundThread::~SoundThread()
-{
- stop();
- //delete m_audioOutput;
- quit();
- wait();
-}
-
-void SoundThread::stop()
-{
- m_audioOutput->stop();
-}
-
-void SoundThread::kill()
-{
- m_audioOutput->stop();
- delete m_audioOutput;
-}
-
-
-void SoundThread::play()
-{
- playInt();
-}
-
-
-void SoundThread::playInt()
-{
-
- //connect(m_audioOutput, SIGNAL(stateChanged(QAudio::State)), SLOT(stateChanged(QAudio::State)));
- m_generator->start();
- m_audioOutput->start(m_generator);
-}
-
-void SoundThread::run()
-{
- QAudioFormat m_format;
- QList<QAudioDeviceInfo> foo = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
- QAudioDeviceInfo m_device(foo[0]);
-
- m_format.setSampleRate(44100);
- m_format.setChannelCount(2);
- m_format.setSampleSize(16);
- m_format.setCodec("audio/pcm");
- m_format.setByteOrder(QAudioFormat::LittleEndian);
- m_format.setSampleType(QAudioFormat::SignedInt);
-
- QAudioDeviceInfo info(QAudioDeviceInfo::defaultOutputDevice());
- if (!info.isFormatSupported(m_format)) {
- qWarning("Default format not supported - trying to use nearest");
- m_format = info.nearestFormat(m_format);
- }
-
- //m_generator = new Generator(m_format, DurationSeconds*1000000, ToneFrequencyHz, this);
-
- delete m_audioOutput;
- m_audioOutput = 0;
- m_audioOutput = new QAudioOutput(m_device, m_format, this);
- //m_audioOutput->setBufferSize(16384);
-
- exec();
-}
-
AudioOutput::AudioOutput() :
m_mutex(),
- m_audioFifos(),
- m_sampleRate(0),
- _sfxThread(this)
+ m_audioOutput(NULL),
+ m_audioFifos()
{
}
AudioOutput::~AudioOutput()
{
stop();
- QMetaObject::invokeMethod(&_sfxThread, "kill", Qt::QueuedConnection);
QMutexLocker mutexLocker(&m_mutex);
for(AudioFifos::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it)
@@ -117,48 +43,91 @@ bool AudioOutput::start(int device, int rate)
{
QMutexLocker mutexLocker(&m_mutex);
- for(AudioFifos::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it)
- (*it)->clear();
+ Q_UNUSED(device);
+ Q_UNUSED(rate);
+
+ QAudioFormat format;
+ QAudioDeviceInfo devInfo(QAudioDeviceInfo::defaultOutputDevice());
+
+ format.setSampleRate(41000);
+ format.setChannelCount(2);
+ format.setSampleSize(16);
+ format.setCodec("audio/pcm");
+ format.setByteOrder(QAudioFormat::LittleEndian);
+ format.setSampleType(QAudioFormat::SignedInt);
+
+ if(!devInfo.isFormatSupported(format)) {
+ qDebug("default format not supported - try to use nearest");
+ format = devInfo.nearestFormat(format);
+ }
+
+ if(format.sampleSize() != 16) {
+ qDebug("audio device doesn't support 16 bit samples (%s)", qPrintable(devInfo.defaultOutputDevice().deviceName()));
+ return false;
+ }
+
+ m_audioOutput = new QAudioOutput(format);
+
+ QIODevice::open(QIODevice::ReadOnly);
+
+ m_audioOutput->start(this);
- QMetaObject::invokeMethod(&_sfxThread, "play", Qt::QueuedConnection);
return true;
+
}
+void AudioOutput::stop()
+{
+ QMutexLocker mutexLocker(&m_mutex);
-void AudioOutput::start()
+ if(m_audioOutput != NULL) {
+ delete m_audioOutput;
+ m_audioOutput = NULL;
+ }
+ QIODevice::close();
+}
+
+void AudioOutput::addFifo(AudioFifo* audioFifo)
{
- open(QIODevice::ReadOnly);
+ QMutexLocker mutexLocker(&m_mutex);
+
+ m_audioFifos.push_back(audioFifo);
}
-void AudioOutput::stop()
+void AudioOutput::removeFifo(AudioFifo* audioFifo)
{
QMutexLocker mutexLocker(&m_mutex);
- QMetaObject::invokeMethod(&_sfxThread, "stop", Qt::QueuedConnection);
- qDebug("AudioOutput: stopped");
- close();
+
+ m_audioFifos.remove(audioFifo);
}
+bool AudioOutput::open(OpenMode mode)
+{
+ Q_UNUSED(mode);
+ return false;
+}
-qint64 AudioOutput::readData(char *data, qint64 len)
+qint64 AudioOutput::readData(char* data, qint64 maxLen)
{
- int reallen = len/4;
QMutexLocker mutexLocker(&m_mutex);
- if(m_mixBuffer.size() != reallen * 2) {
- m_mixBuffer.resize(reallen * 2); // allocate 2 qint32 per frame (stereo)
- if(m_mixBuffer.size() != reallen * 2)
- return 0;
+ maxLen -= maxLen % 4;
+ int framesPerBuffer = maxLen / 4;
+ if(m_mixBuffer.size() < framesPerBuffer * 2) {
+ m_mixBuffer.resize(framesPerBuffer * 2); // allocate 2 qint32 per frame (stereo)
+ if(m_mixBuffer.size() != framesPerBuffer * 2)
+ return 0;
}
- memset(m_mixBuffer.data(), 0x00, m_mixBuffer.size() * sizeof(m_mixBuffer[0])); // start with silence
+ memset(m_mixBuffer.data(), 0x00, framesPerBuffer * sizeof(m_mixBuffer[0])); // start with silence
// sum up a block from all fifos
for(AudioFifos::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it) {
// use outputBuffer as temp - yes, one memcpy could be saved
- uint samples = (*it)->read((quint8*)data, reallen, 0);
+ uint samples = (*it)->read((quint8*)data, framesPerBuffer, 0);
const qint16* src = (const qint16*)data;
std::vector<qint32>::iterator dst = m_mixBuffer.begin();
- for(uint i = 0; i < samples; i++) {
+ for(int i = 0; i < samples; i++) {
*dst += *src;
++src;
++dst;
@@ -169,9 +138,9 @@ qint64 AudioOutput::readData(char *data, qint64 len)
}
// convert to int16
- std::vector<qint32>::const_iterator src = m_mixBuffer.begin();
+ std::vector<qint32>::const_iterator src = m_mixBuffer.begin();
qint16* dst = (qint16*)data;
- for(uint i = 0; i < reallen; ++i) {
+ for(int i = 0; i < framesPerBuffer; ++i) {
qint32 s = *src++;
if(s < -32768)
s = -32768;
@@ -180,29 +149,12 @@ qint64 AudioOutput::readData(char *data, qint64 len)
*dst++ = s;
}
- //qDebug("AudioOutput: read %d", len);
- return len;
-}
-
-qint64 AudioOutput::writeData(const char *data, qint64 len)
-{
- Q_UNUSED(data);
- Q_UNUSED(len);
- qDebug("AudioOutput: watwatwatwatwat??!");
- return 0;
-}
-
-void AudioOutput::addFifo(AudioFifo* audioFifo)
-{
- QMutexLocker mutexLocker(&m_mutex);
-
- m_audioFifos.push_back(audioFifo);
+ return maxLen;
}
-void AudioOutput::removeFifo(AudioFifo* audioFifo)
+qint64 AudioOutput::writeData(const char* data, qint64 len)
{
- QMutexLocker mutexLocker(&m_mutex);
-
- m_audioFifos.remove(audioFifo);
+ Q_UNUSED(data);
+ Q_UNUSED(len);
+ return 0;
}
-
diff --git a/sdrbase/audio/portaudioholder.cpp b/sdrbase/audio/portaudioholder.cpp
deleted file mode 100644
index 9a58781..0000000
--- a/sdrbase/audio/portaudioholder.cpp
+++ /dev/null
@@ -1,26 +0,0 @@
-#include <QMessageBox>
-//#include <portaudio.h>
-#include "audio/portaudioholder.h"
-
-PortAudioHolder::PortAudioHolder() :
- m_initialized(false)
-{
- //PaError err;
-
- //if((err = Pa_Initialize()) == paNoError) {
- m_initialized = true;
- qDebug("PortAudio initialized");
- //} else {
- // qCritical("PortAudio: could not initialise: %s (%d)", Pa_GetErrorText(err), err);
- // QString error = QObject::tr("PortAudio could not be initialised: %1 (%2)").arg(Pa_GetErrorText(err)).arg(err);
- // QMessageBox::critical(NULL, "PortAudio failure", error);
- //}
-}
-
-PortAudioHolder::~PortAudioHolder()
-{
- if(m_initialized) {
- //Pa_Terminate();
- qDebug("PortAudio terminated");
- }
-}