Multiple audio support: added ability to manage more than one audio output

pull/162/head
f4exb 2018-03-24 23:50:28 +01:00
rodzic d7db3405a0
commit 7aaa230eb4
20 zmienionych plików z 133 dodań i 99 usunięć

Wyświetl plik

@ -33,7 +33,7 @@ void AMDemodSettings::resetToDefaults()
m_rfBandwidth = 5000;
m_squelch = -40.0;
m_volume = 2.0;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_audioMute = false;
m_bandpassEnable = false;
m_copyAudioToUDP = false;

Wyświetl plik

@ -41,7 +41,7 @@ void BFMDemodSettings::resetToDefaults()
m_afBandwidth = 15000;
m_volume = 2.0;
m_squelch = -60.0;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_audioStereo = false;
m_lsbStereo = false;
m_showPilot = false;

Wyświetl plik

@ -39,7 +39,7 @@ void DSDDemodSettings::resetToDefaults()
m_squelchGate = 5; // 10s of ms at 48000 Hz sample rate. Corresponds to 2400 for AGC attack
m_squelch = -40.0;
m_audioMute = false;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_enableCosineFiltering = false;
m_syncOrConstellation = false;
m_slot1On = true;

Wyświetl plik

@ -49,7 +49,7 @@ void NFMDemodSettings::resetToDefaults()
m_ctcssOn = false;
m_audioMute = false;
m_ctcssIndex = 0;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_copyAudioToUDP = false;
m_copyAudioUseRTP = false;
m_udpAddress = "127.0.0.1";

Wyświetl plik

@ -66,7 +66,7 @@ SSBDemod::SSBDemod(DeviceSourceAPI *deviceAPI) :
m_spanLog2 = 3;
m_inputSampleRate = 48000;
m_inputFrequencyOffset = 0;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_audioBuffer.resize(1<<14);
m_audioBufferFill = 0;

Wyświetl plik

@ -54,7 +54,7 @@ void SSBDemodSettings::resetToDefaults()
m_volume = 3.0;
m_spanLog2 = 3;
m_inputFrequencyOffset = 0;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_udpAddress = "127.0.0.1";
m_udpPort = 9999;
m_rgbColor = QColor(0, 255, 0).rgb();

Wyświetl plik

@ -42,7 +42,7 @@ void WFMDemodSettings::resetToDefaults()
m_volume = 2.0;
m_squelch = -60.0;
m_audioMute = false;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_copyAudioToUDP = false;
m_copyAudioUseRTP = false;
m_udpAddress = "127.0.0.1";

Wyświetl plik

@ -34,7 +34,7 @@ void AMModSettings::resetToDefaults()
m_rfBandwidth = 12500.0;
m_modFactor = 0.2f;
m_toneFrequency = 1000.0f;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_volumeFactor = 1.0f;
m_channelMute = false;
m_playLoop = false;

Wyświetl plik

@ -50,7 +50,7 @@ void NFMModSettings::resetToDefaults()
m_rfBandwidth = 12500.0f;
m_fmDeviation = 5000.0f;
m_toneFrequency = 1000.0f;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_volumeFactor = 1.0f;
m_channelMute = false;
m_playLoop = false;

Wyświetl plik

@ -51,7 +51,7 @@ void SSBModSettings::resetToDefaults()
m_usb = true;
m_toneFrequency = 1000.0;
m_volumeFactor = 1.0;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_spanLog2 = 3;
m_audioBinaural = false;
m_audioFlipChannels = false;

Wyświetl plik

@ -42,7 +42,7 @@ void WFMModSettings::resetToDefaults()
m_afBandwidth = 15000.0f;
m_fmDeviation = 50000.0f;
m_toneFrequency = 1000.0f;
m_audioSampleRate = DSPEngine::instance()->getAudioSampleRate();
m_audioSampleRate = DSPEngine::instance()->getDefaultAudioSampleRate();
m_volumeFactor = 1.0f;
m_channelMute = false;
m_playLoop = false;

Wyświetl plik

@ -18,10 +18,9 @@
#include <audio/audiodevicemanager.h>
#include "util/simpleserializer.h"
AudioDeviceManager::AudioDeviceManager() :
AudioDeviceManager::AudioDeviceManager(unsigned int defaultAudioSampleRate) :
m_defaultAudioSampleRate(defaultAudioSampleRate),
m_inputDeviceIndex(-1), // default device
m_outputDeviceIndex(-1), // default device
m_audioOutputSampleRate(48000), // Use default output device at 48 kHz
m_audioInputSampleRate(48000), // Use default input device at 48 kHz
m_inputVolume(1.0f)
{
@ -29,10 +28,18 @@ AudioDeviceManager::AudioDeviceManager() :
m_outputDevicesInfo = QAudioDeviceInfo::availableDevices(QAudio::AudioOutput);
}
AudioDeviceManager::~AudioDeviceManager()
{
QMap<int, AudioOutput*>::iterator it = m_audioOutputs.begin();
for (; it != m_audioOutputs.end(); ++it) {
delete(*it);
}
}
void AudioDeviceManager::resetToDefaults()
{
m_inputDeviceIndex = -1;
m_outputDeviceIndex = -1;
m_inputVolume = 1.0f;
}
@ -40,7 +47,6 @@ QByteArray AudioDeviceManager::serialize() const
{
SimpleSerializer s(1);
s.writeS32(1, m_inputDeviceIndex);
s.writeS32(2, m_outputDeviceIndex);
s.writeFloat(3, m_inputVolume);
return s.final();
}
@ -57,7 +63,6 @@ bool AudioDeviceManager::deserialize(const QByteArray& data)
if(d.getVersion() == 1)
{
d.readS32(1, &m_inputDeviceIndex, -1);
d.readS32(2, &m_outputDeviceIndex, -1);
d.readFloat(3, &m_inputVolume, 1.0f);
return true;
}
@ -68,48 +73,81 @@ bool AudioDeviceManager::deserialize(const QByteArray& data)
}
}
int AudioDeviceManager::getOutputDeviceIndex(AudioFifo* audioFifo) const
{
if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end()) {
return -2; // error
} else {
return m_audioSinkFifos[audioFifo];
}
}
void AudioDeviceManager::setInputDeviceIndex(int inputDeviceIndex)
{
int nbDevices = m_inputDevicesInfo.size();
m_inputDeviceIndex = inputDeviceIndex < -1 ? -1 : inputDeviceIndex >= nbDevices ? nbDevices-1 : inputDeviceIndex;
}
void AudioDeviceManager::setOutputDeviceIndex(int outputDeviceIndex)
{
int nbDevices = m_outputDevicesInfo.size();
m_outputDeviceIndex = outputDeviceIndex < -1 ? -1 : outputDeviceIndex >= nbDevices ? nbDevices-1 : outputDeviceIndex;
}
void AudioDeviceManager::setInputVolume(float inputVolume)
{
m_inputVolume = inputVolume < 0.0 ? 0.0 : inputVolume > 1.0 ? 1.0 : inputVolume;
}
void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo)
void AudioDeviceManager::addAudioSink(AudioFifo* audioFifo, int outputDeviceIndex)
{
qDebug("AudioDeviceInfo::addAudioSink");
qDebug("AudioDeviceManager::addAudioSink: %d: %p", outputDeviceIndex, audioFifo);
if (m_audioOutput.getNbFifos() == 0) {
startAudioOutput();
if (m_audioOutputs.find(outputDeviceIndex) == m_audioOutputs.end())
{
m_audioOutputs[outputDeviceIndex] = new AudioOutput();
m_audioOutputSampleRates[outputDeviceIndex] = m_defaultAudioSampleRate;
}
m_audioOutput.addFifo(audioFifo);
if (m_audioOutputs[outputDeviceIndex]->getNbFifos() == 0) {
startAudioOutput(outputDeviceIndex);
}
if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end()) // new FIFO
{
m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo);
}
else
{
int audioOutputDeviceIndex = m_audioSinkFifos[audioFifo];
if (audioOutputDeviceIndex != outputDeviceIndex) // change of audio device
{
removeAudioSink(audioFifo); // remove from current
m_audioOutputs[outputDeviceIndex]->addFifo(audioFifo); // add to new
}
}
m_audioSinkFifos[audioFifo] = outputDeviceIndex; // register audio FIFO
}
void AudioDeviceManager::removeAudioSink(AudioFifo* audioFifo)
{
qDebug("AudioDeviceInfo::removeAudioSink");
qDebug("AudioDeviceManager::removeAudioSink: %p", audioFifo);
m_audioOutput.removeFifo(audioFifo);
if (m_audioOutput.getNbFifos() == 0) {
stopAudioOutput();
if (m_audioSinkFifos.find(audioFifo) == m_audioSinkFifos.end())
{
qWarning("AudioDeviceManager::removeAudioSink: audio FIFO %p not found", audioFifo);
return;
}
int audioOutputDeviceIndex = m_audioSinkFifos[audioFifo];
m_audioOutputs[audioOutputDeviceIndex]->removeFifo(audioFifo);
if (m_audioOutputs[audioOutputDeviceIndex]->getNbFifos() == 0) {
stopAudioOutput(audioOutputDeviceIndex);
}
m_audioSinkFifos.remove(audioFifo); // unregister audio FIFO
}
void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo)
{
qDebug("AudioDeviceInfo::addAudioSource");
qDebug("AudioDeviceManager::addAudioSource");
if (m_audioInput.getNbFifos() == 0) {
startAudioInput();
@ -120,7 +158,7 @@ void AudioDeviceManager::addAudioSource(AudioFifo* audioFifo)
void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
{
qDebug("AudioDeviceInfo::removeAudioSource");
qDebug("AudioDeviceManager::removeAudioSource");
m_audioInput.removeFifo(audioFifo);
@ -129,15 +167,17 @@ void AudioDeviceManager::removeAudioSource(AudioFifo* audioFifo)
}
}
void AudioDeviceManager::startAudioOutput()
void AudioDeviceManager::startAudioOutput(int outputDeviceIndex)
{
m_audioOutput.start(m_outputDeviceIndex, m_audioOutputSampleRate);
m_audioOutputSampleRate = m_audioOutput.getRate(); // update with actual rate
m_audioOutputs[outputDeviceIndex]->start(outputDeviceIndex, m_audioOutputSampleRates[outputDeviceIndex]);
m_audioOutputSampleRates[outputDeviceIndex] = m_audioOutputs[outputDeviceIndex]->getRate(); // update with actual rate
// m_audioOutput.start(m_outputDeviceIndex, m_audioOutputSampleRate);
// m_audioOutputSampleRate = m_audioOutput.getRate(); // update with actual rate
}
void AudioDeviceManager::stopAudioOutput()
void AudioDeviceManager::stopAudioOutput(int outputDeviceIndex)
{
m_audioOutput.stop();
m_audioOutputs[outputDeviceIndex]->stop();
}
void AudioDeviceManager::startAudioInput()

Wyświetl plik

@ -20,6 +20,7 @@
#include <QStringList>
#include <QList>
#include <QMap>
#include <QAudioDeviceInfo>
#include "audio/audioinput.h"
@ -30,22 +31,20 @@ class AudioFifo;
class SDRBASE_API AudioDeviceManager {
public:
AudioDeviceManager();
AudioDeviceManager(unsigned int defaultAudioSampleRate);
~AudioDeviceManager();
const QList<QAudioDeviceInfo>& getInputDevices() const { return m_inputDevicesInfo; }
const QList<QAudioDeviceInfo>& getOutputDevices() const { return m_outputDevicesInfo; }
int getOutputDeviceIndex(AudioFifo* audioFifo) const;
int getInputDeviceIndex() const { return m_inputDeviceIndex; }
int getOutputDeviceIndex() const { return m_outputDeviceIndex; }
float getInputVolume() const { return m_inputVolume; }
void setInputDeviceIndex(int inputDeviceIndex);
void setOutputDeviceIndex(int inputDeviceIndex);
void setInputVolume(float inputVolume);
unsigned int getAudioSampleRate() const { return m_audioOutputSampleRate; }
void addAudioSink(AudioFifo* audioFifo); //!< Add the audio sink
void addAudioSink(AudioFifo* audioFifo, int outputDeviceIndex = -1); //!< Add the audio sink
void removeAudioSink(AudioFifo* audioFifo); //!< Remove the audio sink
void addAudioSource(AudioFifo* audioFifo); //!< Add an audio source
@ -54,13 +53,14 @@ public:
void setAudioInputVolume(float volume) { m_audioInput.setVolume(volume); }
private:
unsigned int m_defaultAudioSampleRate;
QList<QAudioDeviceInfo> m_inputDevicesInfo;
QList<QAudioDeviceInfo> m_outputDevicesInfo;
QMap<AudioFifo*, int> m_audioSinkFifos; //< Audio sink FIFO to audio output device index-1 map
QMap<int, AudioOutput*> m_audioOutputs; //!< audio device index-1 to audio output map (index -1 is default device)
QMap<int, unsigned int> m_audioOutputSampleRates; //!< audio device index-1 to audio sample rate
int m_inputDeviceIndex;
int m_outputDeviceIndex;
unsigned int m_audioOutputSampleRate;
unsigned int m_audioInputSampleRate;
AudioOutput m_audioOutput;
AudioInput m_audioInput;
float m_inputVolume;
@ -68,8 +68,8 @@ private:
QByteArray serialize() const;
bool deserialize(const QByteArray& data);
void startAudioOutput();
void stopAudioOutput();
void startAudioOutput(int outputDeviceIndex);
void stopAudioOutput(int outputDeviceIndex);
void startAudioInput();
void stopAudioInput();

Wyświetl plik

@ -33,23 +33,23 @@ AudioOutput::AudioOutput() :
AudioOutput::~AudioOutput()
{
stop();
QMutexLocker mutexLocker(&m_mutex);
for (std::list<AudioFifo*>::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it)
{
delete *it;
}
m_audioFifos.clear();
// stop();
//
// QMutexLocker mutexLocker(&m_mutex);
//
// for (std::list<AudioFifo*>::iterator it = m_audioFifos.begin(); it != m_audioFifos.end(); ++it)
// {
// delete *it;
// }
//
// m_audioFifos.clear();
}
bool AudioOutput::start(int device, int rate)
{
if (m_audioUsageCount == 0)
{
// if (m_audioUsageCount == 0)
// {
QMutexLocker mutexLocker(&m_mutex);
QAudioDeviceInfo devInfo;
@ -109,9 +109,9 @@ bool AudioOutput::start(int device, int rate)
{
qWarning("AudioOutput::start: cannot start");
}
}
m_audioUsageCount++;
// }
//
// m_audioUsageCount++;
return true;
}
@ -120,20 +120,25 @@ void AudioOutput::stop()
{
qDebug("AudioOutput::stop");
if (m_audioUsageCount > 0)
{
m_audioUsageCount--;
QMutexLocker mutexLocker(&m_mutex);
m_audioOutput->stop();
QIODevice::close();
delete m_audioOutput;
if (m_audioUsageCount == 0)
{
QMutexLocker mutexLocker(&m_mutex);
QIODevice::close();
if (!m_onExit) {
delete m_audioOutput;
}
}
}
// if (m_audioUsageCount > 0)
// {
// m_audioUsageCount--;
//
// if (m_audioUsageCount == 0)
// {
// QMutexLocker mutexLocker(&m_mutex);
// QIODevice::close();
//
// if (!m_onExit) {
// delete m_audioOutput;
// }
// }
// }
}
void AudioOutput::addFifo(AudioFifo* audioFifo)

Wyświetl plik

@ -41,7 +41,7 @@ public:
void removeFifo(AudioFifo* audioFifo);
int getNbFifos() const { return m_audioFifos.size(); }
uint getRate() const { return m_audioFormat.sampleRate(); }
unsigned int getRate() const { return m_audioFormat.sampleRate(); }
void setOnExit(bool onExit) { m_onExit = onExit; }
private:

Wyświetl plik

@ -26,8 +26,7 @@
DSPEngine::DSPEngine() :
m_deviceSourceEnginesUIDSequence(0),
m_deviceSinkEnginesUIDSequence(0),
m_audioOutputSampleRate(48000), // Use default output device at 48 kHz
m_audioInputSampleRate(48000), // Use default input device at 48 kHz
m_audioDeviceManager(m_defaultAudioSampleRate),
m_audioInputDeviceIndex(-1), // default device
m_audioOutputDeviceIndex(-1) // default device
{
@ -37,9 +36,6 @@ DSPEngine::DSPEngine() :
DSPEngine::~DSPEngine()
{
m_audioOutput.setOnExit(true);
m_audioInput.setOnExit(true);
std::vector<DSPDeviceSourceEngine*>::iterator it = m_deviceSourceEngines.begin();
while (it != m_deviceSourceEngines.end())

Wyświetl plik

@ -41,7 +41,7 @@ public:
static DSPEngine *instance();
uint getAudioSampleRate() const { return m_audioOutputSampleRate; }
unsigned int getDefaultAudioSampleRate() const { return m_defaultAudioSampleRate; }
DSPDeviceSourceEngine *addDeviceSourceEngine();
void removeLastDeviceSourceEngine();
@ -78,14 +78,11 @@ private:
std::vector<DSPDeviceSinkEngine*> m_deviceSinkEngines;
uint m_deviceSinkEnginesUIDSequence;
AudioDeviceManager m_audioDeviceManager;
AudioOutput m_audioOutput;
AudioInput m_audioInput;
uint m_audioOutputSampleRate;
uint m_audioInputSampleRate;
int m_audioInputDeviceIndex;
int m_audioOutputDeviceIndex;
QTimer m_masterTimer;
bool m_dvSerialSupport;
static const unsigned int m_defaultAudioSampleRate = 48000;
#ifdef DSD_USE_SERIALDV
DVSerialEngine m_dvSerialEngine;
#endif

Wyświetl plik

@ -26,7 +26,7 @@ AudioDialog::AudioDialog(AudioDeviceManager* audioDeviceManager, QWidget* parent
treeItem = new QTreeWidgetItem(ui->audioOutTree);
treeItem->setText(0, qPrintable(it->deviceName()));
if (i == m_audioDeviceManager->getOutputDeviceIndex())
if (i == 0)
{
ui->audioOutTree->setCurrentItem(treeItem);
}
@ -78,10 +78,8 @@ AudioDialog::~AudioDialog()
void AudioDialog::accept()
{
int inIndex = ui->audioInTree->indexOfTopLevelItem(ui->audioInTree->currentItem());
int outIndex = ui->audioOutTree->indexOfTopLevelItem(ui->audioOutTree->currentItem());
m_audioDeviceManager->m_inputDeviceIndex = inIndex - 1;
m_audioDeviceManager->m_outputDeviceIndex = outIndex - 1;
m_audioDeviceManager->m_inputVolume = m_inputVolume;
QDialog::accept();

Wyświetl plik

@ -236,7 +236,7 @@ int WebAPIAdapterGUI::instanceAudioGet(
response.setNbInputDevices(nbInputDevices);
response.setInputDeviceSelectedIndex(m_mainWindow.m_dspEngine->getAudioDeviceManager()->getInputDeviceIndex());
response.setNbOutputDevices(nbOutputDevices);
response.setOutputDeviceSelectedIndex(m_mainWindow.m_dspEngine->getAudioDeviceManager()->getOutputDeviceIndex());
response.setOutputDeviceSelectedIndex(-1); // FIXME: remove
response.setInputVolume(m_mainWindow.m_dspEngine->getAudioDeviceManager()->getInputVolume());
QList<SWGSDRangel::SWGAudioDevice*> *inputDevices = response.getInputDevices();
QList<SWGSDRangel::SWGAudioDevice*> *outputDevices = response.getOutputDevices();
@ -278,11 +278,10 @@ int WebAPIAdapterGUI::instanceAudioPatch(
m_mainWindow.m_dspEngine->getAudioDeviceManager()->setInputVolume(inputVolume);
m_mainWindow.m_dspEngine->getAudioDeviceManager()->setInputDeviceIndex(inputIndex);
m_mainWindow.m_dspEngine->getAudioDeviceManager()->setOutputDeviceIndex(outputIndex);
response.setInputVolume(m_mainWindow.m_dspEngine->getAudioDeviceManager()->getInputVolume());
response.setInputIndex(m_mainWindow.m_dspEngine->getAudioDeviceManager()->getInputDeviceIndex());
response.setOutputIndex(m_mainWindow.m_dspEngine->getAudioDeviceManager()->getOutputDeviceIndex());
response.setOutputIndex(-1); // FIXME: remove
return 200;
}

Wyświetl plik

@ -237,7 +237,7 @@ int WebAPIAdapterSrv::instanceAudioGet(
response.setNbInputDevices(nbInputDevices);
response.setInputDeviceSelectedIndex(m_mainCore.m_dspEngine->getAudioDeviceManager()->getInputDeviceIndex());
response.setNbOutputDevices(nbOutputDevices);
response.setOutputDeviceSelectedIndex(m_mainCore.m_dspEngine->getAudioDeviceManager()->getOutputDeviceIndex());
response.setOutputDeviceSelectedIndex(-1); // FIXME: remove
response.setInputVolume(m_mainCore.m_dspEngine->getAudioDeviceManager()->getInputVolume());
QList<SWGSDRangel::SWGAudioDevice*> *inputDevices = response.getInputDevices();
QList<SWGSDRangel::SWGAudioDevice*> *outputDevices = response.getOutputDevices();
@ -279,11 +279,10 @@ int WebAPIAdapterSrv::instanceAudioPatch(
m_mainCore.m_dspEngine->getAudioDeviceManager()->setInputVolume(inputVolume);
m_mainCore.m_dspEngine->getAudioDeviceManager()->setInputDeviceIndex(inputIndex);
m_mainCore.m_dspEngine->getAudioDeviceManager()->setOutputDeviceIndex(outputIndex);
response.setInputVolume(m_mainCore.m_dspEngine->getAudioDeviceManager()->getInputVolume());
response.setInputIndex(m_mainCore.m_dspEngine->getAudioDeviceManager()->getInputDeviceIndex());
response.setOutputIndex(m_mainCore.m_dspEngine->getAudioDeviceManager()->getOutputDeviceIndex());
response.setOutputIndex(-1); // FIXME: remove
return 200;
}