more Voice work

This commit is contained in:
Kae 2023-07-13 19:12:55 +10:00
parent c3bf7a3c87
commit 28f4204b09
7 changed files with 101 additions and 31 deletions

View File

@ -44,8 +44,15 @@ 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;

View File

@ -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;

View File

@ -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();

View File

@ -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})

View File

@ -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;
}
} }

View File

@ -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;
}; };
} }

View File

@ -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