diff --git a/Detector.cpp b/Detector.cpp index 240d17571..045d6380c 100644 --- a/Detector.cpp +++ b/Detector.cpp @@ -10,19 +10,15 @@ extern "C" { void fil4_(qint16*, qint32*, qint16*, qint32*); } -namespace -{ - unsigned const downsampleFactor = 4; -} - -Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, QObject * parent) +Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, unsigned downSampleFactor, QObject * parent) : AudioDevice (parent) , m_frameRate (frameRate) , m_period (periodLengthInSeconds) + , m_downSampleFactor (downSampleFactor) , m_framesPerSignal (framesPerSignal) , m_monitoring (false) , m_starting (false) - , m_buffer (new short [framesPerSignal * downsampleFactor]) + , m_buffer ((downSampleFactor > 1) ? new short [framesPerSignal * downSampleFactor] : 0) , m_bufferPos (0) { clear (); @@ -53,7 +49,7 @@ qint64 Detector::writeData (char const * data, qint64 maxSize) Q_ASSERT (!(maxSize % static_cast (bytesPerFrame ()))); // no torn frames // these are in terms of input frames (not down sampled) - size_t framesAcceptable ((sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]) - jt9com_.kin) * downsampleFactor); + size_t framesAcceptable ((sizeof (jt9com_.d2) / sizeof (jt9com_.d2[0]) - jt9com_.kin) * m_downSampleFactor); size_t framesAccepted (qMin (static_cast (maxSize / bytesPerFrame ()), framesAcceptable)); if (framesAccepted < static_cast (maxSize / bytesPerFrame ())) @@ -63,18 +59,33 @@ qint64 Detector::writeData (char const * data, qint64 maxSize) for (unsigned remaining = framesAccepted; remaining; ) { - size_t numFramesProcessed (qMin (m_framesPerSignal * downsampleFactor - m_bufferPos, remaining)); - store (&data[(framesAccepted - remaining) * bytesPerFrame ()], numFramesProcessed, &m_buffer[m_bufferPos]); - m_bufferPos += numFramesProcessed; - if (m_bufferPos == m_framesPerSignal * downsampleFactor && m_monitoring) - { - qint32 framesToProcess (m_framesPerSignal * downsampleFactor); - qint32 framesAfterDownSample; - fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin], &framesAfterDownSample); - m_bufferPos = 0; + size_t numFramesProcessed (qMin (m_framesPerSignal * m_downSampleFactor - m_bufferPos, remaining)); - jt9com_.kin += framesAfterDownSample; - Q_EMIT framesWritten (jt9com_.kin); + if (m_downSampleFactor > 1) + { + store (&data[(framesAccepted - remaining) * bytesPerFrame ()], numFramesProcessed, &m_buffer[m_bufferPos]); + m_bufferPos += numFramesProcessed; + if (m_bufferPos == m_framesPerSignal * m_downSampleFactor && m_monitoring) + { + qint32 framesToProcess (m_framesPerSignal * m_downSampleFactor); + qint32 framesAfterDownSample; + fil4_(&m_buffer[0], &framesToProcess, &jt9com_.d2[jt9com_.kin], &framesAfterDownSample); + jt9com_.kin += framesAfterDownSample; + Q_EMIT framesWritten (jt9com_.kin); + m_bufferPos = 0; + } + + } + else + { + store (&data[(framesAccepted - remaining) * bytesPerFrame ()], numFramesProcessed, &jt9com_.d2[jt9com_.kin]); + m_bufferPos += numFramesProcessed; + jt9com_.kin += numFramesProcessed; + if (m_bufferPos == static_cast (m_framesPerSignal) && m_monitoring) + { + Q_EMIT framesWritten (jt9com_.kin); + m_bufferPos = 0; + } } if (!secondInPeriod ()) diff --git a/Detector.hpp b/Detector.hpp index 46fb32f27..6003b7fd8 100644 --- a/Detector.hpp +++ b/Detector.hpp @@ -26,7 +26,7 @@ public: // // the framesPerSignal argument is the number after down sampling // - Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, QObject * parent = 0); + Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, unsigned downSampleFactor = 4u, QObject * parent = 0); bool isMonitoring () const {return m_monitoring;} @@ -52,7 +52,8 @@ private: unsigned m_frameRate; unsigned m_period; - qint32 m_framesPerSignal; // after down sampling + unsigned m_downSampleFactor; + qint32 m_framesPerSignal; // after any down sampling bool volatile m_monitoring; bool m_starting; QScopedArrayPointer m_buffer; // de-interleaved sample buffer diff --git a/main.cpp b/main.cpp index c52f259c7..ad348a014 100644 --- a/main.cpp +++ b/main.cpp @@ -6,6 +6,7 @@ #include #include #include +#include #include "mainwindow.h" @@ -55,8 +56,20 @@ int main(int argc, char *argv[]) } memset(to,0,size); //Zero all decoding params in shared memory + settings.beginGroup ("Tune"); + + // deal with Windows Vista input audio rate converter problems + unsigned downSampleFactor = settings.value ("Audio/DisableInputResampling", +#if defined (Q_OS_WIN) + QSysInfo::WV_VISTA == QSysInfo::WindowsVersion ? true : false +#else + false +#endif + ).toBool () ? 1u : 4u; + settings.endGroup (); + // Multiple instances: Call MainWindow() with the UUID key - MainWindow w(&settings, &mem_jt9, &my_key, fontSize2, fontWeight2); + MainWindow w(&settings, &mem_jt9, &my_key, fontSize2, fontWeight2, downSampleFactor); w.show(); QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit())); diff --git a/mainwindow.cpp b/mainwindow.cpp index 3b9e9a361..10e784f7c 100644 --- a/mainwindow.cpp +++ b/mainwindow.cpp @@ -42,14 +42,14 @@ QString Program_Title_Version=" WSJT-X v1.2.1, r" + rev.mid(6,4) + //-------------------------------------------------- MainWindow constructor // Multiple instances: new arg *thekey MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *thekey, - qint32 fontSize2, qint32 fontWeight2, + qint32 fontSize2, qint32 fontWeight2, unsigned downSampleFactor, QWidget *parent) : QMainWindow(parent), m_settings (settings), ui(new Ui::MainWindow), m_wideGraph (new WideGraph (settings)), m_logDlg (new LogQSO (settings, this)), - m_detector (RX_SAMPLE_RATE, NTMAX / 2, 6912 / 2), + m_detector (RX_SAMPLE_RATE, NTMAX / 2, 6912 / 2, downSampleFactor), m_audioInputDevice (QAudioDeviceInfo::defaultInputDevice ()), // start with default m_modulator (TX_SAMPLE_RATE, NTMAX / 2), m_audioOutputDevice (QAudioDeviceInfo::defaultOutputDevice ()), // start with default @@ -57,6 +57,7 @@ MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *the psk_Reporter (new PSK_Reporter (this)), m_msAudioOutputBuffered (0u), m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10), + m_downSampleFactor (downSampleFactor), m_audioThreadPriority (QThread::HighPriority) { ui->setupUi(this); @@ -91,8 +92,8 @@ MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *the , &m_modulator, SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double))); // hook up the audio input stream - connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *)) - , &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *))); + connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned)) + , &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned))); connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ())); connect(&m_soundInput, SIGNAL (error (QString)), this, SLOT (showSoundInError (QString))); @@ -394,7 +395,7 @@ MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *the connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished())); Q_EMIT startDetector (m_audioInputChannel); - Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector); + Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor); Q_EMIT transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0)); Q_EMIT muteAudioOutput (false); @@ -855,7 +856,7 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog Q_EMIT stopAudioInputStream (); Q_EMIT detectorClose (); Q_EMIT startDetector (m_audioInputChannel); - Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector); + Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor); } if(dlg.m_restartSoundOut) { @@ -892,7 +893,7 @@ void MainWindow::on_monitorButton_clicked() //Monitor { m_monitoring=true; Q_EMIT detectorSetMonitoring (true); - // Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector); + // Q_EMIT startAudioInputStream (m_audioInputDevice, AudioDevice::Mono == m_audioInputChannel ? 1 : 2, m_framesAudioInputBuffered, &m_detector, m_downSampleFactor); m_diskData=false; } diff --git a/mainwindow.h b/mainwindow.h index 270ddacba..1bb456d91 100644 --- a/mainwindow.h +++ b/mainwindow.h @@ -48,8 +48,8 @@ class MainWindow : public QMainWindow // Multiple instances: call MainWindow() with *thekey public: - explicit MainWindow(QSettings *, QSharedMemory *shdmem, QString *thekey, \ - qint32 fontSize2, qint32 fontWeight2, \ + explicit MainWindow(QSettings *, QSharedMemory *shdmem, QString *thekey, + qint32 fontSize2, qint32 fontWeight2, unsigned downSampleFactor, QWidget *parent = 0); ~MainWindow(); @@ -184,7 +184,7 @@ private slots: Q_SIGNAL void startAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered); Q_SIGNAL void stopAudioOutputStream (); - Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink); + Q_SIGNAL void startAudioInputStream (QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor); Q_SIGNAL void stopAudioInputStream (); Q_SIGNAL void startDetector (AudioDevice::Channel); @@ -391,6 +391,7 @@ private: DecodedText m_QSOText; unsigned m_msAudioOutputBuffered; unsigned m_framesAudioInputBuffered; + unsigned m_downSampleFactor; QThread::Priority m_audioThreadPriority; diff --git a/soundin.cpp b/soundin.cpp index 32f478586..caf61d376 100644 --- a/soundin.cpp +++ b/soundin.cpp @@ -38,7 +38,7 @@ bool SoundInput::audioError () const return result; } -void SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int framesPerBuffer, QIODevice * sink) +void SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor) { Q_ASSERT (0 < channels && channels < 3); Q_ASSERT (sink); @@ -48,7 +48,7 @@ void SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int fr QAudioFormat format (device.preferredFormat()); format.setChannelCount (channels); format.setCodec ("audio/pcm"); - format.setSampleRate (48000); + format.setSampleRate (12000 * downSampleFactor); format.setSampleType (QAudioFormat::SignedInt); format.setSampleSize (16); diff --git a/soundin.h b/soundin.h index f153957e6..8f8c663d7 100644 --- a/soundin.h +++ b/soundin.h @@ -31,7 +31,7 @@ class SoundInput : public QObject Q_SIGNAL void status (QString message) const; // sink must exist from the start call to any following stop () call - Q_SLOT void start(QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink); + Q_SLOT void start(QAudioDeviceInfo const&, unsigned channels, int framesPerBuffer, QIODevice * sink, unsigned downSampleFactor); Q_SLOT void stop(); // used internally