refs #320 Voicechannel and audio device connections

- Methods to connect voice channel and audio devices
- Methods to connect audio devices with each other (loopback)
This commit is contained in:
Roland Winklmeier
2014-12-25 18:30:13 +01:00
parent 3126067d31
commit b6869affd5
6 changed files with 99 additions and 11 deletions

View File

@@ -23,6 +23,8 @@ Client::Client(QObject *parent) :
m_inputDevice = m_voice->createInputDevice();
m_outputDevice = m_voice->createOutputDevice();
m_voice->connectChannelOutputDevice(m_channelCom1.get(), m_outputDevice.get());
using namespace BlackCore;
connect(m_channelCom1.get(), &IVoiceChannel::connectionStatusChanged, this, &Client::connectionStatusChanged);
connect(m_channelCom1.get(), &IVoiceChannel::audioStarted, this, &Client::audioStartedStream);
@@ -163,15 +165,14 @@ void Client::listCallsignsCmd(QTextStream &args)
void Client::enableLoopbackCmd(QTextStream &/*args*/)
{
std::cout << "Enabling audio loopback." << std::endl;
m_voice->enableAudioLoopback(true);
m_voice->enableAudioLoopback(m_inputDevice.get(), m_outputDevice.get());
printLinePrefix();
}
void Client::disableLoopbackCmd(QTextStream &/*args*/)
{
std::cout << "Disabling audio loopback." << std::endl;
m_voice->enableAudioLoopback(false);
printLinePrefix();
m_voice->enableAudioLoopback(m_inputDevice.get(), nullptr);
printLinePrefix();
}

View File

@@ -39,6 +39,7 @@ namespace BlackCore
// 2. Register PTT hotkey function
m_inputManager = CInputManager::getInstance();
m_handlePtt = m_inputManager->registerHotkeyFunc(CHotkeyFunction::Ptt(), this, &CContextAudio::ps_setVoiceTransmission);
m_channelCom1 = m_voice->createVoiceChannel();
m_channelCom1->setMyAircraftCallsign(getIContextOwnAircraft()->getOwnAircraft().getCallsign());
@@ -50,6 +51,9 @@ namespace BlackCore
m_voiceInputDevice = m_voice->createInputDevice();
m_voiceOutputDevice = m_voice->createOutputDevice();
m_voice->connectChannelOutputDevice(m_channelCom1.get(), m_voiceOutputDevice.get());
m_voice->connectChannelOutputDevice(m_channelCom2.get(), m_voiceOutputDevice.get());
// 4. load sounds (init), not possible in own thread
QTimer::singleShot(10 * 1000, this, SLOT(ps_initNotificationSounds()));
}
@@ -401,7 +405,10 @@ namespace BlackCore
{
Q_ASSERT(this->m_voice);
CLogMessage(this, CLogCategory::contextSlot()).debug() << Q_FUNC_INFO;
m_voice->enableAudioLoopback(enable);
if (enable)
m_voice->enableAudioLoopback(m_voiceInputDevice.get(), m_voiceOutputDevice.get());
else
m_voice->enableAudioLoopback(m_voiceInputDevice.get(), nullptr);
}
bool CContextAudio::parseCommandLine(const QString &commandLine)
@@ -452,6 +459,13 @@ namespace BlackCore
return false;
}
void CContextAudio::ps_setVoiceTransmission(bool enable)
{
// FIXME: Use the 'active' channel instead of hardcoded COM1
if (enable) m_voice->connectChannelInputDevice(m_voiceInputDevice.get(), m_channelCom1.get());
else m_voice->connectChannelInputDevice(nullptr, m_channelCom1.get());
}
/*
* Connection status changed
*/

View File

@@ -157,6 +157,8 @@ namespace BlackCore
//! Init notification sounds
void ps_initNotificationSounds();
void ps_setVoiceTransmission(bool enable);
private:
const int MinUnmuteVolume = 20; //!< minimum volume when unmuted
const int VoiceRoomEnabledVolume = 95; //!< voice room volume when enabled

View File

@@ -47,11 +47,18 @@ namespace BlackCore
//! Create output device object
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() = 0;
//! Connect voice channel to an audio output device
virtual void connectChannelOutputDevice(IVoiceChannel *channel, IAudioOutputDevice *device) = 0;
/*!
* \brief Enable audio loopback to route recorded voice from microphone to speakers
* \param enable (default true)
* Connect input device to voice channel to start/stop voice transmission
* \param device Audio input device, e.g. a microphone. Pass nullptr to stop transmission
* \param channel Voice channel audio should be transmitted to
*/
virtual void enableAudioLoopback(bool enable = true) = 0;
virtual void connectChannelInputDevice(IAudioInputDevice *device, IVoiceChannel *channel) = 0;
//! Connect audio input to an audio output to hear your own voice
virtual void enableAudioLoopback(IAudioInputDevice *input, IAudioOutputDevice *output) = 0;
};
} // namespace BlackCore

View File

@@ -53,6 +53,67 @@ namespace BlackCore
return make_unique<CAudioOutputDeviceVatlib>(m_audioService.data(), this);
}
/* FIXME:
Can the following methods be more general somehow?
E.g.:
template <typename Input, typename Output>
connectVoice(Input input, Output output)
{
...
}
*/
void CVoiceVatlib::connectChannelOutputDevice(IVoiceChannel *channel, IAudioOutputDevice *device)
{
auto voiceChannelVatlib = qobject_cast<CVoiceChannelVatlib*>(channel);
Q_ASSERT_X(voiceChannelVatlib, "CVoiceVatlib::connectChannelOutputDevice", "No valid CVoiceChannelVatlib pointer.");
if (!device)
{
Vat_VoiceConnect(voiceChannelVatlib->getVoiceChannel(), 0, nullptr, 0);
return;
}
auto audioDeviceVatlib = qobject_cast<CAudioOutputDeviceVatlib*>(device);
Q_ASSERT_X(audioDeviceVatlib, "CVoiceVatlib::connectOutputDevice", "No valid CAudioOutputDeviceVatlib pointer.");
Vat_VoiceConnect(voiceChannelVatlib->getVoiceChannel(), 0, audioDeviceVatlib->getVatLocalOutputCodec(), 0);
}
void CVoiceVatlib::connectChannelInputDevice(IAudioInputDevice *device, IVoiceChannel *channel)
{
auto voiceChannelVatlib = qobject_cast<CVoiceChannelVatlib*>(channel);
Q_ASSERT_X(voiceChannelVatlib, "CVoiceVatlib::connectChannelInputDevice", "No valid CVoiceChannelVatlib pointer.");
if (!device)
{
Vat_VoiceConnect(voiceChannelVatlib->getVoiceChannel(), 0, nullptr, 0);
return;
}
auto audioDeviceVatlib = qobject_cast<CAudioInputDeviceVatlib*>(device);
Q_ASSERT_X(audioDeviceVatlib, "CVoiceVatlib::connectChannelInputDevice", "No valid CAudioInputDeviceVatlib pointer.");
Vat_VoiceConnect(audioDeviceVatlib->getVatLocalInputCodec(), 0, voiceChannelVatlib->getVoiceChannel(), 0);
}
void CVoiceVatlib::enableAudioLoopback(IAudioInputDevice *input, IAudioOutputDevice *output)
{
auto vatlibInput = qobject_cast<CAudioInputDeviceVatlib*>(input);
Q_ASSERT_X(vatlibInput, "CVoiceVatlib::enableAudioLoopback", "No valid CAudioInputDeviceVatlib pointer.");
if (!output)
{
Vat_VoiceConnect(vatlibInput->getVatLocalInputCodec(), 0, nullptr, 0);
return;
}
auto vatlibOutput = qobject_cast<CAudioOutputDeviceVatlib*>(output);
Q_ASSERT_X(vatlibOutput, "CVoiceVatlib::enableAudioLoopback", "No valid CAudioOutputDeviceVatlib pointer.");
Vat_VoiceConnect(vatlibInput->getVatLocalInputCodec(), 0, vatlibOutput->getVatLocalOutputCodec(), 0);
}
/*
* Process voice handling
*/

View File

@@ -50,9 +50,14 @@ namespace BlackCore
//! \copydoc IVoice::createOutputDevice()
virtual std::unique_ptr<IAudioOutputDevice> createOutputDevice() override;
//! \copydoc IVoice::enableAudioLoopback
virtual void enableAudioLoopback(bool enable = true) override;
//! \copydoc IVoice::connectChannelOutputDevice()
virtual void connectChannelOutputDevice(IVoiceChannel *channel, IAudioOutputDevice *device) override;
//! \copydoc IVoice::connectChannelInputDevice()
virtual void connectChannelInputDevice(IAudioInputDevice *device, IVoiceChannel *channel) override;
//! \copydoc IVoice::enableAudioLoopback()
virtual void enableAudioLoopback(IAudioInputDevice *input, IAudioOutputDevice *output) override;
protected: // QObject overrides
@@ -84,8 +89,6 @@ namespace BlackCore
QScopedPointer<VatAudioService_tag, VatAudioServiceDeleter> m_audioService;
QScopedPointer<VatUDPAudioPort_tag, VatUDPAudioPortDeleter> m_udpPort;
bool m_isAudioLoopbackEnabled; /*!< A flag whether audio loopback is enabled or not */
};
} // namespace