mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-23 12:48:40 -05:00
Fix audio input rate issue on Windows Vista
Windows Vista has a broken rate converter which gets invoked when an input audio stream at 48kHz sampel rate is requested. I've no idea why our application can't get exclusive access to the audio input device and have a unconverted stream direct at 48kHz. To get around this our down sampling filter for audio input from 48kHz to 12kHz is disaabled by default on Windows Vista, instead we request a 12kHz stream and process it directly. This default behviour can be overriden by specifying the following settings value: [Tune] Audio\DisableInputResampling=false This settings value defaults to true on Windows Vista and false everywhere else so normally needn't be present. git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/branches/wsjtx@3588 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
This commit is contained in:
parent
f858ff7038
commit
688943e779
49
Detector.cpp
49
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<qint64> (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<size_t> (maxSize / bytesPerFrame ()), framesAcceptable));
|
||||
|
||||
if (framesAccepted < static_cast<size_t> (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<unsigned> (m_framesPerSignal) && m_monitoring)
|
||||
{
|
||||
Q_EMIT framesWritten (jt9com_.kin);
|
||||
m_bufferPos = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (!secondInPeriod ())
|
||||
|
@ -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<short> m_buffer; // de-interleaved sample buffer
|
||||
|
15
main.cpp
15
main.cpp
@ -6,6 +6,7 @@
|
||||
#include <QApplication>
|
||||
#include <QObject>
|
||||
#include <QSettings>
|
||||
#include <QSysInfo>
|
||||
|
||||
#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()));
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user