diff options
author | Christian Daniel <cd@maintech.de> | 2013-08-01 23:46:45 +0200 |
---|---|---|
committer | Christian Daniel <cd@maintech.de> | 2013-08-01 23:46:45 +0200 |
commit | 0f28461e70706d8f3910a801c81d8a51690b2319 (patch) | |
tree | 7477ef0afd36a5502a369fdfb9470425070cc091 | |
parent | fca9f8870f8fa8144a97c02843aa6004ddd26421 (diff) |
finalize switch to QAudioOutput, get rid of PortAudio
-rw-r--r-- | CMakeLists.txt | 7 | ||||
-rw-r--r-- | cmake/Modules/FindPortaudio.cmake | 35 | ||||
-rw-r--r-- | include-gpl/audio/audiooutput.h | 50 | ||||
-rw-r--r-- | include-gpl/audio/portaudioholder.h | 13 | ||||
-rw-r--r-- | include-gpl/mainwindow.h | 2 | ||||
-rw-r--r-- | sdrbase/audio/audiodeviceinfo.cpp | 55 | ||||
-rw-r--r-- | sdrbase/audio/audiooutput.cpp | 194 | ||||
-rw-r--r-- | sdrbase/audio/portaudioholder.cpp | 26 |
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"); - } -} |