mirror of
https://github.com/f4exb/sdrangel.git
synced 2024-11-22 16:08:39 -05:00
Multiple audio support: extend audio output information to UDP/RTP information. New audio preferences dialog
This commit is contained in:
parent
bfce9a4fcc
commit
745e187e2b
@ -63,7 +63,7 @@ AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) :
|
|||||||
|
|
||||||
m_magsq = 0.0;
|
m_magsq = 0.0;
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
||||||
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ BFMDemod::BFMDemod(DeviceSourceAPI *deviceAPI) :
|
|||||||
m_audioBuffer.resize(16384);
|
m_audioBuffer.resize(16384);
|
||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
||||||
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
||||||
m_audioNetSink->setStereo(true);
|
m_audioNetSink->setStereo(true);
|
||||||
|
@ -72,8 +72,8 @@ DSDDemod::DSDDemod(DeviceSourceAPI *deviceAPI) :
|
|||||||
m_magsqPeak = 0.0f;
|
m_magsqPeak = 0.0f;
|
||||||
m_magsqCount = 0;
|
m_magsqCount = 0;
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo1);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo1, getInputMessageQueue());
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo2);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo2, getInputMessageQueue());
|
||||||
|
|
||||||
// m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_settings.m_udpPort);
|
// m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_settings.m_udpPort);
|
||||||
// m_audioFifo1.setUDPSink(m_udpBufferAudio);
|
// m_audioFifo1.setUDPSink(m_udpBufferAudio);
|
||||||
|
@ -80,7 +80,7 @@ NFMDemod::NFMDemod(DeviceSourceAPI *devieAPI) :
|
|||||||
m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution
|
m_ctcssDetector.setCoefficients(3000, 6000.0); // 0.5s / 2 Hz resolution
|
||||||
m_afSquelch.setCoefficients(24, 600, 48000.0, 200, 0); // 0.5ms test period, 300ms average span, 48kS/s SR, 100ms attack, no decay
|
m_afSquelch.setCoefficients(24, 600, 48000.0, 200, 0); // 0.5ms test period, 300ms average span, 48kS/s SR, 100ms attack, no decay
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
||||||
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
|
|||||||
SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen);
|
SSBFilter = new fftfilt(m_LowCutoff / m_audioSampleRate, m_Bandwidth / m_audioSampleRate, ssbFftLen);
|
||||||
DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * ssbFftLen);
|
DSBFilter = new fftfilt((2.0f * m_Bandwidth) / m_audioSampleRate, 2 * ssbFftLen);
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
||||||
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
||||||
|
|
||||||
|
@ -59,7 +59,7 @@ WFMDemod::WFMDemod(DeviceSourceAPI* deviceAPI) :
|
|||||||
m_audioBuffer.resize(16384);
|
m_audioBuffer.resize(16384);
|
||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
|
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
m_audioNetSink = new AudioNetSink(0); // parent thread allocated dynamically
|
||||||
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
m_audioNetSink->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
|
||||||
|
|
||||||
|
@ -543,7 +543,7 @@ void UDPSrc::applySettings(const UDPSrcSettings& settings, bool force)
|
|||||||
if (settings.m_audioActive)
|
if (settings.m_audioActive)
|
||||||
{
|
{
|
||||||
m_audioBufferFill = 0;
|
m_audioBufferFill = 0;
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -66,7 +66,7 @@ AMMod::AMMod(DeviceSinkAPI *deviceAPI) :
|
|||||||
m_magsq = 0.0;
|
m_magsq = 0.0;
|
||||||
|
|
||||||
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
|
||||||
|
|
||||||
// CW keyer
|
// CW keyer
|
||||||
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
||||||
|
@ -73,7 +73,7 @@ NFMMod::NFMMod(DeviceSinkAPI *deviceAPI) :
|
|||||||
|
|
||||||
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
||||||
m_ctcssNco.setFreq(88.5, m_settings.m_audioSampleRate);
|
m_ctcssNco.setFreq(88.5, m_settings.m_audioSampleRate);
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
|
||||||
|
|
||||||
// CW keyer
|
// CW keyer
|
||||||
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
||||||
|
@ -88,7 +88,7 @@ SSBMod::SSBMod(DeviceSinkAPI *deviceAPI) :
|
|||||||
m_magsq = 0.0;
|
m_magsq = 0.0;
|
||||||
|
|
||||||
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
|
||||||
|
|
||||||
// CW keyer
|
// CW keyer
|
||||||
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
|
||||||
|
@ -75,7 +75,7 @@ WFMMod::WFMMod(DeviceSinkAPI *deviceAPI) :
|
|||||||
|
|
||||||
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
|
||||||
m_toneNcoRF.setFreq(1000.0, m_outputSampleRate);
|
m_toneNcoRF.setFreq(1000.0, m_outputSampleRate);
|
||||||
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
|
DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
|
||||||
|
|
||||||
// CW keyer
|
// CW keyer
|
||||||
m_cwKeyer.setSampleRate(m_outputSampleRate);
|
m_cwKeyer.setSampleRate(m_outputSampleRate);
|
||||||
|
@ -18,9 +18,11 @@
|
|||||||
#include "audio/audiodevicemanager.h"
|
#include "audio/audiodevicemanager.h"
|
||||||
#include "util/simpleserializer.h"
|
#include "util/simpleserializer.h"
|
||||||
|
|
||||||
|
#include <QDataStream>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
|
||||||
const float AudioDeviceManager::m_defaultAudioInputVolume = 0.15f;
|
const float AudioDeviceManager::m_defaultAudioInputVolume = 0.15f;
|
||||||
|
const QString AudioDeviceManager::m_defaultUDPAddress = "127.0.0.1";
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info)
|
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info)
|
||||||
{
|
{
|
||||||
@ -34,6 +36,18 @@ QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::InputDeviceInfo& in
|
|||||||
return ds;
|
return ds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::OutputDeviceInfo& info)
|
||||||
|
{
|
||||||
|
ds << info.sampleRate << info.udpAddress << info.udpPort << info.copyToUDP << info.udpStereo << info.udpUseRTP;
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::OutputDeviceInfo& info)
|
||||||
|
{
|
||||||
|
ds >> info.sampleRate >> info.udpAddress >> info.udpPort >> info.copyToUDP >> info.udpStereo >> info.udpUseRTP;
|
||||||
|
return ds;
|
||||||
|
}
|
||||||
|
|
||||||
AudioDeviceManager::AudioDeviceManager()
|
AudioDeviceManager::AudioDeviceManager()
|
||||||
{
|
{
|
||||||
m_inputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
|
m_inputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
|
||||||
@ -122,7 +136,7 @@ void AudioDeviceManager::serializeInputMap(QByteArray& data) const
|
|||||||
void AudioDeviceManager::serializeOutputMap(QByteArray& data) const
|
void AudioDeviceManager::serializeOutputMap(QByteArray& data) const
|
||||||
{
|
{
|
||||||
QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
|
QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
|
||||||
*stream << m_audioOutputSampleRates;
|
*stream << m_audioOutputInfos;
|
||||||
delete stream;
|
delete stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,10 +181,10 @@ void AudioDeviceManager::deserializeInputMap(QByteArray& data)
|
|||||||
void AudioDeviceManager::deserializeOutputMap(QByteArray& data)
|
void AudioDeviceManager::deserializeOutputMap(QByteArray& data)
|
||||||
{
|
{
|
||||||
QDataStream readStream(&data, QIODevice::ReadOnly);
|
QDataStream readStream(&data, QIODevice::ReadOnly);
|
||||||
readStream >> m_audioOutputSampleRates;
|
readStream >> m_audioOutputInfos;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, int outputDeviceIndex)
|
void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex)
|
||||||
{
|
{
|
||||||
qDebug("AudioDeviceManager::addAudioSink: %d: %p", outputDeviceIndex, audioFifo);
|
qDebug("AudioDeviceManager::addAudioSink: %d: %p", outputDeviceIndex, audioFifo);
|
||||||
|
|
||||||
@ -198,6 +212,7 @@ void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, int outputDeviceInde
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO
|
m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO
|
||||||
|
m_sampleSinkMessageQueues[audioFifo] = sampleSinkMessageQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo)
|
void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo)
|
||||||
@ -218,9 +233,10 @@ void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO
|
m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO
|
||||||
|
m_sampleSinkMessageQueues.remove(audioFifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, int inputDeviceIndex)
|
void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex)
|
||||||
{
|
{
|
||||||
qDebug("AudioDeviceManager::addAudioSource: %d: %p", inputDeviceIndex, audioFifo);
|
qDebug("AudioDeviceManager::addAudioSource: %d: %p", inputDeviceIndex, audioFifo);
|
||||||
|
|
||||||
@ -248,6 +264,7 @@ void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, int inputDeviceInd
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_audioSourceFifos[audioFifo] = inputDeviceIndex; // register audio FIFO
|
m_audioSourceFifos[audioFifo] = inputDeviceIndex; // register audio FIFO
|
||||||
|
m_sampleSourceMessageQueues[audioFifo] = sampleSourceMessageQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
|
void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
|
||||||
@ -268,23 +285,47 @@ void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO
|
m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO
|
||||||
|
m_sampleSourceMessageQueues.remove(audioFifo);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioDeviceManager::startAudioOutput(int outputDeviceIndex)
|
void AudioDeviceManager::startAudioOutput(int outputDeviceIndex)
|
||||||
{
|
{
|
||||||
unsigned int sampleRate;
|
unsigned int sampleRate;
|
||||||
|
QString udpAddress;
|
||||||
|
quint16 udpPort;
|
||||||
|
bool copyAudioToUDP;
|
||||||
|
bool udpStereo;
|
||||||
|
bool udpUseRTP;
|
||||||
QString deviceName;
|
QString deviceName;
|
||||||
|
|
||||||
if (getOutputDeviceName(outputDeviceIndex, deviceName))
|
if (getOutputDeviceName(outputDeviceIndex, deviceName))
|
||||||
{
|
{
|
||||||
if (m_audioOutputSampleRates.find(deviceName) == m_audioOutputSampleRates.end()) {
|
if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end())
|
||||||
|
{
|
||||||
sampleRate = m_defaultAudioSampleRate;
|
sampleRate = m_defaultAudioSampleRate;
|
||||||
} else {
|
udpAddress = m_defaultUDPAddress;
|
||||||
sampleRate = m_audioOutputSampleRates[deviceName];
|
udpPort = m_defaultUDPPort;
|
||||||
|
copyAudioToUDP = false;
|
||||||
|
udpStereo = false;
|
||||||
|
udpUseRTP = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sampleRate = m_audioOutputInfos[deviceName].sampleRate;
|
||||||
|
udpAddress = m_audioOutputInfos[deviceName].udpAddress;
|
||||||
|
udpPort = m_audioOutputInfos[deviceName].udpPort;
|
||||||
|
copyAudioToUDP = m_audioOutputInfos[deviceName].copyToUDP;
|
||||||
|
udpStereo = m_audioOutputInfos[deviceName].udpStereo;
|
||||||
|
udpUseRTP = m_audioOutputInfos[deviceName].udpUseRTP;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_audioOutputs[outputDeviceIndex]->start(outputDeviceIndex, sampleRate);
|
m_audioOutputs[outputDeviceIndex]->start(outputDeviceIndex, sampleRate);
|
||||||
m_audioOutputSampleRates[deviceName] = m_audioOutputs[outputDeviceIndex]->getRate(); // update with actual rate
|
m_audioOutputInfos[deviceName].sampleRate = m_audioOutputs[outputDeviceIndex]->getRate(); // update with actual rate
|
||||||
|
m_audioOutputInfos[deviceName].udpAddress = udpAddress;
|
||||||
|
m_audioOutputInfos[deviceName].udpPort = udpPort;
|
||||||
|
m_audioOutputInfos[deviceName].copyToUDP = copyAudioToUDP;
|
||||||
|
m_audioOutputInfos[deviceName].udpStereo = udpStereo;
|
||||||
|
m_audioOutputInfos[deviceName].udpUseRTP = udpUseRTP;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -347,12 +388,17 @@ void AudioDeviceManager::debugAudioInputInfos() const
|
|||||||
|
|
||||||
void AudioDeviceManager::debugAudioOutputInfos() const
|
void AudioDeviceManager::debugAudioOutputInfos() const
|
||||||
{
|
{
|
||||||
QMap<QString, unsigned int>::const_iterator it = m_audioOutputSampleRates.begin();
|
QMap<QString, OutputDeviceInfo>::const_iterator it = m_audioOutputInfos.begin();
|
||||||
|
|
||||||
for (; it != m_audioOutputSampleRates.end(); ++it)
|
for (; it != m_audioOutputInfos.end(); ++it)
|
||||||
{
|
{
|
||||||
qDebug() << "AudioDeviceManager::debugAudioOutputInfos:"
|
qDebug() << "AudioDeviceManager::debugAudioOutputInfos:"
|
||||||
<< " name: " << it.key()
|
<< " name: " << it.key()
|
||||||
<< " sampleRate: " << it.value();
|
<< " sampleRate: " << it.value().sampleRate
|
||||||
|
<< " udpAddress: " << it.value().udpAddress
|
||||||
|
<< " udpPort: " << it.value().udpPort
|
||||||
|
<< " copyToUDP: " << it.value().copyToUDP
|
||||||
|
<< " udpStereo: " << it.value().udpStereo
|
||||||
|
<< " udpUseRTP: " << it.value().udpUseRTP;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,25 +22,51 @@
|
|||||||
#include <QList>
|
#include <QList>
|
||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QAudioDeviceInfo>
|
#include <QAudioDeviceInfo>
|
||||||
#include <QDataStream>
|
|
||||||
|
|
||||||
#include "audio/audioinput.h"
|
#include "audio/audioinput.h"
|
||||||
#include "audio/audiooutput.h"
|
#include "audio/audiooutput.h"
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
|
class QDataStream;
|
||||||
class AudioFifo;
|
class AudioFifo;
|
||||||
|
class MessageQueue;
|
||||||
|
|
||||||
class SDRBASE_API AudioDeviceManager {
|
class SDRBASE_API AudioDeviceManager {
|
||||||
public:
|
public:
|
||||||
class InputDeviceInfo
|
class InputDeviceInfo
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
InputDeviceInfo() :
|
||||||
|
sampleRate(m_defaultAudioSampleRate),
|
||||||
|
volume(m_defaultAudioInputVolume)
|
||||||
|
{}
|
||||||
unsigned int sampleRate;
|
unsigned int sampleRate;
|
||||||
float volume;
|
float volume;
|
||||||
friend QDataStream& operator<<(QDataStream& ds, const InputDeviceInfo& info);
|
friend QDataStream& operator<<(QDataStream& ds, const InputDeviceInfo& info);
|
||||||
friend QDataStream& operator>>(QDataStream& ds, InputDeviceInfo& info);
|
friend QDataStream& operator>>(QDataStream& ds, InputDeviceInfo& info);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class OutputDeviceInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OutputDeviceInfo() :
|
||||||
|
sampleRate(m_defaultAudioSampleRate),
|
||||||
|
udpAddress(m_defaultUDPAddress),
|
||||||
|
udpPort(m_defaultUDPPort),
|
||||||
|
copyToUDP(false),
|
||||||
|
udpStereo(false),
|
||||||
|
udpUseRTP(false)
|
||||||
|
{}
|
||||||
|
unsigned int sampleRate;
|
||||||
|
QString udpAddress;
|
||||||
|
quint16 udpPort;
|
||||||
|
bool copyToUDP;
|
||||||
|
bool udpStereo;
|
||||||
|
bool udpUseRTP;
|
||||||
|
friend QDataStream& operator<<(QDataStream& ds, const OutputDeviceInfo& info);
|
||||||
|
friend QDataStream& operator>>(QDataStream& ds, OutputDeviceInfo& info);
|
||||||
|
};
|
||||||
|
|
||||||
AudioDeviceManager();
|
AudioDeviceManager();
|
||||||
~AudioDeviceManager();
|
~AudioDeviceManager();
|
||||||
|
|
||||||
@ -51,24 +77,28 @@ public:
|
|||||||
bool getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const;
|
bool getOutputDeviceName(int outputDeviceIndex, QString &deviceName) const;
|
||||||
bool getInputDeviceName(int outputDeviceIndex, QString &deviceName) const;
|
bool getInputDeviceName(int outputDeviceIndex, QString &deviceName) const;
|
||||||
|
|
||||||
void addAudioSink(AudioFifo* audioFifo, int outputDeviceIndex = -1); //!< Add the audio sink
|
void addAudioSink(AudioFifo* audioFifo, MessageQueue *sampleSinkMessageQueue, int outputDeviceIndex = -1); //!< Add the audio sink
|
||||||
void removeAudioSink(AudioFifo* audioFifo); //!< Remove the audio sink
|
void removeAudioSink(AudioFifo* audioFifo); //!< Remove the audio sink
|
||||||
|
|
||||||
void addAudioSource(AudioFifo* audioFifo, int inputDeviceIndex = -1); //!< Add an audio source
|
void addAudioSource(AudioFifo* audioFifo, MessageQueue *sampleSourceMessageQueue, int inputDeviceIndex = -1); //!< Add an audio source
|
||||||
void removeAudioSource(AudioFifo* audioFifo); //!< Remove an audio source
|
void removeAudioSource(AudioFifo* audioFifo); //!< Remove an audio source
|
||||||
|
|
||||||
static const unsigned int m_defaultAudioSampleRate = 48000;
|
static const unsigned int m_defaultAudioSampleRate = 48000;
|
||||||
static const float m_defaultAudioInputVolume;
|
static const float m_defaultAudioInputVolume;
|
||||||
private:
|
static const QString m_defaultUDPAddress;
|
||||||
|
static const quint16 m_defaultUDPPort = 9998;
|
||||||
|
|
||||||
|
private:
|
||||||
QList<QAudioDeviceInfo> m_inputDevicesInfo;
|
QList<QAudioDeviceInfo> m_inputDevicesInfo;
|
||||||
QList<QAudioDeviceInfo> m_outputDevicesInfo;
|
QList<QAudioDeviceInfo> m_outputDevicesInfo;
|
||||||
|
|
||||||
QMap<AudioFifo*, int> m_audioSinkFifos; //< Audio sink FIFO to audio output device index-1 map
|
QMap<AudioFifo*, int> m_audioSinkFifos; //< audio sink FIFO to audio output device index-1 map
|
||||||
|
QMap<AudioFifo*, MessageQueue*> m_sampleSinkMessageQueues; //!< audio sink FIFO to attached sink message queue
|
||||||
QMap<int, AudioOutput*> m_audioOutputs; //!< audio device index to audio output map (index -1 is default device)
|
QMap<int, AudioOutput*> m_audioOutputs; //!< audio device index to audio output map (index -1 is default device)
|
||||||
QMap<QString, unsigned int> m_audioOutputSampleRates; //!< audio device name to audio sample rate
|
QMap<QString, OutputDeviceInfo> m_audioOutputInfos; //!< audio device name to audio output info
|
||||||
|
|
||||||
QMap<AudioFifo*, int> m_audioSourceFifos; //< Audio source FIFO to audio input device index-1 map
|
QMap<AudioFifo*, int> m_audioSourceFifos; //< audio source FIFO to audio input device index-1 map
|
||||||
|
QMap<AudioFifo*, MessageQueue*> m_sampleSourceMessageQueues; //!< audio source FIFO to attached source message queue
|
||||||
QMap<int, AudioInput*> m_audioInputs; //!< audio device index to audio input map (index -1 is default device)
|
QMap<int, AudioInput*> m_audioInputs; //!< audio device index to audio input map (index -1 is default device)
|
||||||
QMap<QString, InputDeviceInfo> m_audioInputInfos; //!< audio device name to audio input device info
|
QMap<QString, InputDeviceInfo> m_audioInputInfos; //!< audio device name to audio input device info
|
||||||
|
|
||||||
@ -94,5 +124,9 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info);
|
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info);
|
||||||
|
QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::InputDeviceInfo& info);
|
||||||
|
|
||||||
|
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::OutputDeviceInfo& info);
|
||||||
|
QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::OutputDeviceInfo& info);
|
||||||
|
|
||||||
#endif // INCLUDE_AUDIODEVICEMANGER_H
|
#endif // INCLUDE_AUDIODEVICEMANGER_H
|
||||||
|
@ -19,12 +19,16 @@
|
|||||||
#include <QAudioFormat>
|
#include <QAudioFormat>
|
||||||
#include <QAudioDeviceInfo>
|
#include <QAudioDeviceInfo>
|
||||||
#include <QAudioOutput>
|
#include <QAudioOutput>
|
||||||
#include "audio/audiooutput.h"
|
#include "audiooutput.h"
|
||||||
#include "audio/audiofifo.h"
|
#include "audiofifo.h"
|
||||||
|
#include "audionetsink.h"
|
||||||
|
|
||||||
AudioOutput::AudioOutput() :
|
AudioOutput::AudioOutput() :
|
||||||
m_mutex(QMutex::Recursive),
|
m_mutex(QMutex::Recursive),
|
||||||
m_audioOutput(0),
|
m_audioOutput(0),
|
||||||
|
m_audioNetSink(0),
|
||||||
|
m_copyAudioToUdp(false),
|
||||||
|
m_udpStereo(false),
|
||||||
m_audioUsageCount(0),
|
m_audioUsageCount(0),
|
||||||
m_onExit(false),
|
m_onExit(false),
|
||||||
m_audioFifos()
|
m_audioFifos()
|
||||||
@ -100,6 +104,7 @@ bool AudioOutput::start(int device, int rate)
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_audioOutput = new QAudioOutput(devInfo, m_audioFormat);
|
m_audioOutput = new QAudioOutput(devInfo, m_audioFormat);
|
||||||
|
m_audioNetSink = new AudioNetSink(0);
|
||||||
|
|
||||||
QIODevice::open(QIODevice::ReadOnly);
|
QIODevice::open(QIODevice::ReadOnly);
|
||||||
|
|
||||||
@ -123,6 +128,8 @@ void AudioOutput::stop()
|
|||||||
QMutexLocker mutexLocker(&m_mutex);
|
QMutexLocker mutexLocker(&m_mutex);
|
||||||
m_audioOutput->stop();
|
m_audioOutput->stop();
|
||||||
QIODevice::close();
|
QIODevice::close();
|
||||||
|
delete m_audioNetSink;
|
||||||
|
m_audioNetSink = 0;
|
||||||
delete m_audioOutput;
|
delete m_audioOutput;
|
||||||
|
|
||||||
// if (m_audioUsageCount > 0)
|
// if (m_audioUsageCount > 0)
|
||||||
@ -162,6 +169,35 @@ bool AudioOutput::open(OpenMode mode)
|
|||||||
return false;
|
return false;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
void AudioOutput::setUdpDestination(const QString& address, uint16_t port)
|
||||||
|
{
|
||||||
|
if (m_audioNetSink) {
|
||||||
|
m_audioNetSink->setDestination(address, port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioOutput::setUdpCopyToUDP(bool copyToUDP)
|
||||||
|
{
|
||||||
|
m_copyAudioToUdp = copyToUDP;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioOutput::setUdpStereo(bool stereo)
|
||||||
|
{
|
||||||
|
if (m_audioNetSink) {
|
||||||
|
m_audioNetSink->setStereo(stereo);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_udpStereo = stereo;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioOutput::setUdpUseRTP(bool useRTP)
|
||||||
|
{
|
||||||
|
if (m_audioNetSink) {
|
||||||
|
m_audioNetSink->selectType(useRTP ? AudioNetSink::SinkRTP : AudioNetSink::SinkUDP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
qint64 AudioOutput::readData(char* data, qint64 maxLen)
|
qint64 AudioOutput::readData(char* data, qint64 maxLen)
|
||||||
{
|
{
|
||||||
//qDebug("AudioOutput::readData: %lld", maxLen);
|
//qDebug("AudioOutput::readData: %lld", maxLen);
|
||||||
|
@ -23,11 +23,13 @@
|
|||||||
#include <QAudioFormat>
|
#include <QAudioFormat>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <stdint.h>
|
||||||
#include "export.h"
|
#include "export.h"
|
||||||
|
|
||||||
class QAudioOutput;
|
class QAudioOutput;
|
||||||
class AudioFifo;
|
class AudioFifo;
|
||||||
class AudioOutputPipe;
|
class AudioOutputPipe;
|
||||||
|
class AudioNetSink;
|
||||||
|
|
||||||
class SDRBASE_API AudioOutput : QIODevice {
|
class SDRBASE_API AudioOutput : QIODevice {
|
||||||
public:
|
public:
|
||||||
@ -44,9 +46,17 @@ public:
|
|||||||
unsigned int getRate() const { return m_audioFormat.sampleRate(); }
|
unsigned int getRate() const { return m_audioFormat.sampleRate(); }
|
||||||
void setOnExit(bool onExit) { m_onExit = onExit; }
|
void setOnExit(bool onExit) { m_onExit = onExit; }
|
||||||
|
|
||||||
|
void setUdpDestination(const QString& address, uint16_t port);
|
||||||
|
void setUdpCopyToUDP(bool copyToUDP);
|
||||||
|
void setUdpStereo(bool stereo);
|
||||||
|
void setUdpUseRTP(bool useRTP);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QMutex m_mutex;
|
QMutex m_mutex;
|
||||||
QAudioOutput* m_audioOutput;
|
QAudioOutput* m_audioOutput;
|
||||||
|
AudioNetSink* m_audioNetSink;
|
||||||
|
bool m_copyAudioToUdp;
|
||||||
|
bool m_udpStereo;
|
||||||
uint m_audioUsageCount;
|
uint m_audioUsageCount;
|
||||||
bool m_onExit;
|
bool m_onExit;
|
||||||
|
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QTabWidget" name="tabWidget">
|
<widget class="QTabWidget" name="tabWidget">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>1</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="tab_2">
|
<widget class="QWidget" name="tabOutput">
|
||||||
<attribute name="title">
|
<attribute name="title">
|
||||||
<string>Audio Output</string>
|
<string>Audio Output</string>
|
||||||
</attribute>
|
</attribute>
|
||||||
@ -39,6 +39,176 @@
|
|||||||
</column>
|
</column>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="sampleRateLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="outputSampleRateLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Rate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="outputSampleRate">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Audio output sample rate</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>8000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>192000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>48000</number>
|
||||||
|
</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="QPushButton" name="outputReset">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Reset values to defaults</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>R</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="udpLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udpAddressLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Addr</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="udpAddress">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>140</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>UDP address</string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>000.000.000.000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>127.0.0.1</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="udpPortLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Port</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLineEdit" name="udpPort">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>60</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>UDP port</string>
|
||||||
|
</property>
|
||||||
|
<property name="inputMask">
|
||||||
|
<string>00000; </string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>9998</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<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="ButtonSwitch" name="udpCopy">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Copy audio to UDP</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>U</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="udpStereo">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Copy to UDP as stereo (no L+R mix)</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>S</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="udpUseRTP">
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Use RTP protocol</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>R</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
<widget class="QWidget" name="tabInput">
|
<widget class="QWidget" name="tabInput">
|
||||||
@ -57,6 +227,41 @@
|
|||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="inputVolumeLayout">
|
<layout class="QHBoxLayout" name="inputVolumeLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="inputSampleRateLabel">
|
||||||
|
<property name="text">
|
||||||
|
<string>Rate</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="inputSampleRate">
|
||||||
|
<property name="minimumSize">
|
||||||
|
<size>
|
||||||
|
<width>80</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Audio input sample rate</string>
|
||||||
|
</property>
|
||||||
|
<property name="alignment">
|
||||||
|
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||||
|
</property>
|
||||||
|
<property name="minimum">
|
||||||
|
<number>8000</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>192000</number>
|
||||||
|
</property>
|
||||||
|
<property name="singleStep">
|
||||||
|
<number>50</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>48000</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QLabel" name="inputVolumeLabel">
|
<widget class="QLabel" name="inputVolumeLabel">
|
||||||
<property name="maximumSize">
|
<property name="maximumSize">
|
||||||
@ -78,6 +283,9 @@
|
|||||||
<height>24</height>
|
<height>24</height>
|
||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Input volume</string>
|
||||||
|
</property>
|
||||||
<property name="maximum">
|
<property name="maximum">
|
||||||
<number>100</number>
|
<number>100</number>
|
||||||
</property>
|
</property>
|
||||||
@ -118,6 +326,22 @@
|
|||||||
</property>
|
</property>
|
||||||
</spacer>
|
</spacer>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="inputReset">
|
||||||
|
<property name="maximumSize">
|
||||||
|
<size>
|
||||||
|
<width>24</width>
|
||||||
|
<height>16777215</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
<property name="toolTip">
|
||||||
|
<string>Reset values to default</string>
|
||||||
|
</property>
|
||||||
|
<property name="text">
|
||||||
|
<string>R</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
@ -136,6 +360,13 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
|
<customwidgets>
|
||||||
|
<customwidget>
|
||||||
|
<class>ButtonSwitch</class>
|
||||||
|
<extends>QToolButton</extends>
|
||||||
|
<header>gui/buttonswitch.h</header>
|
||||||
|
</customwidget>
|
||||||
|
</customwidgets>
|
||||||
<tabstops>
|
<tabstops>
|
||||||
<tabstop>buttonBox</tabstop>
|
<tabstop>buttonBox</tabstop>
|
||||||
<tabstop>tabWidget</tabstop>
|
<tabstop>tabWidget</tabstop>
|
||||||
|
Loading…
Reference in New Issue
Block a user