kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			UDP source plugin: implemented squelch gate
							rodzic
							
								
									2c3f7fe690
								
							
						
					
					
						commit
						587d38665d
					
				| 
						 | 
				
			
			@ -30,17 +30,9 @@ MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcConfigureImmediate, Message)
 | 
			
		|||
MESSAGE_CLASS_DEFINITION(UDPSrc::MsgUDPSrcSpectrum, Message)
 | 
			
		||||
 | 
			
		||||
UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampleSink* spectrum) :
 | 
			
		||||
	m_udpPort(9999),
 | 
			
		||||
	m_gain(1.0),
 | 
			
		||||
	m_audioActive(false),
 | 
			
		||||
	m_audioStereo(false),
 | 
			
		||||
	m_volume(20),
 | 
			
		||||
    m_fmDeviation(2500),
 | 
			
		||||
    m_outMovingAverage(480, 1e-10),
 | 
			
		||||
    m_inMovingAverage(480, 1e-10),
 | 
			
		||||
    m_audioFifo(4, 24000),
 | 
			
		||||
    m_squelch(1e-6),
 | 
			
		||||
    m_squelchEnabled(true),
 | 
			
		||||
    m_squelchOpen(false),
 | 
			
		||||
    m_squelchOpenCount(0),
 | 
			
		||||
    m_squelchCloseCount(0),
 | 
			
		||||
| 
						 | 
				
			
			@ -49,22 +41,17 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampl
 | 
			
		|||
{
 | 
			
		||||
	setObjectName("UDPSrc");
 | 
			
		||||
 | 
			
		||||
	m_udpBuffer = new UDPSink<Sample>(this, udpBlockSize, m_udpPort);
 | 
			
		||||
	m_udpBufferMono = new UDPSink<FixReal>(this, udpBlockSize, m_udpPort);
 | 
			
		||||
	m_udpBuffer = new UDPSink<Sample>(this, udpBlockSize, m_config.m_udpPort);
 | 
			
		||||
	m_udpBufferMono = new UDPSink<FixReal>(this, udpBlockSize, m_config.m_udpPort);
 | 
			
		||||
	m_audioSocket = new QUdpSocket(this);
 | 
			
		||||
	m_udpAudioBuf = new char[m_udpAudioPayloadSize];
 | 
			
		||||
 | 
			
		||||
	m_audioBuffer.resize(1<<9);
 | 
			
		||||
	m_audioBufferFill = 0;
 | 
			
		||||
 | 
			
		||||
	m_inputSampleRate = 96000;
 | 
			
		||||
	m_sampleFormat = FormatS16LE;
 | 
			
		||||
	m_outputSampleRate = 48000;
 | 
			
		||||
	m_rfBandwidth = 32000;
 | 
			
		||||
	m_audioPort = m_udpPort - 1;
 | 
			
		||||
	m_nco.setFreq(0, m_inputSampleRate);
 | 
			
		||||
	m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
 | 
			
		||||
	m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
 | 
			
		||||
	m_nco.setFreq(0, m_config.m_inputSampleRate);
 | 
			
		||||
	m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.0);
 | 
			
		||||
	m_sampleDistanceRemain = m_config.m_inputSampleRate / m_config.m_outputSampleRate;
 | 
			
		||||
	m_uiMessageQueue = uiMessageQueue;
 | 
			
		||||
	m_udpSrcGUI = udpSrcGUI;
 | 
			
		||||
	m_spectrum = spectrum;
 | 
			
		||||
| 
						 | 
				
			
			@ -77,13 +64,13 @@ UDPSrc::UDPSrc(MessageQueue* uiMessageQueue, UDPSrcGUI* udpSrcGUI, BasebandSampl
 | 
			
		|||
	m_scale = 0;
 | 
			
		||||
	m_magsq = 0;
 | 
			
		||||
	m_inMagsq = 0;
 | 
			
		||||
	UDPFilter = new fftfilt(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate, udpBlockSize);
 | 
			
		||||
	UDPFilter = new fftfilt(0.0, (m_config.m_rfBandwidth / 2.0) / m_config.m_outputSampleRate, udpBlockSize);
 | 
			
		||||
 | 
			
		||||
	m_phaseDiscri.setFMScaling((float) m_outputSampleRate / (2.0f * m_fmDeviation));
 | 
			
		||||
	m_phaseDiscri.setFMScaling((float) m_config. m_outputSampleRate / (2.0f * m_config.m_fmDeviation));
 | 
			
		||||
 | 
			
		||||
	if (m_audioSocket->bind(QHostAddress::LocalHost, m_audioPort))
 | 
			
		||||
	if (m_audioSocket->bind(QHostAddress::LocalHost, m_config.m_audioPort))
 | 
			
		||||
	{
 | 
			
		||||
		qDebug("UDPSrc::UDPSrc: bind audio socket to port %d", m_audioPort);
 | 
			
		||||
		qDebug("UDPSrc::UDPSrc: bind audio socket to port %d", m_config.m_audioPort);
 | 
			
		||||
		connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection);
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -101,9 +88,10 @@ UDPSrc::~UDPSrc()
 | 
			
		|||
	delete m_udpBufferMono;
 | 
			
		||||
	delete[] m_udpAudioBuf;
 | 
			
		||||
	if (UDPFilter) delete UDPFilter;
 | 
			
		||||
	if (m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo);
 | 
			
		||||
	if (m_running.m_audioActive) DSPEngine::instance()->removeAudioSink(&m_audioFifo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** what needs the "apply" button validation */
 | 
			
		||||
void UDPSrc::configure(MessageQueue* messageQueue,
 | 
			
		||||
		SampleFormat sampleFormat,
 | 
			
		||||
		Real outputSampleRate,
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +99,8 @@ void UDPSrc::configure(MessageQueue* messageQueue,
 | 
			
		|||
		int fmDeviation,
 | 
			
		||||
		QString& udpAddress,
 | 
			
		||||
		int udpPort,
 | 
			
		||||
		int audioPort)
 | 
			
		||||
		int audioPort,
 | 
			
		||||
		bool force)
 | 
			
		||||
{
 | 
			
		||||
	Message* cmd = MsgUDPSrcConfigure::create(sampleFormat,
 | 
			
		||||
			outputSampleRate,
 | 
			
		||||
| 
						 | 
				
			
			@ -119,17 +108,21 @@ void UDPSrc::configure(MessageQueue* messageQueue,
 | 
			
		|||
			fmDeviation,
 | 
			
		||||
			udpAddress,
 | 
			
		||||
			udpPort,
 | 
			
		||||
			audioPort);
 | 
			
		||||
			audioPort,
 | 
			
		||||
			force);
 | 
			
		||||
	messageQueue->push(cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** changes applied immediately */
 | 
			
		||||
void UDPSrc::configureImmediate(MessageQueue* messageQueue,
 | 
			
		||||
		bool audioActive,
 | 
			
		||||
		bool audioStereo,
 | 
			
		||||
		Real boost,
 | 
			
		||||
		int  volume,
 | 
			
		||||
		Real squelchDB,
 | 
			
		||||
		bool squelchEnabled)
 | 
			
		||||
		Real squelchGate,
 | 
			
		||||
		bool squelchEnabled,
 | 
			
		||||
		bool force)
 | 
			
		||||
{
 | 
			
		||||
	Message* cmd = MsgUDPSrcConfigureImmediate::create(
 | 
			
		||||
			audioActive,
 | 
			
		||||
| 
						 | 
				
			
			@ -137,7 +130,9 @@ void UDPSrc::configureImmediate(MessageQueue* messageQueue,
 | 
			
		|||
			boost,
 | 
			
		||||
			volume,
 | 
			
		||||
			squelchDB,
 | 
			
		||||
			squelchEnabled);
 | 
			
		||||
			squelchGate,
 | 
			
		||||
			squelchEnabled,
 | 
			
		||||
			force);
 | 
			
		||||
	messageQueue->push(cmd);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -171,11 +166,11 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
 | 
			
		|||
			Sample ss(ci.real(), ci.imag());
 | 
			
		||||
			m_sampleBuffer.push_back(ss);
 | 
			
		||||
 | 
			
		||||
			m_sampleDistanceRemain += m_inputSampleRate / m_outputSampleRate;
 | 
			
		||||
			m_sampleDistanceRemain += m_running.m_inputSampleRate / m_running.m_outputSampleRate;
 | 
			
		||||
 | 
			
		||||
			calculateSquelch(m_inMagsq);
 | 
			
		||||
 | 
			
		||||
			if (m_sampleFormat == FormatLSB) // binaural LSB
 | 
			
		||||
			if (m_running.m_sampleFormat == FormatLSB) // binaural LSB
 | 
			
		||||
			{
 | 
			
		||||
				int n_out = UDPFilter->runSSB(ci, &sideband, false);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -183,14 +178,14 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
 | 
			
		|||
				{
 | 
			
		||||
					for (int i = 0; i < n_out; i++)
 | 
			
		||||
					{
 | 
			
		||||
						l = m_squelchOpen ? sideband[i].real() * m_gain : 0;
 | 
			
		||||
						r = m_squelchOpen ? sideband[i].imag() * m_gain : 0;
 | 
			
		||||
						l = m_squelchOpen ? sideband[i].real() * m_running.m_gain : 0;
 | 
			
		||||
						r = m_squelchOpen ? sideband[i].imag() * m_running.m_gain : 0;
 | 
			
		||||
					    m_udpBuffer->write(Sample(l, r));
 | 
			
		||||
					    m_outMovingAverage.feed((l*l + r*r) / (1<<30));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			if (m_sampleFormat == FormatUSB) // binaural USB
 | 
			
		||||
			if (m_running.m_sampleFormat == FormatUSB) // binaural USB
 | 
			
		||||
			{
 | 
			
		||||
				int n_out = UDPFilter->runSSB(ci, &sideband, true);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -198,26 +193,26 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
 | 
			
		|||
				{
 | 
			
		||||
					for (int i = 0; i < n_out; i++)
 | 
			
		||||
					{
 | 
			
		||||
						l = m_squelchOpen ? sideband[i].real() * m_gain : 0;
 | 
			
		||||
						r = m_squelchOpen ? sideband[i].imag() * m_gain : 0;
 | 
			
		||||
						l = m_squelchOpen ? sideband[i].real() * m_running.m_gain : 0;
 | 
			
		||||
						r = m_squelchOpen ? sideband[i].imag() * m_running.m_gain : 0;
 | 
			
		||||
						m_udpBuffer->write(Sample(l, r));
 | 
			
		||||
						m_outMovingAverage.feed((l*l + r*r) / (1<<30));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (m_sampleFormat == FormatNFM)
 | 
			
		||||
			else if (m_running.m_sampleFormat == FormatNFM)
 | 
			
		||||
			{
 | 
			
		||||
				double demod = m_squelchOpen ? 32768.0 * m_phaseDiscri.phaseDiscriminator(ci) * m_gain : 0;
 | 
			
		||||
				double demod = m_squelchOpen ? 32768.0 * m_phaseDiscri.phaseDiscriminator(ci) * m_running.m_gain : 0;
 | 
			
		||||
				m_udpBuffer->write(Sample(demod, demod));
 | 
			
		||||
				m_outMovingAverage.feed((demod * demod) / (1<<30));
 | 
			
		||||
			}
 | 
			
		||||
			else if (m_sampleFormat == FormatNFMMono)
 | 
			
		||||
			else if (m_running.m_sampleFormat == FormatNFMMono)
 | 
			
		||||
			{
 | 
			
		||||
				FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_gain) : 0;
 | 
			
		||||
				FixReal demod = m_squelchOpen ? (FixReal) (32768.0f * m_phaseDiscri.phaseDiscriminator(ci) * m_running.m_gain) : 0;
 | 
			
		||||
				m_udpBufferMono->write(demod);
 | 
			
		||||
				m_outMovingAverage.feed((demod * demod) / 1073741824.0);
 | 
			
		||||
			}
 | 
			
		||||
			else if (m_sampleFormat == FormatLSBMono) // Monaural LSB
 | 
			
		||||
			else if (m_running.m_sampleFormat == FormatLSBMono) // Monaural LSB
 | 
			
		||||
			{
 | 
			
		||||
				int n_out = UDPFilter->runSSB(ci, &sideband, false);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -225,13 +220,13 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
 | 
			
		|||
				{
 | 
			
		||||
					for (int i = 0; i < n_out; i++)
 | 
			
		||||
					{
 | 
			
		||||
						l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0;
 | 
			
		||||
						l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_running.m_gain : 0;
 | 
			
		||||
						m_udpBufferMono->write(l);
 | 
			
		||||
						m_outMovingAverage.feed((l * l) / (1<<30));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (m_sampleFormat == FormatUSBMono) // Monaural USB
 | 
			
		||||
			else if (m_running.m_sampleFormat == FormatUSBMono) // Monaural USB
 | 
			
		||||
			{
 | 
			
		||||
				int n_out = UDPFilter->runSSB(ci, &sideband, true);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -239,15 +234,15 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
 | 
			
		|||
				{
 | 
			
		||||
					for (int i = 0; i < n_out; i++)
 | 
			
		||||
					{
 | 
			
		||||
						l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_gain : 0;
 | 
			
		||||
						l = m_squelchOpen ? (sideband[i].real() + sideband[i].imag()) * 0.7 * m_running.m_gain : 0;
 | 
			
		||||
						m_udpBufferMono->write(l);
 | 
			
		||||
						m_outMovingAverage.feed((l * l) / (1<<30));
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
			else if (m_sampleFormat == FormatAMMono)
 | 
			
		||||
			else if (m_running.m_sampleFormat == FormatAMMono)
 | 
			
		||||
			{
 | 
			
		||||
				FixReal demod = m_squelchOpen ? (FixReal) (sqrt(inMagSq) * m_gain) : 0;
 | 
			
		||||
				FixReal demod = m_squelchOpen ? (FixReal) (sqrt(inMagSq) * m_running.m_gain) : 0;
 | 
			
		||||
				m_udpBufferMono->write(demod);
 | 
			
		||||
				m_outMovingAverage.feed((demod * demod) / (1<<30));
 | 
			
		||||
			}
 | 
			
		||||
| 
						 | 
				
			
			@ -255,9 +250,9 @@ void UDPSrc::feed(const SampleVector::const_iterator& begin, const SampleVector:
 | 
			
		|||
			{
 | 
			
		||||
			    if (m_squelchOpen)
 | 
			
		||||
			    {
 | 
			
		||||
	                Sample s(ci.real() * m_gain, ci.imag() * m_gain);
 | 
			
		||||
	                Sample s(ci.real() * m_running.m_gain, ci.imag() * m_running.m_gain);
 | 
			
		||||
	                m_udpBuffer->write(s);
 | 
			
		||||
	                m_outMovingAverage.feed((inMagSq*m_gain*m_gain) / (1<<30));
 | 
			
		||||
	                m_outMovingAverage.feed((inMagSq*m_running.m_gain*m_running.m_gain) / (1<<30));
 | 
			
		||||
			    }
 | 
			
		||||
			    else
 | 
			
		||||
			    {
 | 
			
		||||
| 
						 | 
				
			
			@ -298,68 +293,38 @@ bool UDPSrc::handleMessage(const Message& cmd)
 | 
			
		|||
	{
 | 
			
		||||
		DownChannelizer::MsgChannelizerNotification& notif = (DownChannelizer::MsgChannelizerNotification&) cmd;
 | 
			
		||||
 | 
			
		||||
		m_settingsMutex.lock();
 | 
			
		||||
		m_config.m_inputSampleRate = notif.getSampleRate();
 | 
			
		||||
		m_config.m_inputFrequencyOffset = notif.getFrequencyOffset();
 | 
			
		||||
 | 
			
		||||
		m_inputSampleRate = notif.getSampleRate();
 | 
			
		||||
		m_nco.setFreq(-notif.getFrequencyOffset(), m_inputSampleRate);
 | 
			
		||||
		m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
 | 
			
		||||
		m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
 | 
			
		||||
		apply(false);
 | 
			
		||||
 | 
			
		||||
		m_settingsMutex.unlock();
 | 
			
		||||
		qDebug() << "UDPSrc::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_config.m_inputSampleRate
 | 
			
		||||
                 << " frequencyOffset: " << notif.getFrequencyOffset();
 | 
			
		||||
 | 
			
		||||
		qDebug() << "UDPSrc::handleMessage: MsgChannelizerNotification: m_inputSampleRate: " << m_inputSampleRate
 | 
			
		||||
				<< " frequencyOffset: " << notif.getFrequencyOffset();
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
        return true;
 | 
			
		||||
	}
 | 
			
		||||
	else if (MsgUDPSrcConfigureImmediate::match(cmd))
 | 
			
		||||
	{
 | 
			
		||||
		MsgUDPSrcConfigureImmediate& cfg = (MsgUDPSrcConfigureImmediate&) cmd;
 | 
			
		||||
 | 
			
		||||
		m_settingsMutex.lock();
 | 
			
		||||
		m_config.m_audioActive = cfg.getAudioActive();
 | 
			
		||||
		m_config.m_audioStereo = cfg.getAudioStereo();
 | 
			
		||||
		m_config.m_gain = cfg.getGain();
 | 
			
		||||
		m_config.m_volume = cfg.getVolume();
 | 
			
		||||
		m_config.m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB());
 | 
			
		||||
		m_config.m_squelchGate = cfg.getSquelchGate();
 | 
			
		||||
		m_config.m_squelchEnabled = cfg.getSquelchEnabled();
 | 
			
		||||
 | 
			
		||||
		if (cfg.getAudioActive() != m_audioActive)
 | 
			
		||||
		{
 | 
			
		||||
			m_audioActive = cfg.getAudioActive();
 | 
			
		||||
 | 
			
		||||
			if (m_audioActive)
 | 
			
		||||
			{
 | 
			
		||||
				m_audioBufferFill = 0;
 | 
			
		||||
				DSPEngine::instance()->addAudioSink(&m_audioFifo);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				DSPEngine::instance()->removeAudioSink(&m_audioFifo);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cfg.getAudioStereo() != m_audioStereo)
 | 
			
		||||
		{
 | 
			
		||||
			m_audioStereo = cfg.getAudioStereo();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cfg.getGain() != m_gain)
 | 
			
		||||
		{
 | 
			
		||||
		    m_gain = cfg.getGain();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cfg.getVolume() != m_volume)
 | 
			
		||||
		{
 | 
			
		||||
			m_volume = cfg.getVolume();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_squelch = CalcDb::powerFromdB(cfg.getSquelchDB());
 | 
			
		||||
		m_squelchEnabled = cfg.getSquelchEnabled();
 | 
			
		||||
 | 
			
		||||
		m_settingsMutex.unlock();
 | 
			
		||||
		apply(cfg.getForce());
 | 
			
		||||
 | 
			
		||||
		qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigureImmediate: "
 | 
			
		||||
				<< " m_audioActive: " << m_audioActive
 | 
			
		||||
				<< " m_audioStereo: " << m_audioStereo
 | 
			
		||||
				<< " m_gain: " << m_gain
 | 
			
		||||
				<< " m_squelchEnabled: " << m_squelchEnabled
 | 
			
		||||
                << " m_squelch: " << m_squelch
 | 
			
		||||
                << " getSquelchDB: " << cfg.getSquelchDB();
 | 
			
		||||
				<< " m_audioActive: " << m_config.m_audioActive
 | 
			
		||||
				<< " m_audioStereo: " << m_config.m_audioStereo
 | 
			
		||||
				<< " m_gain: " << m_config.m_gain
 | 
			
		||||
				<< " m_squelchEnabled: " << m_config.m_squelchEnabled
 | 
			
		||||
                << " m_squelch: " << m_config.m_squelch
 | 
			
		||||
                << " getSquelchDB: " << cfg.getSquelchDB()
 | 
			
		||||
                << " m_squelchGate" << m_config.m_squelchGate;
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -368,67 +333,22 @@ bool UDPSrc::handleMessage(const Message& cmd)
 | 
			
		|||
	{
 | 
			
		||||
		MsgUDPSrcConfigure& cfg = (MsgUDPSrcConfigure&) cmd;
 | 
			
		||||
 | 
			
		||||
		m_settingsMutex.lock();
 | 
			
		||||
		m_config.m_sampleFormat = cfg.getSampleFormat();
 | 
			
		||||
		m_config.m_outputSampleRate = cfg.getOutputSampleRate();
 | 
			
		||||
		m_config.m_rfBandwidth = cfg.getRFBandwidth();
 | 
			
		||||
		m_config.m_udpAddressStr = cfg.getUDPAddress();
 | 
			
		||||
		m_config.m_udpPort = cfg.getUDPPort();
 | 
			
		||||
		m_config.m_audioPort = cfg.getAudioPort();
 | 
			
		||||
		m_config.m_fmDeviation = cfg.getFMDeviation();
 | 
			
		||||
 | 
			
		||||
		m_sampleFormat = cfg.getSampleFormat();
 | 
			
		||||
		m_outputSampleRate = cfg.getOutputSampleRate();
 | 
			
		||||
		m_rfBandwidth = cfg.getRFBandwidth();
 | 
			
		||||
		apply(cfg.getForce());
 | 
			
		||||
 | 
			
		||||
		if (cfg.getUDPAddress() != m_udpAddressStr)
 | 
			
		||||
		{
 | 
			
		||||
			m_udpAddressStr = cfg.getUDPAddress();
 | 
			
		||||
			m_udpBuffer->setAddress(m_udpAddressStr);
 | 
			
		||||
			m_udpBufferMono->setAddress(m_udpAddressStr);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cfg.getUDPPort() != m_udpPort)
 | 
			
		||||
		{
 | 
			
		||||
			m_udpPort = cfg.getUDPPort();
 | 
			
		||||
			m_udpBuffer->setPort(m_udpPort);
 | 
			
		||||
			m_udpBufferMono->setPort(m_udpPort);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cfg.getAudioPort() != m_audioPort)
 | 
			
		||||
		{
 | 
			
		||||
			m_audioPort = cfg.getAudioPort();
 | 
			
		||||
 | 
			
		||||
			disconnect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()));
 | 
			
		||||
			delete m_audioSocket;
 | 
			
		||||
			m_audioSocket = new QUdpSocket(this);
 | 
			
		||||
 | 
			
		||||
			if (m_audioSocket->bind(QHostAddress::LocalHost, m_audioPort))
 | 
			
		||||
			{
 | 
			
		||||
				connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection);
 | 
			
		||||
				qDebug("UDPSrc::handleMessage: audio socket bound to port %d", m_audioPort);
 | 
			
		||||
			}
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				qWarning("UDPSrc::handleMessage: cannot bind audio socket");
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if (cfg.getFMDeviation() != m_fmDeviation)
 | 
			
		||||
		{
 | 
			
		||||
			m_fmDeviation = cfg.getFMDeviation();
 | 
			
		||||
			m_phaseDiscri.setFMScaling((float) m_outputSampleRate / (2.0f * m_fmDeviation));
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		m_interpolator.create(16, m_inputSampleRate, m_rfBandwidth / 2.0);
 | 
			
		||||
		m_sampleDistanceRemain = m_inputSampleRate / m_outputSampleRate;
 | 
			
		||||
		UDPFilter->create_filter(0.0, (m_rfBandwidth / 2.0) / m_outputSampleRate);
 | 
			
		||||
 | 
			
		||||
        m_inMovingAverage.resize(m_outputSampleRate * 0.01, 1e-10);   // 10 ms
 | 
			
		||||
        m_outMovingAverage.resize(m_outputSampleRate * 0.01, 1e-10); // 10 ms
 | 
			
		||||
        m_squelchThreshold = m_outputSampleRate * 0.05; // 50 ms
 | 
			
		||||
 | 
			
		||||
		m_settingsMutex.unlock();
 | 
			
		||||
 | 
			
		||||
		qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigure: m_sampleFormat: " << m_sampleFormat
 | 
			
		||||
				<< " m_outputSampleRate: " << m_outputSampleRate
 | 
			
		||||
				<< " m_rfBandwidth: " << m_rfBandwidth
 | 
			
		||||
				<< " m_udpAddressStr: " << m_udpAddressStr
 | 
			
		||||
				<< " m_udpPort: " << m_udpPort
 | 
			
		||||
				<< " m_audioPort: " << m_audioPort;
 | 
			
		||||
		qDebug() << "UDPSrc::handleMessage: MsgUDPSrcConfigure: m_sampleFormat: " << m_config.m_sampleFormat
 | 
			
		||||
				<< " m_outputSampleRate: " << m_config.m_outputSampleRate
 | 
			
		||||
				<< " m_rfBandwidth: " << m_config.m_rfBandwidth
 | 
			
		||||
				<< " m_udpAddressStr: " << m_config.m_udpAddressStr
 | 
			
		||||
				<< " m_udpPort: " << m_config.m_udpPort
 | 
			
		||||
				<< " m_audioPort: " << m_config.m_audioPort;
 | 
			
		||||
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -455,6 +375,83 @@ bool UDPSrc::handleMessage(const Message& cmd)
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UDPSrc::apply(bool force)
 | 
			
		||||
{
 | 
			
		||||
    m_settingsMutex.lock();
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_inputSampleRate != m_running.m_inputSampleRate) ||
 | 
			
		||||
        (m_config.m_inputFrequencyOffset != m_running.m_inputFrequencyOffset) ||
 | 
			
		||||
        (m_config.m_rfBandwidth != m_running.m_rfBandwidth) ||
 | 
			
		||||
        (m_config.m_outputSampleRate != m_running.m_outputSampleRate) || force)
 | 
			
		||||
    {
 | 
			
		||||
        m_nco.setFreq(-m_config.m_inputFrequencyOffset, m_config.m_inputSampleRate);
 | 
			
		||||
        m_interpolator.create(16, m_config.m_inputSampleRate, m_config.m_rfBandwidth / 2.0);
 | 
			
		||||
        m_sampleDistanceRemain = m_config.m_inputSampleRate / m_config.m_outputSampleRate;
 | 
			
		||||
 | 
			
		||||
        m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate;
 | 
			
		||||
        initSquelch(m_squelchOpen);
 | 
			
		||||
 | 
			
		||||
        m_inMovingAverage.resize(m_config.m_outputSampleRate * 0.01, 1e-10);  // 10 ms
 | 
			
		||||
        m_outMovingAverage.resize(m_config.m_outputSampleRate * 0.01, 1e-10); // 10 ms
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_audioActive != m_config.m_audioActive) || force)
 | 
			
		||||
    {
 | 
			
		||||
        if (m_config.m_audioActive)
 | 
			
		||||
        {
 | 
			
		||||
            m_audioBufferFill = 0;
 | 
			
		||||
            DSPEngine::instance()->addAudioSink(&m_audioFifo);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            DSPEngine::instance()->removeAudioSink(&m_audioFifo);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_squelchGate != m_running.m_squelchGate) || force)
 | 
			
		||||
    {
 | 
			
		||||
        m_squelchThreshold = m_config.m_outputSampleRate * m_config.m_squelchGate;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_udpAddressStr != m_running.m_udpAddressStr) || force)
 | 
			
		||||
    {
 | 
			
		||||
        m_udpBuffer->setAddress(m_config.m_udpAddressStr);
 | 
			
		||||
        m_udpBufferMono->setAddress(m_config.m_udpAddressStr);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_udpPort != m_running.m_udpPort) || force)
 | 
			
		||||
    {
 | 
			
		||||
        m_udpBuffer->setPort(m_config.m_udpPort);
 | 
			
		||||
        m_udpBufferMono->setPort(m_config.m_udpPort);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_audioPort != m_running.m_audioPort) || force)
 | 
			
		||||
    {
 | 
			
		||||
        disconnect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()));
 | 
			
		||||
        delete m_audioSocket;
 | 
			
		||||
        m_audioSocket = new QUdpSocket(this);
 | 
			
		||||
 | 
			
		||||
        if (m_audioSocket->bind(QHostAddress::LocalHost, m_config.m_audioPort))
 | 
			
		||||
        {
 | 
			
		||||
            connect(m_audioSocket, SIGNAL(readyRead()), this, SLOT(audioReadyRead()), Qt::QueuedConnection);
 | 
			
		||||
            qDebug("UDPSrc::handleMessage: audio socket bound to port %d", m_config.m_audioPort);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            qWarning("UDPSrc::handleMessage: cannot bind audio socket");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if ((m_config.m_fmDeviation != m_running.m_fmDeviation) || force)
 | 
			
		||||
    {
 | 
			
		||||
        m_phaseDiscri.setFMScaling((float) m_config.m_outputSampleRate / (2.0f * m_config.m_fmDeviation));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    m_settingsMutex.unlock();
 | 
			
		||||
 | 
			
		||||
    m_running = m_config;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UDPSrc::audioReadyRead()
 | 
			
		||||
{
 | 
			
		||||
	while (m_audioSocket->hasPendingDatagrams())
 | 
			
		||||
| 
						 | 
				
			
			@ -463,16 +460,16 @@ void UDPSrc::audioReadyRead()
 | 
			
		|||
	    qint64 udpReadBytes = m_audioSocket->readDatagram(m_udpAudioBuf, pendingDataSize, 0, 0);
 | 
			
		||||
		//qDebug("UDPSrc::audioReadyRead: %lld", udpReadBytes);
 | 
			
		||||
 | 
			
		||||
		if (m_audioActive)
 | 
			
		||||
		if (m_running.m_audioActive)
 | 
			
		||||
		{
 | 
			
		||||
			if (m_audioStereo)
 | 
			
		||||
			if (m_running.m_audioStereo)
 | 
			
		||||
			{
 | 
			
		||||
				for (int i = 0; i < udpReadBytes - 3; i += 4)
 | 
			
		||||
				{
 | 
			
		||||
					qint16 l_sample = (qint16) *(&m_udpAudioBuf[i]);
 | 
			
		||||
					qint16 r_sample = (qint16) *(&m_udpAudioBuf[i+2]);
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].l  = l_sample * m_volume;
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].r  = r_sample * m_volume;
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].l  = l_sample * m_running.m_volume;
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].r  = r_sample * m_running.m_volume;
 | 
			
		||||
					++m_audioBufferFill;
 | 
			
		||||
 | 
			
		||||
					if (m_audioBufferFill >= m_audioBuffer.size())
 | 
			
		||||
| 
						 | 
				
			
			@ -493,8 +490,8 @@ void UDPSrc::audioReadyRead()
 | 
			
		|||
				for (int i = 0; i < udpReadBytes - 1; i += 2)
 | 
			
		||||
				{
 | 
			
		||||
					qint16 sample = (qint16) *(&m_udpAudioBuf[i]);
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].l  = sample * m_volume;
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].r  = sample * m_volume;
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].l  = sample * m_running.m_volume;
 | 
			
		||||
					m_audioBuffer[m_audioBufferFill].r  = sample * m_running.m_volume;
 | 
			
		||||
					++m_audioBufferFill;
 | 
			
		||||
 | 
			
		||||
					if (m_audioBufferFill >= m_audioBuffer.size())
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,14 +67,17 @@ public:
 | 
			
		|||
			int fmDeviation,
 | 
			
		||||
			QString& udpAddress,
 | 
			
		||||
			int udpPort,
 | 
			
		||||
			int audioPort);
 | 
			
		||||
			int audioPort,
 | 
			
		||||
			bool force);
 | 
			
		||||
	void configureImmediate(MessageQueue* messageQueue,
 | 
			
		||||
			bool audioActive,
 | 
			
		||||
			bool audioStereo,
 | 
			
		||||
			Real gain,
 | 
			
		||||
			int volume,
 | 
			
		||||
			Real squelchDB,
 | 
			
		||||
			bool squelchEnabled);
 | 
			
		||||
			Real squelchGate,
 | 
			
		||||
			bool squelchEnabled,
 | 
			
		||||
			bool force);
 | 
			
		||||
	void setSpectrum(MessageQueue* messageQueue, bool enabled);
 | 
			
		||||
	double getMagSq() const { return m_magsq; }
 | 
			
		||||
	double getInMagSq() const { return m_inMagsq; }
 | 
			
		||||
| 
						 | 
				
			
			@ -102,6 +105,7 @@ protected:
 | 
			
		|||
		const QString& getUDPAddress() const { return m_udpAddress; }
 | 
			
		||||
		int getUDPPort() const { return m_udpPort; }
 | 
			
		||||
		int getAudioPort() const { return m_audioPort; }
 | 
			
		||||
		bool getForce() const { return m_force; }
 | 
			
		||||
 | 
			
		||||
		static MsgUDPSrcConfigure* create(SampleFormat
 | 
			
		||||
				sampleFormat,
 | 
			
		||||
| 
						 | 
				
			
			@ -110,7 +114,8 @@ protected:
 | 
			
		|||
				int fmDeviation,
 | 
			
		||||
				QString& udpAddress,
 | 
			
		||||
				int udpPort,
 | 
			
		||||
				int audioPort)
 | 
			
		||||
				int audioPort,
 | 
			
		||||
				bool force)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgUDPSrcConfigure(sampleFormat,
 | 
			
		||||
					sampleRate,
 | 
			
		||||
| 
						 | 
				
			
			@ -118,7 +123,8 @@ protected:
 | 
			
		|||
					fmDeviation,
 | 
			
		||||
					udpAddress,
 | 
			
		||||
					udpPort,
 | 
			
		||||
					audioPort);
 | 
			
		||||
					audioPort,
 | 
			
		||||
					force);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +135,7 @@ protected:
 | 
			
		|||
		QString m_udpAddress;
 | 
			
		||||
		int m_udpPort;
 | 
			
		||||
		int m_audioPort;
 | 
			
		||||
		bool m_force;
 | 
			
		||||
 | 
			
		||||
		MsgUDPSrcConfigure(SampleFormat sampleFormat,
 | 
			
		||||
				Real outputSampleRate,
 | 
			
		||||
| 
						 | 
				
			
			@ -136,7 +143,8 @@ protected:
 | 
			
		|||
				int fmDeviation,
 | 
			
		||||
				QString& udpAddress,
 | 
			
		||||
				int udpPort,
 | 
			
		||||
				int audioPort) :
 | 
			
		||||
				int audioPort,
 | 
			
		||||
				bool force) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_sampleFormat(sampleFormat),
 | 
			
		||||
			m_outputSampleRate(outputSampleRate),
 | 
			
		||||
| 
						 | 
				
			
			@ -144,7 +152,8 @@ protected:
 | 
			
		|||
			m_fmDeviation(fmDeviation),
 | 
			
		||||
			m_udpAddress(udpAddress),
 | 
			
		||||
			m_udpPort(udpPort),
 | 
			
		||||
			m_audioPort(audioPort)
 | 
			
		||||
			m_audioPort(audioPort),
 | 
			
		||||
			m_force(force)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +166,9 @@ protected:
 | 
			
		|||
		bool getAudioActive() const { return m_audioActive; }
 | 
			
		||||
		bool getAudioStereo() const { return m_audioStereo; }
 | 
			
		||||
		Real getSquelchDB() const { return m_squelchDB; }
 | 
			
		||||
		Real getSquelchGate() const { return m_squelchGate; }
 | 
			
		||||
		bool getSquelchEnabled() const { return m_squelchEnabled; }
 | 
			
		||||
		bool getForce() const { return m_force; }
 | 
			
		||||
 | 
			
		||||
		static MsgUDPSrcConfigureImmediate* create(
 | 
			
		||||
				bool audioActive,
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +176,9 @@ protected:
 | 
			
		|||
				int gain,
 | 
			
		||||
				int volume,
 | 
			
		||||
				Real squelchDB,
 | 
			
		||||
				bool squelchEnabled)
 | 
			
		||||
				Real squelchGate,
 | 
			
		||||
				bool squelchEnabled,
 | 
			
		||||
				bool force)
 | 
			
		||||
		{
 | 
			
		||||
			return new MsgUDPSrcConfigureImmediate(
 | 
			
		||||
					audioActive,
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +186,9 @@ protected:
 | 
			
		|||
					gain,
 | 
			
		||||
					volume,
 | 
			
		||||
					squelchDB,
 | 
			
		||||
					squelchEnabled);
 | 
			
		||||
					squelchGate,
 | 
			
		||||
					squelchEnabled,
 | 
			
		||||
					force);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
	private:
 | 
			
		||||
| 
						 | 
				
			
			@ -182,7 +197,9 @@ protected:
 | 
			
		|||
		bool m_audioActive;
 | 
			
		||||
		bool m_audioStereo;
 | 
			
		||||
		Real m_squelchDB;
 | 
			
		||||
        Real m_squelchGate; // seconds
 | 
			
		||||
		bool m_squelchEnabled;
 | 
			
		||||
		bool m_force;
 | 
			
		||||
 | 
			
		||||
		MsgUDPSrcConfigureImmediate(
 | 
			
		||||
				bool audioActive,
 | 
			
		||||
| 
						 | 
				
			
			@ -190,14 +207,18 @@ protected:
 | 
			
		|||
				Real gain,
 | 
			
		||||
				int volume,
 | 
			
		||||
                Real squelchDB,
 | 
			
		||||
                bool squelchEnabled) :
 | 
			
		||||
                Real squelchGate,
 | 
			
		||||
                bool squelchEnabled,
 | 
			
		||||
                bool force) :
 | 
			
		||||
			Message(),
 | 
			
		||||
			m_gain(gain),
 | 
			
		||||
            m_volume(volume),
 | 
			
		||||
			m_audioActive(audioActive),
 | 
			
		||||
			m_audioStereo(audioStereo),
 | 
			
		||||
			m_squelchDB(squelchDB),
 | 
			
		||||
			m_squelchEnabled(squelchEnabled)
 | 
			
		||||
            m_squelchGate(squelchGate),
 | 
			
		||||
			m_squelchEnabled(squelchEnabled),
 | 
			
		||||
			m_force(force)
 | 
			
		||||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -221,23 +242,54 @@ protected:
 | 
			
		|||
		{ }
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
    struct Config {
 | 
			
		||||
        Real m_outputSampleRate;
 | 
			
		||||
        SampleFormat m_sampleFormat;
 | 
			
		||||
        Real m_inputSampleRate;
 | 
			
		||||
        qint64 m_inputFrequencyOffset;
 | 
			
		||||
        Real m_rfBandwidth;
 | 
			
		||||
        int m_fmDeviation;
 | 
			
		||||
        bool m_channelMute;
 | 
			
		||||
        Real m_gain;
 | 
			
		||||
        Real m_squelch; //!< squared magnitude
 | 
			
		||||
        Real m_squelchGate; //!< seconds
 | 
			
		||||
        bool m_squelchEnabled;
 | 
			
		||||
        bool m_audioActive;
 | 
			
		||||
        bool m_audioStereo;
 | 
			
		||||
        int m_volume;
 | 
			
		||||
 | 
			
		||||
        QString m_udpAddressStr;
 | 
			
		||||
        quint16 m_udpPort;
 | 
			
		||||
        quint16 m_audioPort;
 | 
			
		||||
 | 
			
		||||
        Config() :
 | 
			
		||||
            m_outputSampleRate(48000),
 | 
			
		||||
            m_sampleFormat(FormatS16LE),
 | 
			
		||||
            m_inputSampleRate(48000),
 | 
			
		||||
            m_inputFrequencyOffset(0),
 | 
			
		||||
            m_rfBandwidth(12500),
 | 
			
		||||
            m_fmDeviation(2500),
 | 
			
		||||
            m_channelMute(false),
 | 
			
		||||
            m_gain(1.0),
 | 
			
		||||
            m_squelch(1e-6),
 | 
			
		||||
            m_squelchGate(0.0),
 | 
			
		||||
            m_squelchEnabled(true),
 | 
			
		||||
            m_audioActive(false),
 | 
			
		||||
            m_audioStereo(false),
 | 
			
		||||
            m_volume(20),
 | 
			
		||||
            m_udpAddressStr("127.0.0.1"),
 | 
			
		||||
            m_udpPort(9999),
 | 
			
		||||
            m_audioPort(9998)
 | 
			
		||||
        {}
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Config m_config;
 | 
			
		||||
    Config m_running;
 | 
			
		||||
 | 
			
		||||
	MessageQueue* m_uiMessageQueue;
 | 
			
		||||
	UDPSrcGUI* m_udpSrcGUI;
 | 
			
		||||
	QUdpSocket *m_audioSocket;
 | 
			
		||||
 | 
			
		||||
	int m_inputSampleRate;
 | 
			
		||||
 | 
			
		||||
	int m_sampleFormat;
 | 
			
		||||
	Real m_outputSampleRate;
 | 
			
		||||
	Real m_rfBandwidth;
 | 
			
		||||
	QString m_udpAddressStr;
 | 
			
		||||
	quint16 m_udpPort;
 | 
			
		||||
	quint16 m_audioPort;
 | 
			
		||||
	Real m_gain;
 | 
			
		||||
	bool m_audioActive;
 | 
			
		||||
	bool m_audioStereo;
 | 
			
		||||
	int m_volume;
 | 
			
		||||
	int m_fmDeviation;
 | 
			
		||||
	double m_magsq;
 | 
			
		||||
    double m_inMagsq;
 | 
			
		||||
    MovingAverage<double> m_outMovingAverage;
 | 
			
		||||
| 
						 | 
				
			
			@ -270,34 +322,54 @@ protected:
 | 
			
		|||
 | 
			
		||||
    PhaseDiscriminators m_phaseDiscri;
 | 
			
		||||
 | 
			
		||||
    Real m_squelch; //!< squared magnitude
 | 
			
		||||
    bool m_squelchEnabled;
 | 
			
		||||
    bool m_squelchOpen;
 | 
			
		||||
    int  m_squelchOpenCount;
 | 
			
		||||
    int  m_squelchCloseCount;
 | 
			
		||||
    int m_squelchThreshold;
 | 
			
		||||
    int m_squelchThreshold; //!< number of samples computed from given gate
 | 
			
		||||
 | 
			
		||||
	QMutex m_settingsMutex;
 | 
			
		||||
 | 
			
		||||
	void apply(bool force);
 | 
			
		||||
 | 
			
		||||
    inline void calculateSquelch(double value)
 | 
			
		||||
    {
 | 
			
		||||
        if ((!m_squelchEnabled) || (value > m_squelch))
 | 
			
		||||
        if ((!m_running.m_squelchEnabled) || (value > m_running.m_squelch))
 | 
			
		||||
        {
 | 
			
		||||
            if (m_squelchOpenCount < m_squelchThreshold) {
 | 
			
		||||
                m_squelchOpenCount++;
 | 
			
		||||
            } else {
 | 
			
		||||
                m_squelchCloseCount = m_squelchThreshold;
 | 
			
		||||
            if (m_squelchThreshold == 0)
 | 
			
		||||
            {
 | 
			
		||||
                m_squelchOpen = true;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (m_squelchOpenCount < m_squelchThreshold)
 | 
			
		||||
                {
 | 
			
		||||
                    m_squelchOpenCount++;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    m_squelchCloseCount = m_squelchThreshold;
 | 
			
		||||
                    m_squelchOpen = true;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
            if (m_squelchCloseCount > 0) {
 | 
			
		||||
                m_squelchCloseCount--;
 | 
			
		||||
            } else {
 | 
			
		||||
                m_squelchOpenCount = 0;
 | 
			
		||||
            if (m_squelchThreshold == 0)
 | 
			
		||||
            {
 | 
			
		||||
                m_squelchOpen = false;
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
            {
 | 
			
		||||
                if (m_squelchCloseCount > 0)
 | 
			
		||||
                {
 | 
			
		||||
                    m_squelchCloseCount--;
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    m_squelchOpenCount = 0;
 | 
			
		||||
                    m_squelchOpen = false;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -197,8 +197,8 @@ bool UDPSrcGUI::deserialize(const QByteArray& data)
 | 
			
		|||
		blockApplySettings(false);
 | 
			
		||||
		m_channelMarker.blockSignals(false);
 | 
			
		||||
 | 
			
		||||
		applySettingsImmediate();
 | 
			
		||||
		applySettings();
 | 
			
		||||
		applySettingsImmediate(true);
 | 
			
		||||
		applySettings(true);
 | 
			
		||||
		return true;
 | 
			
		||||
	}
 | 
			
		||||
	else
 | 
			
		||||
| 
						 | 
				
			
			@ -297,8 +297,8 @@ UDPSrcGUI::UDPSrcGUI(PluginAPI* pluginAPI, DeviceSourceAPI *deviceAPI, QWidget*
 | 
			
		|||
	ui->spectrumGUI->setBuddies(m_spectrumVis->getInputMessageQueue(), m_spectrumVis, ui->glSpectrum);
 | 
			
		||||
 | 
			
		||||
	displaySettings();
 | 
			
		||||
	applySettingsImmediate();
 | 
			
		||||
	applySettings();
 | 
			
		||||
	applySettingsImmediate(true);
 | 
			
		||||
	applySettings(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
UDPSrcGUI::~UDPSrcGUI()
 | 
			
		||||
| 
						 | 
				
			
			@ -323,9 +323,10 @@ void UDPSrcGUI::displaySettings()
 | 
			
		|||
    ui->gainText->setText(tr("%1").arg(ui->gain->value()/10.0, 0, 'f', 1));
 | 
			
		||||
    ui->volumeText->setText(QString("%1").arg(ui->volume->value()));
 | 
			
		||||
    ui->squelchText->setText(tr("%1").arg(ui->squelch->value()*1.0, 0, 'f', 0));
 | 
			
		||||
    ui->squelchGateText->setText(tr("%1").arg(ui->squelchGate->value()*10.0, 0, 'f', 0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UDPSrcGUI::applySettingsImmediate()
 | 
			
		||||
void UDPSrcGUI::applySettingsImmediate(bool force)
 | 
			
		||||
{
 | 
			
		||||
	if (m_doApplySettings)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -340,12 +341,14 @@ void UDPSrcGUI::applySettingsImmediate()
 | 
			
		|||
		    m_gain,
 | 
			
		||||
			m_volume,
 | 
			
		||||
			ui->squelch->value() * 1.0f,
 | 
			
		||||
			ui->squelch->value() != -100);
 | 
			
		||||
			ui->squelchGate->value() * 0.01f,
 | 
			
		||||
			ui->squelch->value() != -100,
 | 
			
		||||
			force);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void UDPSrcGUI::applySettings()
 | 
			
		||||
void UDPSrcGUI::applySettings(bool force)
 | 
			
		||||
{
 | 
			
		||||
	if (m_doApplySettings)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -461,7 +464,8 @@ void UDPSrcGUI::applySettings()
 | 
			
		|||
			fmDeviation,
 | 
			
		||||
			m_udpAddress,
 | 
			
		||||
			udpPort,
 | 
			
		||||
			audioPort);
 | 
			
		||||
			audioPort,
 | 
			
		||||
			force);
 | 
			
		||||
 | 
			
		||||
		ui->applyBtn->setEnabled(false);
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			@ -554,6 +558,12 @@ void UDPSrcGUI::on_squelch_valueChanged(int value)
 | 
			
		|||
    applySettingsImmediate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UDPSrcGUI::on_squelchGate_valueChanged(int value)
 | 
			
		||||
{
 | 
			
		||||
    ui->squelchGateText->setText(tr("%1").arg(value*10.0, 0, 'f', 0));
 | 
			
		||||
    applySettingsImmediate();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void UDPSrcGUI::onWidgetRolled(QWidget* widget, bool rollDown)
 | 
			
		||||
{
 | 
			
		||||
	if ((widget == ui->spectrumBox) && (m_udpSrc != 0))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,6 +75,7 @@ private slots:
 | 
			
		|||
	void on_gain_valueChanged(int value);
 | 
			
		||||
	void on_volume_valueChanged(int value);
 | 
			
		||||
	void on_squelch_valueChanged(int value);
 | 
			
		||||
	void on_squelchGate_valueChanged(int value);
 | 
			
		||||
	void tick();
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
| 
						 | 
				
			
			@ -111,8 +112,8 @@ private:
 | 
			
		|||
	virtual ~UDPSrcGUI();
 | 
			
		||||
 | 
			
		||||
    void blockApplySettings(bool block);
 | 
			
		||||
	void applySettings();
 | 
			
		||||
	void applySettingsImmediate();
 | 
			
		||||
	void applySettings(bool force = false);
 | 
			
		||||
	void applySettingsImmediate(bool force = false);
 | 
			
		||||
	void displaySettings();
 | 
			
		||||
 | 
			
		||||
	void leaveEvent(QEvent*);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -236,6 +236,38 @@
 | 
			
		|||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <spacer name="horizontalSpacer_2">
 | 
			
		||||
        <property name="orientation">
 | 
			
		||||
         <enum>Qt::Horizontal</enum>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="sizeHint" stdset="0">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>40</width>
 | 
			
		||||
          <height>20</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
       </spacer>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="inputPower">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>40</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Input power (dB) to which squelch applies</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>-100.0</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
     </layout>
 | 
			
		||||
    </item>
 | 
			
		||||
    <item row="6" column="0">
 | 
			
		||||
| 
						 | 
				
			
			@ -637,18 +669,40 @@
 | 
			
		|||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="inputPower">
 | 
			
		||||
       <widget class="QDial" name="squelchGate">
 | 
			
		||||
        <property name="maximumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>22</width>
 | 
			
		||||
          <height>22</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Squelch gate (ms)</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="maximum">
 | 
			
		||||
         <number>50</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="pageStep">
 | 
			
		||||
         <number>1</number>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="value">
 | 
			
		||||
         <number>5</number>
 | 
			
		||||
        </property>
 | 
			
		||||
       </widget>
 | 
			
		||||
      </item>
 | 
			
		||||
      <item>
 | 
			
		||||
       <widget class="QLabel" name="squelchGateText">
 | 
			
		||||
        <property name="minimumSize">
 | 
			
		||||
         <size>
 | 
			
		||||
          <width>40</width>
 | 
			
		||||
          <width>24</width>
 | 
			
		||||
          <height>0</height>
 | 
			
		||||
         </size>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="toolTip">
 | 
			
		||||
         <string>Input power (dB) to which squelch applies</string>
 | 
			
		||||
         <string>Squelch gate (ms)</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="text">
 | 
			
		||||
         <string>-100.0</string>
 | 
			
		||||
         <string>000</string>
 | 
			
		||||
        </property>
 | 
			
		||||
        <property name="alignment">
 | 
			
		||||
         <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue