more Voice work
This commit is contained in:
parent
c3bf7a3c87
commit
28f4204b09
@ -44,9 +44,16 @@ public:
|
|||||||
virtual bool setCursorImage(const String& id, const ImageConstPtr& image, unsigned scale, const Vec2I& offset) = 0;
|
virtual bool setCursorImage(const String& id, const ImageConstPtr& image, unsigned scale, const Vec2I& offset) = 0;
|
||||||
virtual void setAcceptingTextInput(bool acceptingTextInput) = 0;
|
virtual void setAcceptingTextInput(bool acceptingTextInput) = 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
virtual AudioFormat enableAudio() = 0;
|
virtual AudioFormat enableAudio() = 0;
|
||||||
virtual void disableAudio() = 0;
|
virtual void disableAudio() = 0;
|
||||||
|
|
||||||
|
typedef void (__cdecl* AudioCallback)(void* userdata, uint8_t* stream, int len);
|
||||||
|
|
||||||
|
virtual bool openAudioInputDevice(const char* name, int freq, int channels, void* userdata, AudioCallback callback) = 0;
|
||||||
|
virtual bool closeAudioInputDevice() = 0;
|
||||||
|
|
||||||
virtual void setClipboard(String text) = 0;
|
virtual void setClipboard(String text) = 0;
|
||||||
virtual Maybe<String> getClipboard() = 0;
|
virtual Maybe<String> getClipboard() = 0;
|
||||||
|
|
||||||
|
@ -292,15 +292,15 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
SDL_AudioSpec obtained = {};
|
SDL_AudioSpec obtained = {};
|
||||||
m_sdlAudioDevice = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
|
m_sdlAudioOutputDevice = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
|
||||||
if (!m_sdlAudioDevice) {
|
if (!m_sdlAudioOutputDevice) {
|
||||||
Logger::error("Application: Could not open audio device, no sound available!");
|
Logger::error("Application: Could not open audio device, no sound available!");
|
||||||
} else if (obtained.freq != desired.freq || obtained.channels != desired.channels || obtained.format != desired.format) {
|
} else if (obtained.freq != desired.freq || obtained.channels != desired.channels || obtained.format != desired.format) {
|
||||||
SDL_CloseAudioDevice(m_sdlAudioDevice);
|
SDL_CloseAudioDevice(m_sdlAudioOutputDevice);
|
||||||
Logger::error("Application: Could not open 44.1khz / 16 bit stereo audio device, no sound available!");
|
Logger::error("Application: Could not open 44.1khz / 16 bit stereo audio device, no sound available!");
|
||||||
} else {
|
} else {
|
||||||
Logger::info("Application: Opened default audio device with 44.1khz / 16 bit stereo audio, {} sample size buffer", obtained.samples);
|
Logger::info("Application: Opened default audio device with 44.1khz / 16 bit stereo audio, {} sample size buffer", obtained.samples);
|
||||||
SDL_PauseAudioDevice(m_sdlAudioDevice, 0);
|
SDL_PauseAudioDevice(m_sdlAudioOutputDevice, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
m_renderer = make_shared<OpenGl20Renderer>();
|
m_renderer = make_shared<OpenGl20Renderer>();
|
||||||
@ -311,7 +311,10 @@ public:
|
|||||||
|
|
||||||
~SdlPlatform() {
|
~SdlPlatform() {
|
||||||
|
|
||||||
SDL_CloseAudioDevice(m_sdlAudioDevice);
|
if (m_sdlAudioOutputDevice)
|
||||||
|
SDL_CloseAudioDevice(m_sdlAudioOutputDevice);
|
||||||
|
|
||||||
|
closeAudioInputDevice();
|
||||||
|
|
||||||
m_renderer.reset();
|
m_renderer.reset();
|
||||||
|
|
||||||
@ -321,6 +324,32 @@ public:
|
|||||||
SDL_Quit();
|
SDL_Quit();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool openAudioInputDevice(const char* name, int freq, int channels, void* userdata, SDL_AudioCallback callback) {
|
||||||
|
SDL_AudioSpec desired = {};
|
||||||
|
desired.freq = freq;
|
||||||
|
desired.format = AUDIO_S16SYS;
|
||||||
|
desired.samples = 1024;
|
||||||
|
desired.channels = channels;
|
||||||
|
desired.userdata = userdata;
|
||||||
|
desired.callback = callback;
|
||||||
|
|
||||||
|
closeAudioInputDevice();
|
||||||
|
|
||||||
|
SDL_AudioSpec obtained = {};
|
||||||
|
return (m_sdlAudioInputDevice = SDL_OpenAudioDevice(name, 1, &desired, &obtained, 0)) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool closeAudioInputDevice() {
|
||||||
|
if (m_sdlAudioInputDevice) {
|
||||||
|
SDL_CloseAudioDevice(m_sdlAudioInputDevice);
|
||||||
|
m_sdlAudioInputDevice = 0;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
m_cursorCache.ptr(m_currentCursor);
|
m_cursorCache.ptr(m_currentCursor);
|
||||||
m_cursorCache.cleanup();
|
m_cursorCache.cleanup();
|
||||||
@ -397,7 +426,7 @@ public:
|
|||||||
Logger::error("Application: threw exception during shutdown: {}", outputException(e, true));
|
Logger::error("Application: threw exception during shutdown: {}", outputException(e, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_CloseAudioDevice(m_sdlAudioDevice);
|
SDL_CloseAudioDevice(m_sdlAudioOutputDevice);
|
||||||
m_SdlControllers.clear();
|
m_SdlControllers.clear();
|
||||||
|
|
||||||
SDL_SetCursor(NULL);
|
SDL_SetCursor(NULL);
|
||||||
@ -569,6 +598,14 @@ private:
|
|||||||
SDL_PauseAudio(true);
|
SDL_PauseAudio(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool openAudioInputDevice(const char* name, int freq, int channels, void* userdata, AudioCallback callback) override {
|
||||||
|
return parent->openAudioInputDevice(name, freq, channels, userdata, callback);
|
||||||
|
};
|
||||||
|
|
||||||
|
bool closeAudioInputDevice() override {
|
||||||
|
return parent->closeAudioInputDevice();
|
||||||
|
};
|
||||||
|
|
||||||
float updateRate() const override {
|
float updateRate() const override {
|
||||||
return parent->m_updateRate;
|
return parent->m_updateRate;
|
||||||
}
|
}
|
||||||
@ -803,7 +840,8 @@ private:
|
|||||||
|
|
||||||
SDL_Window* m_sdlWindow = nullptr;
|
SDL_Window* m_sdlWindow = nullptr;
|
||||||
SDL_GLContext m_sdlGlContext = nullptr;
|
SDL_GLContext m_sdlGlContext = nullptr;
|
||||||
SDL_AudioDeviceID m_sdlAudioDevice = 0;
|
SDL_AudioDeviceID m_sdlAudioOutputDevice = 0;
|
||||||
|
SDL_AudioDeviceID m_sdlAudioInputDevice = 0;
|
||||||
|
|
||||||
typedef std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> SDLGameControllerUPtr;
|
typedef std::unique_ptr<SDL_GameController, decltype(&SDL_GameControllerClose)> SDLGameControllerUPtr;
|
||||||
StableHashMap<int, SDLGameControllerUPtr> m_SdlControllers;
|
StableHashMap<int, SDLGameControllerUPtr> m_SdlControllers;
|
||||||
|
@ -174,7 +174,7 @@ void ClientApplication::applicationInit(ApplicationControllerPtr appController)
|
|||||||
|
|
||||||
m_guiContext = make_shared<GuiContext>(m_mainMixer->mixer(), appController);
|
m_guiContext = make_shared<GuiContext>(m_mainMixer->mixer(), appController);
|
||||||
m_input = make_shared<Input>();
|
m_input = make_shared<Input>();
|
||||||
m_voice = make_shared<Voice>();
|
m_voice = make_shared<Voice>(appController);
|
||||||
|
|
||||||
auto configuration = m_root->configuration();
|
auto configuration = m_root->configuration();
|
||||||
bool vsync = configuration->get("vsync").toBool();
|
bool vsync = configuration->get("vsync").toBool();
|
||||||
|
@ -56,6 +56,7 @@ SET (star_frontend_HEADERS
|
|||||||
StarStatusPane.hpp
|
StarStatusPane.hpp
|
||||||
StarTeleportDialog.hpp
|
StarTeleportDialog.hpp
|
||||||
StarWireInterface.hpp
|
StarWireInterface.hpp
|
||||||
|
StarVoice.hpp
|
||||||
)
|
)
|
||||||
|
|
||||||
SET (star_frontend_SOURCES
|
SET (star_frontend_SOURCES
|
||||||
@ -104,6 +105,7 @@ SET (star_frontend_SOURCES
|
|||||||
StarStatusPane.cpp
|
StarStatusPane.cpp
|
||||||
StarTeleportDialog.cpp
|
StarTeleportDialog.cpp
|
||||||
StarWireInterface.cpp
|
StarWireInterface.cpp
|
||||||
|
StarVoice.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
ADD_LIBRARY (star_frontend OBJECT ${star_frontend_SOURCES} ${star_frontend_HEADERS})
|
ADD_LIBRARY (star_frontend OBJECT ${star_frontend_SOURCES} ${star_frontend_HEADERS})
|
||||||
|
@ -1,23 +1,10 @@
|
|||||||
#include "StarVoice.hpp"
|
#include "StarVoice.hpp"
|
||||||
#include "StarFormat.hpp"
|
#include "StarFormat.hpp"
|
||||||
|
#include "StarApplicationController.hpp"
|
||||||
#include "opus/include/opus.h"
|
#include "opus/include/opus.h"
|
||||||
|
|
||||||
#include "SDL.h"
|
#include "SDL.h"
|
||||||
|
|
||||||
namespace Star {
|
|
||||||
|
|
||||||
EnumMap<VoiceTriggerMode> const VoiceTriggerModeNames{
|
|
||||||
{VoiceTriggerMode::VoiceActivity, "VoiceActivity"},
|
|
||||||
{VoiceTriggerMode::PushToTalk, "PushToTalk"}
|
|
||||||
};
|
|
||||||
|
|
||||||
EnumMap<VoiceChannelMode> const VoiceChannelModeNames{
|
|
||||||
{VoiceChannelMode::Mono, "Mono"},
|
|
||||||
{VoiceChannelMode::Stereo, "Stereo"}
|
|
||||||
};
|
|
||||||
|
|
||||||
static SDL_AudioDeviceID sdlInputDevice = 0;
|
|
||||||
|
|
||||||
constexpr int VOICE_SAMPLE_RATE = 48000;
|
constexpr int VOICE_SAMPLE_RATE = 48000;
|
||||||
constexpr int VOICE_FRAME_SIZE = 960;
|
constexpr int VOICE_FRAME_SIZE = 960;
|
||||||
|
|
||||||
@ -26,6 +13,18 @@ constexpr int VOICE_MAX_PACKET_SIZE = 3 * 1276;
|
|||||||
|
|
||||||
constexpr uint16_t VOICE_VERSION = 1;
|
constexpr uint16_t VOICE_VERSION = 1;
|
||||||
|
|
||||||
|
namespace Star {
|
||||||
|
|
||||||
|
EnumMap<VoiceInputMode> const VoiceInputModeNames{
|
||||||
|
{VoiceInputMode::VoiceActivity, "VoiceActivity"},
|
||||||
|
{VoiceInputMode::PushToTalk, "PushToTalk"}
|
||||||
|
};
|
||||||
|
|
||||||
|
EnumMap<VoiceChannelMode> const VoiceChannelModeNames{
|
||||||
|
{VoiceChannelMode::Mono, "Mono"},
|
||||||
|
{VoiceChannelMode::Stereo, "Stereo"}
|
||||||
|
};
|
||||||
|
|
||||||
Voice::Speaker::Speaker(SpeakerId id)
|
Voice::Speaker::Speaker(SpeakerId id)
|
||||||
: decoderMono (createDecoder(1), opus_decoder_destroy)
|
: decoderMono (createDecoder(1), opus_decoder_destroy)
|
||||||
, decoderStereo(createDecoder(2), opus_decoder_destroy) {
|
, decoderStereo(createDecoder(2), opus_decoder_destroy) {
|
||||||
@ -45,13 +44,14 @@ Voice& Voice::singleton() {
|
|||||||
return *s_singleton;
|
return *s_singleton;
|
||||||
}
|
}
|
||||||
|
|
||||||
Voice::Voice() : m_encoder(nullptr, opus_encoder_destroy) {
|
Voice::Voice(ApplicationControllerPtr appController) : m_encoder(nullptr, opus_encoder_destroy) {
|
||||||
if (s_singleton)
|
if (s_singleton)
|
||||||
throw VoiceException("Singleton Voice has been constructed twice");
|
throw VoiceException("Singleton Voice has been constructed twice");
|
||||||
|
|
||||||
m_clientSpeaker = make_shared<Speaker>(m_speakerId);
|
m_clientSpeaker = make_shared<Speaker>(m_speakerId);
|
||||||
m_triggerMode = VoiceTriggerMode::PushToTalk;
|
m_inputMode = VoiceInputMode::PushToTalk;
|
||||||
m_channelMode = VoiceChannelMode::Mono;
|
m_channelMode = VoiceChannelMode::Mono;
|
||||||
|
m_applicationController = appController;
|
||||||
|
|
||||||
resetEncoder();
|
resetEncoder();
|
||||||
s_singleton = this;
|
s_singleton = this;
|
||||||
@ -128,4 +128,19 @@ void Voice::resetEncoder() {
|
|||||||
opus_encoder_ctl(m_encoder.get(), OPUS_SET_BITRATE(channels == 2 ? 50000 : 24000));
|
opus_encoder_ctl(m_encoder.get(), OPUS_SET_BITRATE(channels == 2 ? 50000 : 24000));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Voice::openDevice() {
|
||||||
|
closeDevice();
|
||||||
|
|
||||||
|
m_deviceOpen = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Voice::closeDevice() {
|
||||||
|
if (!m_deviceOpen)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_applicationController->closeAudioInputDevice();
|
||||||
|
|
||||||
|
m_deviceOpen = false;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
@ -2,8 +2,10 @@
|
|||||||
#define STAR_VOICE_HPP
|
#define STAR_VOICE_HPP
|
||||||
#include "StarJson.hpp"
|
#include "StarJson.hpp"
|
||||||
#include "StarBiMap.hpp"
|
#include "StarBiMap.hpp"
|
||||||
#include "StarGameTypes.hpp"
|
|
||||||
#include "StarException.hpp"
|
#include "StarException.hpp"
|
||||||
|
#include "StarGameTypes.hpp"
|
||||||
|
#include "StarMaybe.hpp"
|
||||||
|
#include "StarApplicationController.hpp"
|
||||||
|
|
||||||
struct OpusDecoder;
|
struct OpusDecoder;
|
||||||
typedef std::unique_ptr<OpusDecoder, void(*)(OpusDecoder*)> OpusDecoderPtr;
|
typedef std::unique_ptr<OpusDecoder, void(*)(OpusDecoder*)> OpusDecoderPtr;
|
||||||
@ -14,13 +16,14 @@ namespace Star {
|
|||||||
|
|
||||||
STAR_EXCEPTION(VoiceException, StarException);
|
STAR_EXCEPTION(VoiceException, StarException);
|
||||||
|
|
||||||
enum class VoiceTriggerMode : uint8_t { VoiceActivity, PushToTalk };
|
enum class VoiceInputMode : uint8_t { VoiceActivity, PushToTalk };
|
||||||
extern EnumMap<VoiceTriggerMode> const VoiceTriggerModeNames;
|
extern EnumMap<VoiceInputMode> const VoiceInputModeNames;
|
||||||
|
|
||||||
enum class VoiceChannelMode: uint8_t { Mono = 1, Stereo = 2 };
|
enum class VoiceChannelMode: uint8_t { Mono = 1, Stereo = 2 };
|
||||||
extern EnumMap<VoiceChannelMode> const VoiceChannelModeNames;
|
extern EnumMap<VoiceChannelMode> const VoiceChannelModeNames;
|
||||||
|
|
||||||
STAR_CLASS(Voice);
|
STAR_CLASS(Voice);
|
||||||
|
STAR_CLASS(ApplicationController);
|
||||||
|
|
||||||
class Voice {
|
class Voice {
|
||||||
public:
|
public:
|
||||||
@ -30,6 +33,7 @@ public:
|
|||||||
struct Speaker {
|
struct Speaker {
|
||||||
SpeakerId speakerId = 0;
|
SpeakerId speakerId = 0;
|
||||||
EntityId entityId = 0;
|
EntityId entityId = 0;
|
||||||
|
|
||||||
Vec2F position = Vec2F();
|
Vec2F position = Vec2F();
|
||||||
String name = "Unnamed";
|
String name = "Unnamed";
|
||||||
|
|
||||||
@ -53,7 +57,7 @@ public:
|
|||||||
// is not initialized.
|
// is not initialized.
|
||||||
static Voice& singleton();
|
static Voice& singleton();
|
||||||
|
|
||||||
Voice();
|
Voice(ApplicationControllerPtr appController);
|
||||||
~Voice();
|
~Voice();
|
||||||
|
|
||||||
Voice(Voice const&) = delete;
|
Voice(Voice const&) = delete;
|
||||||
@ -81,6 +85,8 @@ private:
|
|||||||
static OpusDecoder* createDecoder(int channels);
|
static OpusDecoder* createDecoder(int channels);
|
||||||
static OpusEncoder* createEncoder(int channels);
|
static OpusEncoder* createEncoder(int channels);
|
||||||
void resetEncoder();
|
void resetEncoder();
|
||||||
|
void openDevice();
|
||||||
|
void closeDevice();
|
||||||
|
|
||||||
SpeakerId m_speakerId = 0;
|
SpeakerId m_speakerId = 0;
|
||||||
SpeakerPtr m_clientSpeaker;
|
SpeakerPtr m_clientSpeaker;
|
||||||
@ -90,8 +96,12 @@ private:
|
|||||||
|
|
||||||
OpusEncoderPtr m_encoder;
|
OpusEncoderPtr m_encoder;
|
||||||
|
|
||||||
VoiceTriggerMode m_triggerMode;
|
bool m_deviceOpen = false;
|
||||||
|
Maybe<String> m_deviceName;
|
||||||
|
VoiceInputMode m_inputMode;
|
||||||
VoiceChannelMode m_channelMode;
|
VoiceChannelMode m_channelMode;
|
||||||
|
|
||||||
|
ApplicationControllerPtr m_applicationController;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
@ -156,7 +156,6 @@ SET (star_game_HEADERS
|
|||||||
StarVehicle.hpp
|
StarVehicle.hpp
|
||||||
StarVehicleDatabase.hpp
|
StarVehicleDatabase.hpp
|
||||||
StarVersioningDatabase.hpp
|
StarVersioningDatabase.hpp
|
||||||
StarVoice.hpp
|
|
||||||
StarWarping.hpp
|
StarWarping.hpp
|
||||||
StarWeather.hpp
|
StarWeather.hpp
|
||||||
StarWeatherTypes.hpp
|
StarWeatherTypes.hpp
|
||||||
@ -415,7 +414,6 @@ SET (star_game_SOURCES
|
|||||||
StarVehicle.cpp
|
StarVehicle.cpp
|
||||||
StarVehicleDatabase.cpp
|
StarVehicleDatabase.cpp
|
||||||
StarVersioningDatabase.cpp
|
StarVersioningDatabase.cpp
|
||||||
StarVoice.cpp
|
|
||||||
StarWarping.cpp
|
StarWarping.cpp
|
||||||
StarWeather.cpp
|
StarWeather.cpp
|
||||||
StarWeatherTypes.cpp
|
StarWeatherTypes.cpp
|
||||||
|
Loading…
Reference in New Issue
Block a user