mirror of
https://github.com/saitohirga/WSJT-X.git
synced 2024-11-27 06:38:44 -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*);
|
void fil4_(qint16*, qint32*, qint16*, qint32*);
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace
|
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, unsigned downSampleFactor, QObject * parent)
|
||||||
{
|
|
||||||
unsigned const downsampleFactor = 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
Detector::Detector (unsigned frameRate, unsigned periodLengthInSeconds, unsigned framesPerSignal, QObject * parent)
|
|
||||||
: AudioDevice (parent)
|
: AudioDevice (parent)
|
||||||
, m_frameRate (frameRate)
|
, m_frameRate (frameRate)
|
||||||
, m_period (periodLengthInSeconds)
|
, m_period (periodLengthInSeconds)
|
||||||
|
, m_downSampleFactor (downSampleFactor)
|
||||||
, m_framesPerSignal (framesPerSignal)
|
, m_framesPerSignal (framesPerSignal)
|
||||||
, m_monitoring (false)
|
, m_monitoring (false)
|
||||||
, m_starting (false)
|
, m_starting (false)
|
||||||
, m_buffer (new short [framesPerSignal * downsampleFactor])
|
, m_buffer ((downSampleFactor > 1) ? new short [framesPerSignal * downSampleFactor] : 0)
|
||||||
, m_bufferPos (0)
|
, m_bufferPos (0)
|
||||||
{
|
{
|
||||||
clear ();
|
clear ();
|
||||||
@ -53,7 +49,7 @@ qint64 Detector::writeData (char const * data, qint64 maxSize)
|
|||||||
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ()))); // no torn frames
|
Q_ASSERT (!(maxSize % static_cast<qint64> (bytesPerFrame ()))); // no torn frames
|
||||||
|
|
||||||
// these are in terms of input frames (not down sampled)
|
// 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));
|
size_t framesAccepted (qMin (static_cast<size_t> (maxSize / bytesPerFrame ()), framesAcceptable));
|
||||||
|
|
||||||
if (framesAccepted < static_cast<size_t> (maxSize / bytesPerFrame ()))
|
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; )
|
for (unsigned remaining = framesAccepted; remaining; )
|
||||||
{
|
{
|
||||||
size_t numFramesProcessed (qMin (m_framesPerSignal * downsampleFactor - m_bufferPos, remaining));
|
size_t numFramesProcessed (qMin (m_framesPerSignal * m_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;
|
|
||||||
|
|
||||||
jt9com_.kin += framesAfterDownSample;
|
if (m_downSampleFactor > 1)
|
||||||
Q_EMIT framesWritten (jt9com_.kin);
|
{
|
||||||
|
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 ())
|
if (!secondInPeriod ())
|
||||||
|
@ -26,7 +26,7 @@ public:
|
|||||||
//
|
//
|
||||||
// the framesPerSignal argument is the number after down sampling
|
// 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;}
|
bool isMonitoring () const {return m_monitoring;}
|
||||||
|
|
||||||
@ -52,7 +52,8 @@ private:
|
|||||||
|
|
||||||
unsigned m_frameRate;
|
unsigned m_frameRate;
|
||||||
unsigned m_period;
|
unsigned m_period;
|
||||||
qint32 m_framesPerSignal; // after down sampling
|
unsigned m_downSampleFactor;
|
||||||
|
qint32 m_framesPerSignal; // after any down sampling
|
||||||
bool volatile m_monitoring;
|
bool volatile m_monitoring;
|
||||||
bool m_starting;
|
bool m_starting;
|
||||||
QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
|
QScopedArrayPointer<short> m_buffer; // de-interleaved sample buffer
|
||||||
|
15
main.cpp
15
main.cpp
@ -6,6 +6,7 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
#include <QSysInfo>
|
||||||
|
|
||||||
#include "mainwindow.h"
|
#include "mainwindow.h"
|
||||||
|
|
||||||
@ -55,8 +56,20 @@ int main(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
memset(to,0,size); //Zero all decoding params in shared memory
|
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
|
// 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();
|
w.show();
|
||||||
|
|
||||||
QObject::connect (&a, SIGNAL (lastWindowClosed()), &a, SLOT (quit()));
|
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
|
//-------------------------------------------------- MainWindow constructor
|
||||||
// Multiple instances: new arg *thekey
|
// Multiple instances: new arg *thekey
|
||||||
MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *thekey,
|
MainWindow::MainWindow(QSettings * settings, QSharedMemory *shdmem, QString *thekey,
|
||||||
qint32 fontSize2, qint32 fontWeight2,
|
qint32 fontSize2, qint32 fontWeight2, unsigned downSampleFactor,
|
||||||
QWidget *parent) :
|
QWidget *parent) :
|
||||||
QMainWindow(parent),
|
QMainWindow(parent),
|
||||||
m_settings (settings),
|
m_settings (settings),
|
||||||
ui(new Ui::MainWindow),
|
ui(new Ui::MainWindow),
|
||||||
m_wideGraph (new WideGraph (settings)),
|
m_wideGraph (new WideGraph (settings)),
|
||||||
m_logDlg (new LogQSO (settings, this)),
|
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_audioInputDevice (QAudioDeviceInfo::defaultInputDevice ()), // start with default
|
||||||
m_modulator (TX_SAMPLE_RATE, NTMAX / 2),
|
m_modulator (TX_SAMPLE_RATE, NTMAX / 2),
|
||||||
m_audioOutputDevice (QAudioDeviceInfo::defaultOutputDevice ()), // start with default
|
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)),
|
psk_Reporter (new PSK_Reporter (this)),
|
||||||
m_msAudioOutputBuffered (0u),
|
m_msAudioOutputBuffered (0u),
|
||||||
m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
|
m_framesAudioInputBuffered (RX_SAMPLE_RATE / 10),
|
||||||
|
m_downSampleFactor (downSampleFactor),
|
||||||
m_audioThreadPriority (QThread::HighPriority)
|
m_audioThreadPriority (QThread::HighPriority)
|
||||||
{
|
{
|
||||||
ui->setupUi(this);
|
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)));
|
, &m_modulator, SLOT (open (unsigned, double, unsigned, AudioDevice::Channel, bool, double)));
|
||||||
|
|
||||||
// hook up the audio input stream
|
// hook up the audio input stream
|
||||||
connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *))
|
connect (this, SIGNAL (startAudioInputStream (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned))
|
||||||
, &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *)));
|
, &m_soundInput, SLOT (start (QAudioDeviceInfo const&, unsigned, int, QIODevice *, unsigned)));
|
||||||
connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ()));
|
connect (this, SIGNAL (stopAudioInputStream ()), &m_soundInput, SLOT (stop ()));
|
||||||
|
|
||||||
connect(&m_soundInput, SIGNAL (error (QString)), this, SLOT (showSoundInError (QString)));
|
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()));
|
connect(watcher2, SIGNAL(finished()),this,SLOT(diskWriteFinished()));
|
||||||
|
|
||||||
Q_EMIT startDetector (m_audioInputChannel);
|
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 transmitFrequency (m_txFreq - (m_bSplit || m_bXIT ? m_XIT : 0));
|
||||||
Q_EMIT muteAudioOutput (false);
|
Q_EMIT muteAudioOutput (false);
|
||||||
@ -855,7 +856,7 @@ void MainWindow::on_actionDeviceSetup_triggered() //Setup Dialog
|
|||||||
Q_EMIT stopAudioInputStream ();
|
Q_EMIT stopAudioInputStream ();
|
||||||
Q_EMIT detectorClose ();
|
Q_EMIT detectorClose ();
|
||||||
Q_EMIT startDetector (m_audioInputChannel);
|
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) {
|
if(dlg.m_restartSoundOut) {
|
||||||
@ -892,7 +893,7 @@ void MainWindow::on_monitorButton_clicked() //Monitor
|
|||||||
{
|
{
|
||||||
m_monitoring=true;
|
m_monitoring=true;
|
||||||
Q_EMIT detectorSetMonitoring (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;
|
m_diskData=false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,8 +48,8 @@ class MainWindow : public QMainWindow
|
|||||||
|
|
||||||
// Multiple instances: call MainWindow() with *thekey
|
// Multiple instances: call MainWindow() with *thekey
|
||||||
public:
|
public:
|
||||||
explicit MainWindow(QSettings *, QSharedMemory *shdmem, QString *thekey, \
|
explicit MainWindow(QSettings *, QSharedMemory *shdmem, QString *thekey,
|
||||||
qint32 fontSize2, qint32 fontWeight2, \
|
qint32 fontSize2, qint32 fontWeight2, unsigned downSampleFactor,
|
||||||
QWidget *parent = 0);
|
QWidget *parent = 0);
|
||||||
~MainWindow();
|
~MainWindow();
|
||||||
|
|
||||||
@ -184,7 +184,7 @@ private slots:
|
|||||||
Q_SIGNAL void startAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered);
|
Q_SIGNAL void startAudioOutputStream (QAudioDeviceInfo, unsigned channels, unsigned msBuffered);
|
||||||
Q_SIGNAL void stopAudioOutputStream ();
|
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 stopAudioInputStream ();
|
||||||
|
|
||||||
Q_SIGNAL void startDetector (AudioDevice::Channel);
|
Q_SIGNAL void startDetector (AudioDevice::Channel);
|
||||||
@ -391,6 +391,7 @@ private:
|
|||||||
DecodedText m_QSOText;
|
DecodedText m_QSOText;
|
||||||
unsigned m_msAudioOutputBuffered;
|
unsigned m_msAudioOutputBuffered;
|
||||||
unsigned m_framesAudioInputBuffered;
|
unsigned m_framesAudioInputBuffered;
|
||||||
|
unsigned m_downSampleFactor;
|
||||||
QThread::Priority m_audioThreadPriority;
|
QThread::Priority m_audioThreadPriority;
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ bool SoundInput::audioError () const
|
|||||||
return result;
|
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 (0 < channels && channels < 3);
|
||||||
Q_ASSERT (sink);
|
Q_ASSERT (sink);
|
||||||
@ -48,7 +48,7 @@ void SoundInput::start(QAudioDeviceInfo const& device, unsigned channels, int fr
|
|||||||
QAudioFormat format (device.preferredFormat());
|
QAudioFormat format (device.preferredFormat());
|
||||||
format.setChannelCount (channels);
|
format.setChannelCount (channels);
|
||||||
format.setCodec ("audio/pcm");
|
format.setCodec ("audio/pcm");
|
||||||
format.setSampleRate (48000);
|
format.setSampleRate (12000 * downSampleFactor);
|
||||||
format.setSampleType (QAudioFormat::SignedInt);
|
format.setSampleType (QAudioFormat::SignedInt);
|
||||||
format.setSampleSize (16);
|
format.setSampleSize (16);
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ class SoundInput : public QObject
|
|||||||
Q_SIGNAL void status (QString message) const;
|
Q_SIGNAL void status (QString message) const;
|
||||||
|
|
||||||
// sink must exist from the start call to any following stop () call
|
// 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();
|
Q_SLOT void stop();
|
||||||
|
|
||||||
// used internally
|
// used internally
|
||||||
|
Loading…
Reference in New Issue
Block a user