kopia lustrzana https://github.com/f4exb/sdrangel
				
				
				
			Multiple audio support: extend audio output information to UDP/RTP information. New audio preferences dialog
							rodzic
							
								
									bfce9a4fcc
								
							
						
					
					
						commit
						745e187e2b
					
				| 
						 | 
				
			
			@ -63,7 +63,7 @@ AMDemod::AMDemod(DeviceSourceAPI *deviceAPI) :
 | 
			
		|||
 | 
			
		||||
	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->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,7 +84,7 @@ BFMDemod::BFMDemod(DeviceSourceAPI *deviceAPI) :
 | 
			
		|||
	m_audioBuffer.resize(16384);
 | 
			
		||||
	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->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
 | 
			
		||||
    m_audioNetSink->setStereo(true);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,8 +72,8 @@ DSDDemod::DSDDemod(DeviceSourceAPI *deviceAPI) :
 | 
			
		|||
    m_magsqPeak = 0.0f;
 | 
			
		||||
    m_magsqCount = 0;
 | 
			
		||||
 | 
			
		||||
    DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo1);
 | 
			
		||||
    DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo2);
 | 
			
		||||
    DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo1, getInputMessageQueue());
 | 
			
		||||
    DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo2, getInputMessageQueue());
 | 
			
		||||
 | 
			
		||||
//    m_udpBufferAudio = new UDPSink<AudioSample>(this, m_udpBlockSize, m_settings.m_udpPort);
 | 
			
		||||
//    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_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->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);
 | 
			
		||||
	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->setDestination(m_settings.m_udpAddress, m_settings.m_udpPort);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,7 +59,7 @@ WFMDemod::WFMDemod(DeviceSourceAPI* deviceAPI) :
 | 
			
		|||
	m_audioBuffer.resize(16384);
 | 
			
		||||
	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->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)
 | 
			
		||||
        {
 | 
			
		||||
            m_audioBufferFill = 0;
 | 
			
		||||
            DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo);
 | 
			
		||||
            DSPEngine::instance()->getAudioDeviceManager()->addAudioSink(&m_audioFifo, getInputMessageQueue());
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,7 +66,7 @@ AMMod::AMMod(DeviceSinkAPI *deviceAPI) :
 | 
			
		|||
	m_magsq = 0.0;
 | 
			
		||||
 | 
			
		||||
	m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
 | 
			
		||||
 | 
			
		||||
	// CW keyer
 | 
			
		||||
	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_ctcssNco.setFreq(88.5, m_settings.m_audioSampleRate);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
 | 
			
		||||
 | 
			
		||||
    // CW keyer
 | 
			
		||||
    m_cwKeyer.setSampleRate(m_settings.m_audioSampleRate);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -88,7 +88,7 @@ SSBMod::SSBMod(DeviceSinkAPI *deviceAPI) :
 | 
			
		|||
	m_magsq = 0.0;
 | 
			
		||||
 | 
			
		||||
	m_toneNco.setFreq(1000.0, m_settings.m_audioSampleRate);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
 | 
			
		||||
 | 
			
		||||
	// CW keyer
 | 
			
		||||
	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_toneNcoRF.setFreq(1000.0, m_outputSampleRate);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo);
 | 
			
		||||
	DSPEngine::instance()->getAudioDeviceManager()->addAudioSource(&m_audioFifo, getInputMessageQueue());
 | 
			
		||||
 | 
			
		||||
    // CW keyer
 | 
			
		||||
    m_cwKeyer.setSampleRate(m_outputSampleRate);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,9 +18,11 @@
 | 
			
		|||
#include "audio/audiodevicemanager.h"
 | 
			
		||||
#include "util/simpleserializer.h"
 | 
			
		||||
 | 
			
		||||
#include <QDataStream>
 | 
			
		||||
#include <QDebug>
 | 
			
		||||
 | 
			
		||||
const float AudioDeviceManager::m_defaultAudioInputVolume = 0.15f;
 | 
			
		||||
const QString AudioDeviceManager::m_defaultUDPAddress = "127.0.0.1";
 | 
			
		||||
 | 
			
		||||
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::InputDeviceInfo& info)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -34,6 +36,18 @@ QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::InputDeviceInfo& in
 | 
			
		|||
    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()
 | 
			
		||||
{
 | 
			
		||||
    m_inputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioInput);
 | 
			
		||||
| 
						 | 
				
			
			@ -122,7 +136,7 @@ void AudioDeviceManager::serializeInputMap(QByteArray& data) const
 | 
			
		|||
void AudioDeviceManager::serializeOutputMap(QByteArray& data) const
 | 
			
		||||
{
 | 
			
		||||
    QDataStream *stream = new QDataStream(&data, QIODevice::WriteOnly);
 | 
			
		||||
    *stream << m_audioOutputSampleRates;
 | 
			
		||||
    *stream << m_audioOutputInfos;
 | 
			
		||||
    delete stream;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -167,10 +181,10 @@ void AudioDeviceManager::deserializeInputMap(QByteArray& data)
 | 
			
		|||
void AudioDeviceManager::deserializeOutputMap(QByteArray& data)
 | 
			
		||||
{
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -198,6 +212,7 @@ void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, int outputDeviceInde
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO
 | 
			
		||||
    m_sampleSinkMessageQueues[audioFifo] = sampleSinkMessageQueue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo)
 | 
			
		||||
| 
						 | 
				
			
			@ -218,9 +233,10 @@ void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    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);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -248,6 +264,7 @@ void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo, int inputDeviceInd
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    m_audioSourceFifos[audioFifo] = inputDeviceIndex; // register audio FIFO
 | 
			
		||||
    m_sampleSourceMessageQueues[audioFifo] = sampleSourceMessageQueue;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
 | 
			
		||||
| 
						 | 
				
			
			@ -268,23 +285,47 @@ void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    m_audioSourceFifos.remove(audioFifo); // unregister audio FIFO
 | 
			
		||||
    m_sampleSourceMessageQueues.remove(audioFifo);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void AudioDeviceManager::startAudioOutput(int outputDeviceIndex)
 | 
			
		||||
{
 | 
			
		||||
    unsigned int sampleRate;
 | 
			
		||||
    QString udpAddress;
 | 
			
		||||
    quint16 udpPort;
 | 
			
		||||
    bool copyAudioToUDP;
 | 
			
		||||
    bool udpStereo;
 | 
			
		||||
    bool udpUseRTP;
 | 
			
		||||
    QString deviceName;
 | 
			
		||||
 | 
			
		||||
    if (getOutputDeviceName(outputDeviceIndex, deviceName))
 | 
			
		||||
    {
 | 
			
		||||
        if (m_audioOutputSampleRates.find(deviceName) == m_audioOutputSampleRates.end()) {
 | 
			
		||||
        if (m_audioOutputInfos.find(deviceName) == m_audioOutputInfos.end())
 | 
			
		||||
        {
 | 
			
		||||
            sampleRate = m_defaultAudioSampleRate;
 | 
			
		||||
        } else {
 | 
			
		||||
            sampleRate = m_audioOutputSampleRates[deviceName];
 | 
			
		||||
            udpAddress = m_defaultUDPAddress;
 | 
			
		||||
            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_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
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			@ -347,12 +388,17 @@ void AudioDeviceManager::debugAudioInputInfos() 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:"
 | 
			
		||||
                << " 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 <QMap>
 | 
			
		||||
#include <QAudioDeviceInfo>
 | 
			
		||||
#include <QDataStream>
 | 
			
		||||
 | 
			
		||||
#include "audio/audioinput.h"
 | 
			
		||||
#include "audio/audiooutput.h"
 | 
			
		||||
#include "export.h"
 | 
			
		||||
 | 
			
		||||
class QDataStream;
 | 
			
		||||
class AudioFifo;
 | 
			
		||||
class MessageQueue;
 | 
			
		||||
 | 
			
		||||
class SDRBASE_API AudioDeviceManager {
 | 
			
		||||
public:
 | 
			
		||||
    class InputDeviceInfo
 | 
			
		||||
    {
 | 
			
		||||
    public:
 | 
			
		||||
        InputDeviceInfo() :
 | 
			
		||||
            sampleRate(m_defaultAudioSampleRate),
 | 
			
		||||
            volume(m_defaultAudioInputVolume)
 | 
			
		||||
        {}
 | 
			
		||||
        unsigned int sampleRate;
 | 
			
		||||
        float volume;
 | 
			
		||||
        friend QDataStream& operator<<(QDataStream& ds, const 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();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -51,24 +77,28 @@ public:
 | 
			
		|||
    bool getOutputDeviceName(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 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
 | 
			
		||||
 | 
			
		||||
    static const unsigned int m_defaultAudioSampleRate = 48000;
 | 
			
		||||
    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_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<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<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, AudioDeviceManager::InputDeviceInfo& info);
 | 
			
		||||
 | 
			
		||||
QDataStream& operator<<(QDataStream& ds, const AudioDeviceManager::OutputDeviceInfo& info);
 | 
			
		||||
QDataStream& operator>>(QDataStream& ds, AudioDeviceManager::OutputDeviceInfo& info);
 | 
			
		||||
 | 
			
		||||
#endif // INCLUDE_AUDIODEVICEMANGER_H
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,12 +19,16 @@
 | 
			
		|||
#include <QAudioFormat>
 | 
			
		||||
#include <QAudioDeviceInfo>
 | 
			
		||||
#include <QAudioOutput>
 | 
			
		||||
#include "audio/audiooutput.h"
 | 
			
		||||
#include "audio/audiofifo.h"
 | 
			
		||||
#include "audiooutput.h"
 | 
			
		||||
#include "audiofifo.h"
 | 
			
		||||
#include "audionetsink.h"
 | 
			
		||||
 | 
			
		||||
AudioOutput::AudioOutput() :
 | 
			
		||||
	m_mutex(QMutex::Recursive),
 | 
			
		||||
	m_audioOutput(0),
 | 
			
		||||
	m_audioNetSink(0),
 | 
			
		||||
	m_copyAudioToUdp(false),
 | 
			
		||||
	m_udpStereo(false),
 | 
			
		||||
	m_audioUsageCount(0),
 | 
			
		||||
	m_onExit(false),
 | 
			
		||||
	m_audioFifos()
 | 
			
		||||
| 
						 | 
				
			
			@ -100,6 +104,7 @@ bool AudioOutput::start(int device, int rate)
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        m_audioOutput = new QAudioOutput(devInfo, m_audioFormat);
 | 
			
		||||
        m_audioNetSink = new AudioNetSink(0);
 | 
			
		||||
 | 
			
		||||
        QIODevice::open(QIODevice::ReadOnly);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -123,6 +128,8 @@ void AudioOutput::stop()
 | 
			
		|||
    QMutexLocker mutexLocker(&m_mutex);
 | 
			
		||||
    m_audioOutput->stop();
 | 
			
		||||
    QIODevice::close();
 | 
			
		||||
    delete m_audioNetSink;
 | 
			
		||||
    m_audioNetSink = 0;
 | 
			
		||||
    delete m_audioOutput;
 | 
			
		||||
 | 
			
		||||
//    if (m_audioUsageCount > 0)
 | 
			
		||||
| 
						 | 
				
			
			@ -162,6 +169,35 @@ bool AudioOutput::open(OpenMode mode)
 | 
			
		|||
	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)
 | 
			
		||||
{
 | 
			
		||||
    //qDebug("AudioOutput::readData: %lld", maxLen);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,11 +23,13 @@
 | 
			
		|||
#include <QAudioFormat>
 | 
			
		||||
#include <list>
 | 
			
		||||
#include <vector>
 | 
			
		||||
#include <stdint.h>
 | 
			
		||||
#include "export.h"
 | 
			
		||||
 | 
			
		||||
class QAudioOutput;
 | 
			
		||||
class AudioFifo;
 | 
			
		||||
class AudioOutputPipe;
 | 
			
		||||
class AudioNetSink;
 | 
			
		||||
 | 
			
		||||
class SDRBASE_API AudioOutput : QIODevice {
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -44,9 +46,17 @@ public:
 | 
			
		|||
	unsigned int getRate() const { return m_audioFormat.sampleRate(); }
 | 
			
		||||
	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:
 | 
			
		||||
	QMutex m_mutex;
 | 
			
		||||
	QAudioOutput* m_audioOutput;
 | 
			
		||||
	AudioNetSink* m_audioNetSink;
 | 
			
		||||
	bool m_copyAudioToUdp;
 | 
			
		||||
	bool m_udpStereo;
 | 
			
		||||
	uint m_audioUsageCount;
 | 
			
		||||
	bool m_onExit;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,9 +23,9 @@
 | 
			
		|||
   <item>
 | 
			
		||||
    <widget class="QTabWidget" name="tabWidget">
 | 
			
		||||
     <property name="currentIndex">
 | 
			
		||||
      <number>1</number>
 | 
			
		||||
      <number>0</number>
 | 
			
		||||
     </property>
 | 
			
		||||
     <widget class="QWidget" name="tab_2">
 | 
			
		||||
     <widget class="QWidget" name="tabOutput">
 | 
			
		||||
      <attribute name="title">
 | 
			
		||||
       <string>Audio Output</string>
 | 
			
		||||
      </attribute>
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +39,176 @@
 | 
			
		|||
         </column>
 | 
			
		||||
        </widget>
 | 
			
		||||
       </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>
 | 
			
		||||
     </widget>
 | 
			
		||||
     <widget class="QWidget" name="tabInput">
 | 
			
		||||
| 
						 | 
				
			
			@ -57,6 +227,41 @@
 | 
			
		|||
       </item>
 | 
			
		||||
       <item>
 | 
			
		||||
        <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>
 | 
			
		||||
          <widget class="QLabel" name="inputVolumeLabel">
 | 
			
		||||
           <property name="maximumSize">
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +283,9 @@
 | 
			
		|||
             <height>24</height>
 | 
			
		||||
            </size>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="toolTip">
 | 
			
		||||
            <string>Input volume</string>
 | 
			
		||||
           </property>
 | 
			
		||||
           <property name="maximum">
 | 
			
		||||
            <number>100</number>
 | 
			
		||||
           </property>
 | 
			
		||||
| 
						 | 
				
			
			@ -118,6 +326,22 @@
 | 
			
		|||
           </property>
 | 
			
		||||
          </spacer>
 | 
			
		||||
         </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>
 | 
			
		||||
       </item>
 | 
			
		||||
      </layout>
 | 
			
		||||
| 
						 | 
				
			
			@ -136,6 +360,13 @@
 | 
			
		|||
   </item>
 | 
			
		||||
  </layout>
 | 
			
		||||
 </widget>
 | 
			
		||||
 <customwidgets>
 | 
			
		||||
  <customwidget>
 | 
			
		||||
   <class>ButtonSwitch</class>
 | 
			
		||||
   <extends>QToolButton</extends>
 | 
			
		||||
   <header>gui/buttonswitch.h</header>
 | 
			
		||||
  </customwidget>
 | 
			
		||||
 </customwidgets>
 | 
			
		||||
 <tabstops>
 | 
			
		||||
  <tabstop>buttonBox</tabstop>
 | 
			
		||||
  <tabstop>tabWidget</tabstop>
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Ładowanie…
	
		Reference in New Issue