diff --git a/fcdlib/fcdtraits.cpp b/fcdlib/fcdtraits.cpp
index 41f8b66a6..40592dd80 100644
--- a/fcdlib/fcdtraits.cpp
+++ b/fcdlib/fcdtraits.cpp
@@ -1,15 +1,27 @@
-/*
- * fcdtraits.cpp
- *
- * Created on: Sep 5, 2015
- * Author: f4exb
- */
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
#include "fcdtraits.h"
const char *fcd_traits::alsaDeviceName = "hw:CARD=V10";
const char *fcd_traits::alsaDeviceName = "hw:CARD=V20";
+const char *fcd_traits::qtDeviceName = "FUNcube_Dongle_V1.0";
+const char *fcd_traits::qtDeviceName = "FUNcube_Dongle_V2.0";
+
const char *fcd_traits::hardwareID = "FCDPro";
const char *fcd_traits::hardwareID = "FCDPro+";
@@ -23,7 +35,7 @@ const char *fcd_traits::pluginDisplayedName = "FunCube Pro Input";
const char *fcd_traits::pluginDisplayedName = "FunCube Pro+ Input";
const char *fcd_traits::pluginVersion = "4.0.0";
-const char *fcd_traits::pluginVersion = "4.0.0";
+const char *fcd_traits::pluginVersion = "4.3.0";
const int64_t fcd_traits::loLowLimitFreq = 64000000L;
const int64_t fcd_traits::loLowLimitFreq = 150000L;
diff --git a/fcdlib/fcdtraits.h b/fcdlib/fcdtraits.h
index a649edc39..b7b5a8365 100644
--- a/fcdlib/fcdtraits.h
+++ b/fcdlib/fcdtraits.h
@@ -1,9 +1,18 @@
-/*
- * fcdtraits.h
- *
- * Created on: 3 Sep 2015
- * Author: egriffiths
- */
+///////////////////////////////////////////////////////////////////////////////////
+// Copyright (C) 2015-2018 Edouard Griffiths, F4EXB //
+// //
+// This program is free software; you can redistribute it and/or modify //
+// it under the terms of the GNU General Public License as published by //
+// the Free Software Foundation as version 3 of the License, or //
+// //
+// This program is distributed in the hope that it will be useful, //
+// but WITHOUT ANY WARRANTY; without even the implied warranty of //
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the //
+// GNU General Public License V3 for more details. //
+// //
+// You should have received a copy of the GNU General Public License //
+// along with this program. If not, see . //
+///////////////////////////////////////////////////////////////////////////////////
#ifndef FCDLIB_FCDTRAITS_H_
#define FCDLIB_FCDTRAITS_H_
@@ -25,6 +34,7 @@ struct fcd_traits
static const int convBufSize = (1<<11);
static const int fcdBufSize = (1<<12);
static const char *alsaDeviceName;
+ static const char *qtDeviceName;
static const char *hardwareID;
static const char *interfaceIID;
static const char *displayedName;
@@ -43,6 +53,7 @@ struct fcd_traits
static const int convBufSize = (1<<11);
static const int fcdBufSize = (1<<12);
static const char *alsaDeviceName;
+ static const char *qtDeviceName;
static const char *hardwareID;
static const char *interfaceIID;
static const char *displayedName;
@@ -58,9 +69,10 @@ struct fcd_traits
static const uint16_t vendorId = 0x04D8;
static const uint16_t productId = 0xFB31;
static const int sampleRate = 192000;
- static const int convBufSize = (1<<12);
- static const int fcdBufSize = (1<<18);
+ static const int convBufSize = (1<<10);
+ static const int fcdBufSize = (1<<18); // used in FCDProPlusReader
static const char *alsaDeviceName;
+ static const char *qtDeviceName;
static const char *hardwareID;
static const char *interfaceIID;
static const char *displayedName;
diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp
index dcb17cd09..9e431137f 100644
--- a/plugins/samplesource/fcdproplus/fcdproplusinput.cpp
+++ b/plugins/samplesource/fcdproplus/fcdproplusinput.cpp
@@ -1,5 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 2016 Edouard Griffiths, F4EXB //
+// Copyright (C) 2016-2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
@@ -14,8 +14,6 @@
// along with this program. If not, see . //
///////////////////////////////////////////////////////////////////////////////////
-// FIXME: FCD is handled very badly!
-
#include
#include
#include
@@ -47,6 +45,7 @@ FCDProPlusInput::FCDProPlusInput(DeviceSourceAPI *deviceAPI) :
m_deviceDescription(fcd_traits::displayedName),
m_running(false)
{
+ m_fcdFIFO.setSize(4*fcd_traits::convBufSize);
openDevice();
m_fileSink = new FileRecord(QString("test_%1.sdriq").arg(m_deviceAPI->getDeviceUID()));
m_deviceAPI->addSink(m_fileSink);
@@ -113,17 +112,17 @@ bool FCDProPlusInput::start()
return false;
}
- if (!openSource(fcd_traits::alsaDeviceName))
+ if (!openFCDAudio(fcd_traits::qtDeviceName))
{
- qCritical("FCDProPlusInput::start: could not open source");
+ qCritical("FCDProPlusInput::start: could not open FCD audio source");
return false;
}
else
{
- qDebug("FCDProPlusInput::start: source opened");
+ qDebug("FCDProPlusInput::start: FCD audio source opened");
}
- m_FCDThread = new FCDProPlusThread(&m_sampleFifo, fcd_handle);
+ m_FCDThread = new FCDProPlusThread(&m_sampleFifo, &m_fcdFIFO);
m_FCDThread->startWork();
// mutexLocker.unlock();
@@ -145,73 +144,33 @@ void FCDProPlusInput::closeDevice()
m_dev = 0;
}
-bool FCDProPlusInput::openSource(const char* cardname)
+bool FCDProPlusInput::openFCDAudio(const char* cardname)
{
- bool fail = false;
- snd_pcm_hw_params_t* params;
- //fcd_rate = FCDPP_RATE;
- //fcd_channels =2;
- //fcd_format = SND_PCM_SFMT_U16_LE;
- snd_pcm_stream_t fcd_stream = SND_PCM_STREAM_CAPTURE;
+ AudioDeviceManager *audioDeviceManager = DSPEngine::instance()->getAudioDeviceManager();
+ const QList& audioList = audioDeviceManager->getInputDevices();
- if (fcd_handle)
+ for (const auto &itAudio : audioList)
{
- qDebug("FCDProPlusInput::OpenSource: already opened");
- return false;
- }
-
- if (snd_pcm_open(&fcd_handle, cardname, fcd_stream, 0) < 0)
- {
- qCritical("FCDProPlusInput::OpenSource: cannot open %s", cardname);
- return false;
- }
-
- snd_pcm_hw_params_alloca(¶ms);
-
- if (snd_pcm_hw_params_any(fcd_handle, params) < 0)
- {
- qCritical("FCDProPlusInput::OpenSource: snd_pcm_hw_params_any failed");
- fail = true;
- }
- else if (snd_pcm_hw_params(fcd_handle, params) < 0)
- {
- qCritical("FCDProPlusInput::OpenSource: snd_pcm_hw_params failed");
- fail = true;
- // TODO: check actual samplerate, may be crippled firmware
- }
- else
- {
- if (snd_pcm_start(fcd_handle) < 0)
+ if (itAudio.deviceName().contains(QString(cardname)))
{
- qCritical("FCDProPlusInput::OpenSource: snd_pcm_start failed");
- fail = true;
- }
- else
- {
- qDebug("FCDProPlusInput::OpenSource: snd_pcm_start OK");
+ int fcdDeviceIndex = audioDeviceManager->getInputDeviceIndex(itAudio.deviceName());
+ m_fcdAudioInput.start(fcdDeviceIndex, fcd_traits::sampleRate);
+ int fcdSampleRate = m_fcdAudioInput.getRate();
+ qDebug("FCDProPlusInput::openFCDAudio: %s index %d at %d S/s",
+ itAudio.deviceName().toStdString().c_str(), fcdDeviceIndex, fcdSampleRate);
+ m_fcdAudioInput.addFifo(&m_fcdFIFO);
+ return true;
}
}
- if (fail)
- {
- snd_pcm_close(fcd_handle);
- return false;
- }
- else
- {
- qDebug("FCDProPlusInput::OpenSource: Funcube stream started");
- }
-
- return true;
+ qCritical("FCDProPlusInput::openFCDAudio: device with name %s not found", cardname);
+ return false;
}
-void FCDProPlusInput::closeSource()
+void FCDProPlusInput::closeFCDAudio()
{
- if (fcd_handle) {
- snd_pcm_close(fcd_handle);
- }
-
- fcd_handle = nullptr;
+ m_fcdAudioInput.removeFifo(&m_fcdFIFO);
+ m_fcdAudioInput.stop();
}
void FCDProPlusInput::stop()
@@ -224,7 +183,7 @@ void FCDProPlusInput::stop()
// wait for thread to quit ?
delete m_FCDThread;
m_FCDThread = nullptr;
- closeSource();
+ closeFCDAudio();
}
m_running = false;
diff --git a/plugins/samplesource/fcdproplus/fcdproplusinput.h b/plugins/samplesource/fcdproplus/fcdproplusinput.h
index 26eb53e61..99a139dff 100644
--- a/plugins/samplesource/fcdproplus/fcdproplusinput.h
+++ b/plugins/samplesource/fcdproplus/fcdproplusinput.h
@@ -23,7 +23,10 @@
#include
-#include
+#include "dsp/devicesamplesource.h"
+#include "audio/audioinput.h"
+#include "audio/audiofifo.h"
+
#include "fcdproplussettings.h"
#include "fcdhid.h"
@@ -149,13 +152,15 @@ public:
private:
bool openDevice();
void closeDevice();
- bool openSource(const char *filename);
- void closeSource();
+ bool openFCDAudio(const char *filename);
+ void closeFCDAudio();
void applySettings(const FCDProPlusSettings& settings, bool force);
void webapiFormatDeviceSettings(SWGSDRangel::SWGDeviceSettings& response, const FCDProPlusSettings& settings);
DeviceSourceAPI *m_deviceAPI;
hid_device *m_dev;
+ AudioInput m_fcdAudioInput;
+ AudioFifo m_fcdFIFO;
snd_pcm_t* fcd_handle;
QMutex m_mutex;
FCDProPlusSettings m_settings;
diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp
index 1be59d82a..0f742bde7 100644
--- a/plugins/samplesource/fcdproplus/fcdproplusthread.cpp
+++ b/plugins/samplesource/fcdproplus/fcdproplusthread.cpp
@@ -1,6 +1,5 @@
///////////////////////////////////////////////////////////////////////////////////
-// Copyright (C) 2012 maintech GmbH, Otto-Hahn-Str. 15, 97204 Hoechberg, Germany //
-// written by Christian Daniel //
+// Copyright (C) 2016-2018 Edouard Griffiths, F4EXB //
// //
// This program is free software; you can redistribute it and/or modify //
// it under the terms of the GNU General Public License as published by //
@@ -21,13 +20,13 @@
#include "fcdproplusthread.h"
#include "dsp/samplesinkfifo.h"
-#include "fcdtraits.h"
+#include "audio/audiofifo.h"
-FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, snd_pcm_t *fcd_handle, QObject* parent) :
+FCDProPlusThread::FCDProPlusThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent) :
QThread(parent),
- m_fcd_handle(fcd_handle),
+ m_fcdFIFO(fcdFIFO),
m_running(false),
- m_convertBuffer(fcd_traits::convBufSize),
+ m_convertBuffer(fcd_traits::convBufSize), // nb samples
m_sampleFifo(sampleFifo)
{
start();
@@ -62,43 +61,18 @@ void FCDProPlusThread::run()
m_running = true;
qDebug("FCDThread::run: start running loop");
- while (m_running)
- {
- if (work(fcd_traits::convBufSize) < 0) {
- break;
- }
+ while (m_running) {
+ work(fcd_traits::convBufSize);
}
qDebug("FCDThread::run: running loop stopped");
+ m_running = false;
}
-int FCDProPlusThread::work(int n_items)
+void FCDProPlusThread::work(unsigned int n_items)
{
- int l;
- SampleVector::iterator it;
- void *out;
-
- it = m_convertBuffer.begin();
- out = (void *)&it[0];
-
- l = snd_pcm_mmap_readi(m_fcd_handle, out, (snd_pcm_uframes_t)n_items);
-
- if (l > 0)
- {
- m_sampleFifo->write(it, it + l);
- }
- else
- {
- if (l == -EPIPE) {
- qDebug("FCDProPlusThread::work: Overrun detected");
- } else if (l < 0) {
- qDebug("FCDProPlusThread::work: snd_pcm_mmap_readi failed with code %d", l);
- } else {
- qDebug("FCDProPlusThread::work: snd_pcm_mmap_readi empty");
- }
-
- return 0;
- }
-
- return l;
+ uint32_t nbRead = m_fcdFIFO->read((unsigned char *) m_buf, n_items); // number of samples
+ SampleVector::iterator it = m_convertBuffer.begin();
+ m_decimators.decimate1(&it, m_buf, 2*nbRead);
+ m_sampleFifo->write(m_convertBuffer.begin(), it);
}
diff --git a/plugins/samplesource/fcdproplus/fcdproplusthread.h b/plugins/samplesource/fcdproplus/fcdproplusthread.h
index e797433cb..d8b7a7961 100644
--- a/plugins/samplesource/fcdproplus/fcdproplusthread.h
+++ b/plugins/samplesource/fcdproplus/fcdproplusthread.h
@@ -21,32 +21,36 @@
#include
#include
#include
-#include
-#include "dsp/inthalfbandfilter.h"
#include "dsp/samplesinkfifo.h"
+#include "dsp/decimators.h"
+#include "fcdtraits.h"
+
+class AudioFifo;
class FCDProPlusThread : public QThread {
Q_OBJECT
public:
- FCDProPlusThread(SampleSinkFifo* sampleFifo, snd_pcm_t *fcd_handle, QObject* parent = nullptr);
+ FCDProPlusThread(SampleSinkFifo* sampleFifo, AudioFifo *fcdFIFO, QObject* parent = nullptr);
~FCDProPlusThread();
void startWork();
void stopWork();
private:
- snd_pcm_t* m_fcd_handle;
+ AudioFifo* m_fcdFIFO;
QMutex m_startWaitMutex;
QWaitCondition m_startWaiter;
bool m_running;
+ qint16 m_buf[fcd_traits::convBufSize*2]; // stereo (I, Q)
SampleVector m_convertBuffer;
SampleSinkFifo* m_sampleFifo;
+ Decimators m_decimators;
void run();
- int work(int n_items);
+ void work(unsigned int n_items);
};
#endif // INCLUDE_FCDTHREAD_H
diff --git a/sdrbase/audio/audioinput.cpp b/sdrbase/audio/audioinput.cpp
index 316100dbb..28f4acb65 100644
--- a/sdrbase/audio/audioinput.cpp
+++ b/sdrbase/audio/audioinput.cpp
@@ -64,12 +64,12 @@ bool AudioInput::start(int device, int rate)
if (device < devicesInfo.size())
{
devInfo = devicesInfo[device];
- qWarning("AudioInput::start: using audio device #%d: %s", device, qPrintable(devInfo.defaultInputDevice().deviceName()));
+ qWarning("AudioInput::start: using audio device #%d: %s", device, qPrintable(devInfo.deviceName()));
}
else
{
devInfo = QAudioDeviceInfo::defaultInputDevice();
- qWarning("AudioInput::start: audio device #%d does not exist. Using default device %s", device, qPrintable(devInfo.defaultInputDevice().deviceName()));
+ qWarning("AudioInput::start: audio device #%d does not exist. Using default device %s", device, qPrintable(devInfo.deviceName()));
}
}
@@ -80,12 +80,13 @@ bool AudioInput::start(int device, int rate)
m_audioFormat.setSampleSize(16);
m_audioFormat.setCodec("audio/pcm");
m_audioFormat.setByteOrder(QAudioFormat::LittleEndian);
- m_audioFormat.setSampleType(QAudioFormat::SignedInt);
+ m_audioFormat.setSampleType(QAudioFormat::SignedInt); // Unknown, SignedInt, UnSignedInt, Float
if (!devInfo.isFormatSupported(m_audioFormat))
{
m_audioFormat = devInfo.nearestFormat(m_audioFormat);
- qWarning("AudioInput::start: %d Hz S16_LE audio format not supported. New rate: %d", rate, m_audioFormat.sampleRate());
+ qWarning("AudioInput::start: %d Hz S16_LE audio format not supported. Nearest is sampleRate: %d channelCount: %d sampleSize: %d sampleType: %d",
+ rate, m_audioFormat.sampleRate(), m_audioFormat.channelCount(), m_audioFormat.sampleSize(), (int) m_audioFormat.sampleType());
}
else
{